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

//**************************************************************************/



#include "SampleViewportFilter.h"

#include <QtCore/QDir>



#define _USE_MATH_DEFINES

#include <cmath>



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()->HUDMessageShow("Failed to load Blur.cg", Kernel::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;

    };

};