hwRenderPostEffect/hwRenderPostEffect.cpp

hwRenderPostEffect/hwRenderPostEffect.cpp
//-
// ==========================================================================
// Copyright 2015 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.
// Simple operations such as inverting the image and adding color triangles to the view
// are performed by this plug-in.
//
// To use this shader, load the plug-in and turn on the Legacy High Quality Viewport.
//
#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 <maya/MGL.h>
#include <stdio.h>
class hwRenderEffect : public MDrawProcedureBase
{
public:
hwRenderEffect();
virtual ~hwRenderEffect();
virtual bool execute();
static void deleteEffect( hwRenderEffect * ePtr);
static MDrawProcedureBase *createEffect( const MString &name,
hwRenderEffect *ePtr,
};
hwRenderEffect::hwRenderEffect()
{
}
hwRenderEffect::~hwRenderEffect()
{
// No-op
}
void
hwRenderEffect::deleteEffect( hwRenderEffect * ePtr)
{
if (ePtr)
{
MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
if (pRenderer)
{
const MString & backEndStr = pRenderer->backEndString();
pRenderer->removeDrawProcedure( backEndStr, ePtr, ePtr->mLocation );
cout<<"Call hwRenderEffect::deleteEffect("<<ePtr->fName.asChar()
<<") loc("<<ePtr->mLocation
<<") = "<<result<<endl;
}
delete ePtr;
ePtr = 0;
}
}
/*static*/
hwRenderEffect::createEffect( const MString &name,
hwRenderEffect *ePtr,
{
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();
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;
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;
{
data_type = GL_UNSIGNED_BYTE;
format = GL_RGBA;
pixels = new unsigned char[totalSize];
}
#ifdef _SUPPORT_16_FLOAT_
{
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)
{
{
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 ) ||
{
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 )
{
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 )
{
// 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;
}