- Main Page
- Related Pages
- Modules
- Classes
- Examples

# hwRenderPostEffect.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,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:
    //      This is an example of adding processing
    //      effects to the hardware renderer.
    //

    #ifdef WIN32
    #pragma warning( disable : 4786 )       // Disable STL warnings.
    #endif

    #include <maya/MIOStream.h>
    #include <maya/MString.h>
    #include <maya/MPlug.h>
    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>
    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFloatVector.h>
    #include <maya/MFnPlugin.h>

    #include <maya/MDrawProcedureBase.h>
    #include <maya/MHardwareRenderer.h>

    #include <stdio.h>

    #if defined(OSMac_MachO_)
    #include <OpenGL/gl.h>
    #include <OpenGL/glu.h>
    #else
    #include <GL/gl.h>
    #include <GL/glu.h>
    #endif

    class hwRenderEffect : public MDrawProcedureBase
    {
    public:
                        hwRenderEffect();
        virtual         ~hwRenderEffect();

        virtual bool execute();

        static void deleteEffect( hwRenderEffect * ePtr);
        static MDrawProcedureBase *createEffect( const MString &name,
                                hwRenderEffect *ePtr,
                                MHardwareRenderer::CallLocation location);

        MHardwareRenderer::CallLocation mLocation;
    };

    hwRenderEffect::hwRenderEffect()
    {
    }

    hwRenderEffect::~hwRenderEffect()
    {
        // No-op
    }

    void
    hwRenderEffect::deleteEffect( hwRenderEffect * ePtr)
    {
        if (ePtr)
        {
            MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
            if (pRenderer)
            {
                const MString & backEndStr = pRenderer->backEndString();
                MHardwareRenderer::DrawProcedureStatusCode result =
                    pRenderer->removeDrawProcedure( backEndStr, ePtr, ePtr->mLocation );
                cout<<"Call hwRenderEffect::deleteEffect("<<ePtr->fName.asChar()
                    <<") loc("<<ePtr->mLocation
                    <<") = "<<result<<endl;
            }
            delete ePtr;
            ePtr = 0;
        }
    }

    /*static*/
    MDrawProcedureBase *
    hwRenderEffect::createEffect( const MString &name,
                                hwRenderEffect *ePtr,
                                MHardwareRenderer::CallLocation location)
    {
        MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
        if (pRenderer)
        {
            if (!ePtr)
            {
                ePtr = new hwRenderEffect();
                ePtr->setEnabled( true );
                ePtr->setName( name );
                ePtr->mLocation = location;

                const MString & backEndStr = pRenderer->backEndString();
                MHardwareRenderer::DrawProcedureStatusCode result =
                    pRenderer->addDrawProcedure( backEndStr, ePtr, location );
                cout<<"Call hwRenderEffect::createEffect("<<ePtr->name().asChar()
                    <<") loc("<<ePtr->mLocation
                    <<") = "<<result<<endl;
            }
        }
        return (MDrawProcedureBase *)ePtr;
    }

    /* virtual */
    bool
    hwRenderEffect::execute()
    {
        MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
        if (!pRenderer)
            return false;

        const MString & backEndStr = pRenderer->backEndString();
        unsigned int width = 0, height = 0;

        MStatus stat =
            pRenderer->getBufferSize( backEndStr, width, height );
        if (width <= 0 || height <= 0)
            return false;

        unsigned int exposureNum;
        unsigned int totalExposureCount;
        pRenderer->getCurrentExposureNumber( backEndStr, exposureNum );
        pRenderer->getTotalExposureCount( backEndStr, totalExposureCount );

        // Perform some post-rendering. Invert the image.
        bool xxxx = true;
        if ( xxxx && mLocation == MHardwareRenderer::kPostRendering )
        {
            cout<<"Call EXP["<<exposureNum<<"/"<<totalExposureCount
                <<"] hwRenderEffect::execute("<<width<<", "<<height
                <<") -- "<<fName.asChar()<<endl;

            MHardwareRenderer::BufferPixelFormat colFmt;
            stat = pRenderer->getColorBufferPixelFormat( backEndStr, colFmt );
            void *pixels = 0;
            unsigned int data_type = GL_UNSIGNED_BYTE;
            unsigned int format = GL_RGBA;

            unsigned int totalSize = width*height*4;

            if (totalSize == 0)
                return false;

            if (colFmt == MHardwareRenderer::kRGBA_Fix8)
            {
                data_type = GL_UNSIGNED_BYTE;
                format = GL_RGBA;
                pixels = new unsigned char[totalSize];
            }
    #ifdef _SUPPORT_16_FLOAT_
            else if (MHardwareRenderer::kRGBA_Float16)
            {
                data_type = GL_HALF_FLOAT;
                format = GL_RGBA;
                pixels = new half[totalSize];
            }
    #endif
            glPushAttrib(GL_ALL_ATTRIB_BITS);

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            glPixelZoom( 1.0f, 1.0f );
            glPixelStorei(GL_PACK_ALIGNMENT, 1);
            glReadPixels(0, 0, width, height, format, data_type, pixels);

            unsigned char *pixelPtr = (unsigned char*)pixels;
            if (pixelPtr)
            {
                unsigned int numPixels = width * height;
                for (unsigned int i=0; i < numPixels; i++)
                {
                    *pixelPtr = (255 - *pixelPtr);
                    pixelPtr++;
                    *pixelPtr = (255 - *pixelPtr);
                    pixelPtr++;
                    *pixelPtr = (255 - *pixelPtr);
                    pixelPtr++;
                    *pixelPtr = 255;
                    pixelPtr++;
                }
            }

            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
            glRasterPos2i( -1, -1 );

            // We only want to clobber RGB. Leave alpha as is.
            glColorMask( 1, 1, 1, 0 );

            // For orthographic views, we need to make sure that depth
            // test is disabled, otherwise the pixels will not draw.
            glDisable(GL_DEPTH_TEST);

            glDrawPixels(width, height, format, data_type, pixels);

            if (pixels)
            {
                if (colFmt == MHardwareRenderer::kRGBA_Fix8)
                {
                    unsigned char *pixelPtr2 = (unsigned char*)pixels;
                    delete[] pixelPtr2;
                }
    #ifdef _SUPPORT_16_FLOAT_
                else
                {
                    half pixelPtr2 = (half*)pixels;
                    delete[] pixelPtr2;
                }
    #endif
            }

            glPopAttrib();
        }
        else
        {
            // Perform some pre-rendering, pre-exposure. Draw coloured
            // triangles.
            if ( (mLocation == MHardwareRenderer::kPreRendering ) ||
                 ( mLocation == MHardwareRenderer::kPreExposure) )
            {
                cout<<"Call EXP["<<exposureNum<<"/"<<totalExposureCount
                    <<"] hwRenderEffect::execute("<<width<<", "<<height
                    <<") -- "<<fName.asChar()<<endl;

                glPushAttrib(GL_ALL_ATTRIB_BITS);

                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();

                glShadeModel(GL_SMOOTH);
                glDisable(GL_DEPTH_TEST);
                glEnable(GL_BLEND);
                glBlendFunc(GL_ONE, GL_ZERO);

                glColorMask( 1, 1, 1, 0 );
                glBegin(GL_QUADS);
                glColor4f(1.0f,1.0f,1.0f,0.5f);
                glVertex3f( -1.0f, 1.0f, 0.0f);
                glColor4f(0.0f,1.0f,1.0f,0.5f);
                glVertex3f( 0.0f, 1.0f, 0.0f);
                glColor4f(0.0f,1.0f,1.0f,0.5f);
                glVertex3f(-1.0f,-1.0f, 0.0f);
                glColor4f(1.0f,0.0f,1.0f,0.5f);
                glVertex3f( 1.0f,-1.0f, 0.0f);
                glEnd();

                glEnable(GL_DEPTH_TEST);
                glDisable(GL_BLEND);

                glPopAttrib();

            }

            // Do some post exposure. Nothing for now...
            else if ( mLocation == MHardwareRenderer::kPostExposure )
            {
                cout<<"Call EXP["<<exposureNum<<"/"<<totalExposureCount
                    <<"] hwRenderEffect::execute("<<width<<", "<<height<<") -- POST-EXPOSURE"<<endl;
            }
        }

        return true;
    }

    // Four callback classes.
    static hwRenderEffect *fsPreRender = 0;
    static hwRenderEffect *fsPreExposure = 0;
    static hwRenderEffect *fsPostExposure = 0;
    static hwRenderEffect *fsPostRender = 0;

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status = MS::kSuccess;

        MFnPlugin plugin( obj, PLUGIN_COMPANY, "7.0", "Any");

        // Register the callbacks.
        fsPreRender = (hwRenderEffect *)hwRenderEffect::createEffect(MString("PRE-RENDER"), fsPreRender, MHardwareRenderer::kPreRendering );
        fsPreExposure = (hwRenderEffect *)hwRenderEffect::createEffect(MString("PRE-EXPOSURE"), fsPreExposure, MHardwareRenderer::kPreExposure );
        fsPostExposure = (hwRenderEffect *)hwRenderEffect::createEffect(MString("POST-EXPOSURE"), fsPostExposure, MHardwareRenderer::kPostExposure );
        fsPostRender = (hwRenderEffect *)hwRenderEffect::createEffect(MString("POST-RENDER"), fsPostRender, MHardwareRenderer::kPostRendering );
        return status;
    }

    MStatus uninitializePlugin( MObject obj )
    {
        MStatus   status = MS::kSuccess;

        // Unregister the callbacks.
        hwRenderEffect::deleteEffect(fsPreRender);
        fsPreRender = 0;
        hwRenderEffect::deleteEffect(fsPreExposure);
        fsPreExposure = 0;
        hwRenderEffect::deleteEffect(fsPostExposure);
        fsPostExposure = 0;
        hwRenderEffect::deleteEffect(fsPostRender);
        fsPostRender = 0;

        MFnPlugin plugin( obj );

        return status;
    }