- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

# SampleViewportFilter/SampleViewportFilter.cpp

    //**************************************************************************/
    // Copyright (c) 2008 Autodesk, Inc.
    // All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk license
    // agreement provided at the time of installation or download, or which
    // otherwise accompanies this software in either electronic or hard copy form.
    //
    //**************************************************************************/
    // DESCRIPTION:
    // CREATED: October 2008
    //**************************************************************************/
    #define _USE_MATH_DEFINES
    #include <cmath>

    #include "SampleViewportFilter.h"

    #include <QtCore/QDir>

    using namespace mudbox;

    // Filter plugin macros
    IMPLEMENT_VCLASS( SampleViewPortFilter, ViewPortFilter, "Sample Viewport Filter", 1 );

    MB_PLUGIN( "Sample Filter", "Sample Viewport Filter", "Autodesk", "http://www.mudbox3d.com", 0 );

    // Render texture to screen to activate shaders.

    static void drawFullScreenQuad() {
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        glBegin( GL_QUADS );

        glTexCoord2f( 0, 0 );
        glVertex2f( -1, -1 );

        glTexCoord2f( 1, 0 );
        glVertex2f( 1, -1 );

        glTexCoord2f( 1, 1 );
        glVertex2f( 1, 1 );

        glTexCoord2f( 0, 1 );
        glVertex2f( -1, 1 );

        glEnd();
    }

    // Renders full screens quad to texture specified
    static void gpuTransform(Texture* const outputTexture) {
        outputTexture->SetAsRenderTarget();
        drawFullScreenQuad();
        outputTexture->RestoreRenderTarget();
    }

    void SampleViewPortFilter::OnNodeEvent( const Attribute &cAttribute, NodeEventType eType ) {
        if(eType == etValueChanged) {
            {
                Kernel()->Redraw();
            }
        }
    }

    SampleViewPortFilter::SampleViewPortFilter() :
        m_aGaussianBlur(this, "Gaussian"),
        m_aBlurWidth(this, "Blur Width")
    {
        // Cg context
        m_CGContext = cgCreateContext();
        cgGLSetDebugMode( CG_FALSE );

        cgGLSetManageTextureParameters(m_CGContext, CG_TRUE);
        cgSetParameterSettingMode(m_CGContext, CG_DEFERRED_PARAMETER_SETTING);

        /* Compile and load the vertex program. */
        m_FragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
        cgGLSetOptimalOptions(m_FragmentProfile);

        // Get the path to where the plug-in was loaded from
        QDir pluginDir( Kernel()->PluginDirectory("Sample Filter") );
        QFileInfo cgPath( pluginDir, QString("Blur.cg") );

        /* Compile and load the fragment program. */
        QByteArray qbaPath = QFile::encodeName(cgPath.filePath());
        m_BlurProgram =
            cgCreateProgramFromFile(
            m_CGContext,                /* Cg runtime context */
            CG_SOURCE,                  /* Program in human-readable form */
            qbaPath.constData(), /* Name of file containing program */
            m_FragmentProfile,/* Profile: OpenGL ARB vertex program */
            "main",      /* Entry function name */
            NULL);                      /* No extra compiler options */

        if ( m_BlurProgram == NULL ) Kernel()->Interface()->HUDMessageShow("Failed to load Blur.cg", mudbox::Interface::HUDmsgFade );

        cgGLLoadProgram(m_BlurProgram);

        m_BlurColorTextureParam = cgGetNamedParameter(m_BlurProgram, "colorTexture");
        m_BlurWidthParam = cgGetNamedParameter(m_BlurProgram, "BlurWidth");
        m_GaussianBlurParam = cgGetNamedParameter(m_BlurProgram, "GaussianBlur");

        m_aGaussianBlur = true;

        m_aBlurWidth.SetMax(.0050f);
        m_aBlurWidth.SetMin(.0001f);
        m_aBlurWidth = 0.0012f;

        // Create the output texture
        m_pResultTexture = CreateInstance<Texture>();
    }

    SampleViewPortFilter::~SampleViewPortFilter()
    {
        if( m_pResultTexture )
            delete m_pResultTexture;

        if (m_CGContext)
            cgDestroyContext(m_CGContext);
    };

    void SampleViewPortFilter::Process( ViewPortState &s )
    {
        enum Image::Format eFormat = s.m_bHDRNeeded ? Image::e16float : Image::e8integer;

        // Set of variables not actually used for anything other than to show
        // how to access the values.
        const float cameraNear = Kernel()->Scene()->ActiveCamera()->Near();
        const float cameraFar = Kernel()->Scene()->ActiveCamera()->Far();
        const float cameraFOV = Kernel()->Scene()->ActiveCamera()->FOV();
        const float cameraAspectRatio = Kernel()->Scene()->ActiveCamera()->AspectRatio();
        const float cameraHeight = tanf(cameraFOV / 2.0f) * cameraNear;
        const float cameraWidth = cameraHeight * cameraAspectRatio;
        const float cameraTop = -cameraHeight;
        const float cameraBottom = cameraHeight;
        const float cameraLeft = -cameraWidth;
        const float cameraRight = cameraWidth;

        // Ensure our output texture is same size & type as the incoming color buffer.
        // Get width and height of the viewport
        const int width = s.m_pColor->Width();
        const int height = s.m_pColor->Height();

        // Smallest of width and height
        const int extendMin = width < height ? width : height;

        // Logarithm of the SMALLER extend, in order to be at least 1 pixel in size in any dimension
        const int levelCountMax = (int)floorf(logf(float(extendMin)) / float(M_LN2));

        // See if the input size or format changed. If so, re-create the texture.
        if( m_pResultTexture->Width() != s.m_pColor->Width() ||
            m_pResultTexture->Height() != s.m_pColor->Height())
        {
            m_pResultTexture->Create(s.m_pColor->Width(), s.m_pColor->Height(), 4, eFormat);
        };
        m_pResultTexture->SetLocation( TexturePool::locationGPU );

        // Enable Cg fragment profile
        cgGLEnableProfile(m_FragmentProfile);

        // Set up some gl states
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_BLEND);
        glDisable(GL_CULL_FACE);

        cgGLBindProgram(m_BlurProgram);

        // Set the incoming color buffer on the shader
        cgGLSetTextureParameter(m_BlurColorTextureParam, s.m_pColor->OpenGLName());

        // Set blur width value
        cgSetParameter1f(m_BlurWidthParam, m_aBlurWidth);

        // Set Gaussian usage value
        cgSetParameter1i(m_GaussianBlurParam, m_aGaussianBlur);

        cgUpdateProgramParameters(m_BlurProgram);

        // Render to the resulting texture.  This activates the shader pass.
        gpuTransform(m_pResultTexture);

        cgGLDisableProfile(m_FragmentProfile);

        // Assign the resulting texture to the color buffer
        s.m_pColor = m_pResultTexture;
    };

    void SampleViewPortFilter::SetVisible( bool bVisible )
    {
        ViewPortFilter::SetVisible( bVisible );

        if( bVisible )
        {
            if( !m_pResultTexture )
                m_pResultTexture = CreateInstance<Texture>();
        }
        else
        {
            delete m_pResultTexture;
            m_pResultTexture = 0;
        };
    };