C++ API Reference
viewRenderOverride/viewRenderOverrideOperations.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.
//+
#include <stdio.h>
#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/M3dView.h>
#include <maya/MPoint.h>
#include <maya/MImage.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MRenderTargetManager.h>
#include <maya/MStateManager.h>
#include <maya/MShaderManager.h>
#include <maya/MTextureManager.h>
#include <maya/MDrawContext.h>
#include "viewRenderOverride.h"
/*
Utilty to print out lighting information from a draw context
*/
void viewRenderOverrideUtilities::printDrawContextLightInfo( const MHWRender::MDrawContext & drawContext )
{
// Get all the lighting information in the scene
unsigned int lightCount = drawContext.numberOfActiveLights(considerAllSceneLights);
if (!lightCount)
return;
MFloatPointArray positions;
MFloatPoint position;
MFloatVector direction;
MColor color;
unsigned int positionCount = 0;
position[0] = position[1] = position[2] = 0.0f;
for (unsigned int i=0; i<lightCount; i++)
{
MHWRender::MLightParameterInformation *lightParam = drawContext.getLightParameterInformation( i, considerAllSceneLights );
if (lightParam)
{
printf("\tLight %d\n\t{\n", i);
MStringArray params;
lightParam->parameterList(params);
for (unsigned int p=0; p<params.length(); p++)
{
MString pname = params[p];
MFloatArray floatVals;
MIntArray intVals;
MMatrix matrixVal;
switch (ptype)
{
lightParam->getParameter( pname, intVals );
printf("\t\tLight parameter %s. Bool[%d]\n", pname.asChar(),
intVals[0]);
break;
lightParam->getParameter( pname, intVals );
printf("\t\tLight parameter %s. Integer[%d]\n", pname.asChar(),
intVals[0]);
break;
lightParam->getParameter( pname, floatVals );
printf("\t\tLight parameter %s. Float[%g]\n", pname.asChar(),
floatVals[0]);
break;
lightParam->getParameter( pname, floatVals );
printf("\t\tLight parameter %s. Float[%g,%g]\n", pname.asChar(),
floatVals[0], floatVals[1]);
break;
lightParam->getParameter( pname, floatVals );
printf("\t\tLight parameter %s. Float3[%g,%g,%g]\n", pname.asChar(),
floatVals[0], floatVals[1], floatVals[2]);
break;
lightParam->getParameter( pname, floatVals );
printf("\t\tLight parameter %s. Float4[%g,%g,%g,%g]\n", pname.asChar(),
floatVals[0], floatVals[1], floatVals[2], floatVals[3]);
break;
lightParam->getParameter( pname, matrixVal );
printf("\t\tLight parameter %s. Float4x4Row [%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n\t\t[%g,%g,%g,%g]\n",
pname.asChar(),
matrixVal[0][0], matrixVal[0][1], matrixVal[0][2], matrixVal[0][3],
matrixVal[1][0], matrixVal[1][1], matrixVal[1][2], matrixVal[1][3],
matrixVal[2][0], matrixVal[2][1], matrixVal[2][2], matrixVal[2][3],
matrixVal[3][0], matrixVal[3][1], matrixVal[3][2], matrixVal[3][3]
);
break;
lightParam->getParameter( pname, matrixVal );
printf("\t\tLight parameter %s. Float4x4Row\n", pname.asChar() );
break;
{
// Get shadow map as a resource handle directly in OpenGL
void *handle = lightParam->getParameterTextureHandle( pname );
printf("\t\tLight texture parameter %s. OpenGL texture id = %d\n", pname.asChar(),
*((int *)handle));
// Similar access for DX would look something like this:
// (ID3D11ShaderResourceView *) lightParam->getParameterTextureHandle( pname );
break;
}
lightParam->getParameter( pname, samplerDesc );
printf("\t\tLight sampler parameter %s. filter = %d\n", pname.asChar(),
samplerDesc.filter );
break;
default:
break;
}
// Do some discovery to map stock parameters to usable values
// based on the semantic
//
switch (semantic)
{
printf("\t\t- Parameter semantic : light enabled\n");
break;
printf("\t\t- Parameter semantic : world position\n");
position += MFloatPoint( floatVals[0], floatVals[1], floatVals[2] );
positionCount++;
break;
printf("\t\t- Parameter semantic : world direction\n");
direction = MFloatVector( floatVals[0], floatVals[1], floatVals[2] );
break;
printf("\t\t- Parameter semantic : intensity\n");
break;
printf("\t\t- Parameter semantic : color\n");
color = MColor( floatVals[0], floatVals[1], floatVals[2] );
break;
printf("\t\t- Parameter semantic : emits-diffuse\n");
break;
printf("\t\t- Parameter semantic : emits-specular\n");
break;
printf("\t\t- Parameter semantic : decay rate\n");
break;
printf("\t\t- Parameter semantic : drop-off\n");
break;
printf("\t\t- Parameter semantic : cosine cone angle\n");
break;
printf("\t\t- Parameter semantic : shadow map\n");
break;
printf("\t\t- Parameter semantic : shadow map sampler\n");
break;
printf("\t\t- Parameter semantic : shadow map bias\n");
break;
printf("\t\t- Parameter semantic : shadow map size\n");
break;
printf("\t\t- Parameter semantic : shadow map view projection matrix\n");
break;
printf("\t\t- Parameter semantic : shadow color\n");
break;
printf("\t\t- Parameter semantic : global shadows on \n");
break;
printf("\t\t- Parameter semantic : local shadows on\n");
break;
printf("\t\t- Parameter semantic : depth range\n");
break;
default:
break;
}
}
// Compute an average position
if (positionCount > 1)
{
position[0] /= (float)positionCount;
position[1] /= (float)positionCount;
position[2] /= (float)positionCount;
printf("\t\tCompute average position [%g,%g,%g]\n", position[0],
position[1], position[2]);
}
// Print by semantic
printf("\t\tSemantic -> Parameter Name Lookups\n");
MStringArray paramNames;
printf("\t\t\tkLightEnabled -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
MFloatArray floatVals;
if (floatVals.length() > 0) printf("(%f)", floatVals[0]);
printf("\n");
printf("\t\t\tkWorldPosition -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkWorldDirection -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkIntensity -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkColor -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkEmitsDiffuse -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkEmitsSpecular -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkDecayRate -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkDropoff -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkCosConeAngle -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
lightParam->parameterNames(MHWRender::MLightParameterInformation::kIrradianceIn, paramNames);
printf("\t\t\tkIrradianceIn -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowMap -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowSamp -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowBias -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowMapSize -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowColor -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkGlobalShadowOn -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkShadowOn -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t\t\tkDepthRange -> ");
for (unsigned int i=0; i<paramNames.length(); i++)
{
printf("%s ", paramNames[i].asChar());
}
printf("\n");
printf("\t}\n");
}
}
}
//------------------------------------------------------------------------
// Custom present target operation
//
// There is not much in this operation except to override which targets
// will be presented.
//
// This differs from scene and quad operations which generally
// use targets as the place to render into.
//
viewRenderPresentTarget::viewRenderPresentTarget(const MString &name)
: MPresentTarget( name )
{
mTargets = NULL;
}
viewRenderPresentTarget::~viewRenderPresentTarget()
{
mTargets = NULL;
}
void
viewRenderPresentTarget::setRenderTargets(MHWRender::MRenderTarget **targets)
{
mTargets = targets;
}
viewRenderPresentTarget::targetOverrideList(unsigned int &listSize)
{
if (mTargets)
{
listSize = 2;
return &mTargets[kMyColorTarget];
}
return NULL;
}
//------------------------------------------------------------------------
// Custom HUD operation
//
void viewRenderHUDOperation::addUIDrawables( MHWRender::MUIDrawManager& drawManager2D, const MHWRender::MFrameContext& frameContext )
{
// Start draw UI
drawManager2D.beginDrawable();
// Set font color
drawManager2D.setColor( MColor( 0.455f, 0.212f, 0.596f ) );
// Set font size
// Draw renderer name
int x=0, y=0, w=0, h=0;
frameContext.getViewportDimensions( x, y, w, h );
drawManager2D.text( MPoint(w*0.5f, h*0.91f), MString("Sample VP2 Renderer Override"), MHWRender::MUIDrawManager::kCenter );
// Draw viewport information
MString viewportInfoText( "Viewport information: x= " );
viewportInfoText += x;
viewportInfoText += ", y= ";
viewportInfoText += y;
viewportInfoText += ", w= ";
viewportInfoText += w;
viewportInfoText += ", h= ";
viewportInfoText += h;
drawManager2D.text( MPoint(w*0.5f, h*0.885f), viewportInfoText, MHWRender::MUIDrawManager::kCenter );
// End draw UI
drawManager2D.endDrawable();
}
//------------------------------------------------------------------------
// Custom quad operation
//
// Instances of this class are used to provide different
// shaders to be applied to a full screen quad.
//
viewRenderQuadRender::viewRenderQuadRender(const MString &name)
: MQuadRender( name )
, mShaderInstance(NULL)
, mShader(kEffectNone)
{
mTargets = NULL;
}
viewRenderQuadRender::~viewRenderQuadRender()
{
mTargets = NULL;
if (mShaderInstance)
{
if (renderer)
{
const MHWRender::MShaderManager* shaderMgr = renderer->getShaderManager();
if (shaderMgr)
{
shaderMgr->releaseShader(mShaderInstance);
}
}
mShaderInstance = NULL;
}
}
/*
Return the appropriate shader instance based on the what
we want the quad operation to perform
*/
viewRenderQuadRender::shader()
{
// Create a new shader instance for this quad render instance
//
if (mShaderInstance == NULL)
{
if (renderer)
{
const MHWRender::MShaderManager* shaderMgr = renderer->getShaderManager();
if (shaderMgr)
{
// Note in the following code that we are not specifying the
// full file name, but relying on the getEffectFileShader() logic
// to determine the correct file name extension based on the shading language
// which is appropriate for the drawing API (DirectX or OpenGL).
//
// Refer to the documentation for this method to review how the
// final name on disk is derived.
//
// The second argument here is the technique. If desired
// and effect on disk can hold different techniques. For each unique
// effect + technique a different shader instance is created.
//
switch (mShader)
{
case kPre_MandelBrot:
mShaderInstance = shaderMgr->getEffectsFileShader( "MandelBrot", "" );
break;
case kPost_EffectMonochrome:
mShaderInstance = shaderMgr->getEffectsFileShader( "FilterMonochrome", "" );
break;
case kPost_EffectEdgeDetect:
mShaderInstance = shaderMgr->getEffectsFileShader( "FilterEdgeDetect", "" );
break;
case kPost_EffectInvert:
mShaderInstance = shaderMgr->getEffectsFileShader( "Invert", "" );
break;
case kScene_Threshold:
mShaderInstance = shaderMgr->getEffectsFileShader( "Threshold", "" );
break;
case kScene_BlurHoriz:
mShaderInstance = shaderMgr->getEffectsFileShader( "Blur", "BlurHoriz" );
break;
case kScene_BlurVert:
mShaderInstance = shaderMgr->getEffectsFileShader( "Blur", "BlurVert" );
break;
case kSceneBlur_Blend:
mShaderInstance = shaderMgr->getEffectsFileShader( "Blend", "Add" );
break;
default:
break;
}
}
}
}
// Set parameters on the shader instance.
//
// This is where the input render targets can be specified by binding
// a render target to the appropriate parameter on the shader instance.
//
if (mShaderInstance)
{
switch (mShader)
{
case kPre_MandelBrot:
{
// Example of a simple float parameter setting.
MStatus status = mShaderInstance->setParameter("gIterate", 50);
if (status != MStatus::kSuccess)
{
printf("Could not change mandelbrot parameter\n");
return NULL;
}
}
break;
case kPost_EffectInvert:
{
// Set the input texture parameter 'gInputTex' to use
// a given color target
assignment.target = mTargets[kMyColorTarget];
MStatus status = mShaderInstance->setParameter("gInputTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on invert shader\n");
return NULL;
}
}
break;
case kScene_Threshold:
{
// Set the input texture parameter 'gSourceTex' to use
// a given color target
assignment.target = mTargets[kMyColorTarget];
MStatus status = mShaderInstance->setParameter("gSourceTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on threshold shader\n");
return NULL;
}
mShaderInstance->setParameter("gBrightThreshold", 0.7f );
}
break;
case kScene_BlurHoriz:
{
// Set the input texture parameter 'gSourceTex' to use
// a given color target
assignment.target = mTargets[kMyBlurTarget];
MStatus status = mShaderInstance->setParameter("gSourceTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on hblur shader\n");
return NULL;
}
}
break;
case kScene_BlurVert:
{
// Set the input texture parameter 'gSourceTex' to use
// a given color target
assignment.target = mTargets[kMyBlurTarget];
MStatus status = mShaderInstance->setParameter("gSourceTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on vblur shader\n");
return NULL;
}
}
break;
case kSceneBlur_Blend:
{
// Set the first input texture parameter 'gSourceTex' to use
// one color target.
assignment.target = mTargets[kMyColorTarget];
MStatus status = mShaderInstance->setParameter("gSourceTex", assignment);
if (status != MStatus::kSuccess)
{
return NULL;
}
// Set the second input texture parameter 'gSourceTex2' to use
// a second color target.
assignment2.target = mTargets[kMyBlurTarget];
status = mShaderInstance->setParameter("gSourceTex2", assignment2);
if (status != MStatus::kSuccess)
{
return NULL;
}
mShaderInstance->setParameter("gBlendSrc", 0.3f );
}
break;
case kPost_EffectMonochrome:
{
// Set the input texture parameter 'gInputTex' to use
// a given color target
assignment.target = mTargets[kMyColorTarget];
MStatus status = mShaderInstance->setParameter("gInputTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on monochrome shader\n");
return NULL;
}
}
break;
case kPost_EffectEdgeDetect:
{
// Set the input texture parameter 'gInputTex' to use
// a given color target
assignment.target = mTargets[kMyColorTarget];
MStatus status = mShaderInstance->setParameter("gInputTex", assignment);
if (status != MStatus::kSuccess)
{
printf("Could not set input render target / texture parameter on edge detect shader\n");
return NULL;
}
mShaderInstance->setParameter("gThickness", 1.0f );
mShaderInstance->setParameter("gThreshold", 0.1f );
}
break;
default:
break;
}
}
return mShaderInstance;
}
/*
Based on which shader is being used for the quad render
we want to render to different targets. For the
threshold and two blur shaders the temporary 'blur'
target is used. Otherwise rendering should be directed
to the custom color and depth target.
*/
viewRenderQuadRender::targetOverrideList(unsigned int &listSize)
{
if (mTargets)
{
// Render to blur target for blur operations
if (mShader == kScene_Threshold ||
mShader == kScene_BlurHoriz ||
mShader == kScene_BlurVert )
{
listSize = 1; // Only to color target
return &mTargets[kMyBlurTarget];
}
// Render to final otherwise
else
{
listSize = 2; // 2nd target is depth
return &mTargets[kMyColorTarget];
}
}
return NULL;
}
/*
Set the clear override to use.
*/
viewRenderQuadRender::clearOperation()
{
// Want to clear everything since the quad render is the first operation.
if (mShader == kPre_MandelBrot)
{
mClearOperation.setClearGradient( false );
mClearOperation.setMask( (unsigned int) MHWRender::MClearOperation::kClearAll );
}
// This is a post processing operation, so we don't want to clear anything
else
{
mClearOperation.setClearGradient( false );
mClearOperation.setMask( (unsigned int) MHWRender::MClearOperation::kClearNone );
}
return mClearOperation;
}
//------------------------------------------------------------------------
//
// Simple scene operation
//
// Example of just overriding a few options on the scene render.
//
simpleViewRenderSceneRender::simpleViewRenderSceneRender(const MString &name)
: MSceneRender( name )
{
// 100 % of target size
mViewRectangle[0] = 0.0f;
mViewRectangle[1] = 0.0f;
mViewRectangle[2] = 1.0f;
mViewRectangle[3] = 1.0f;
}
const MFloatPoint *
simpleViewRenderSceneRender::viewportRectangleOverride()
{
// Enable this flag to use viewport sizing
bool testRectangleSize = false;
if (testRectangleSize)
{
// 1/3 to the right and 10 % up. 1/2 the target size.
mViewRectangle[0] = 0.33f;
mViewRectangle[1] = 0.10f;
mViewRectangle[2] = 0.50f;
mViewRectangle[3] = 0.50f;
}
return &mViewRectangle;
}
simpleViewRenderSceneRender::clearOperation()
{
// Override to clear to these gradient colors
float val1[4] = { 0.0f, 0.2f, 0.8f, 1.0f };
float val2[4] = { 0.5f, 0.4f, 0.1f, 1.0f };
mClearOperation.setClearColor( val1 );
mClearOperation.setClearColor2( val2 );
mClearOperation.setClearGradient( true );
return mClearOperation;
}
//------------------------------------------------------------------------
// Custom scene operation
//
// Some example things that can be done with the operation are
// included here but disabled. They are here as examples only
// and not all are used for the overrall render loop logic.
//
viewRenderSceneRender::viewRenderSceneRender(
const MString &name,
unsigned int clearMask)
: MSceneRender(name)
, mSceneFilter(sceneFilter)
, mClearMask(clearMask)
, mEnableSRGBWrite(false)
{
mPrevDisplayStyle = M3dView::kGouraudShaded;
// 100 % of target size
mViewRectangle[0] = 0.0f;
mViewRectangle[1] = 0.0f;
mViewRectangle[2] = 1.0f;
mViewRectangle[3] = 1.0f;
mTargets = NULL;
mShaderOverride = NULL;
mUseShaderOverride = false;
mUseStockShaderOverride = false;
mAttachPrePostShaderCallback = false;
mUseShadowShader = false;
mOverrideDisplayMode = true;
mOverrideDisplayModeFlatActive = false;
mOverrideLightingMode = false;
mOverrideCullingMode = false;
mOverrrideM3dViewDisplayMode = false;
mDebugTargetResourceHandle = false;
mFilterDrawNothing = false;
mFilterDrawSelected = false;
}
viewRenderSceneRender::~viewRenderSceneRender()
{
mTargets = NULL;
if (mShaderOverride)
{
if (renderer)
{
const MHWRender::MShaderManager* shaderMgr = renderer->getShaderManager();
if (shaderMgr)
{
shaderMgr->releaseShader(mShaderOverride);
}
}
mShaderOverride = NULL;
}
}
/*
Pre UI draw
*/
void viewRenderSceneRender::addPreUIDrawables( MHWRender::MUIDrawManager& drawManager, const MHWRender::MFrameContext& frameContext )
{
drawManager.beginDrawable();
drawManager.setColor( MColor( 0.1f, 0.5f, 0.95f ) );
drawManager.text( MPoint( -2, 2, -2 ), MString("Pre UI draw test in Scene operation"), MHWRender::MUIDrawManager::kRight );
drawManager.line( MPoint( -2, 0, -2 ), MPoint( -2, 2, -2 ) );
drawManager.setColor( MColor( 1.0f, 1.0f, 1.0f ) );
drawManager.sphere( MPoint( -2, 2, -2 ), 0.8, false );
drawManager.setColor( MColor( 0.1f, 0.5f, 0.95f, 0.4f ) );
drawManager.sphere( MPoint( -2, 2, -2 ), 0.8, true );
drawManager.endDrawable();
}
/*
Post UI draw
*/
void viewRenderSceneRender::addPostUIDrawables( MHWRender::MUIDrawManager& drawManager, const MHWRender::MFrameContext& frameContext )
{
drawManager.beginDrawable();
drawManager.setColor( MColor( 0.05f, 0.95f, 0.34f ) );
drawManager.text( MPoint( 2, 2, 2 ), MString("Post UI draw test in Scene operation"), MHWRender::MUIDrawManager::kLeft );
drawManager.line( MPoint( 2, 0, 2), MPoint( 2, 2, 2 ) );
drawManager.setColor( MColor( 1.0f, 1.0f, 1.0f ) );
drawManager.sphere( MPoint( 2, 2, 2 ), 0.8, false );
drawManager.setColor( MColor( 0.05f, 0.95f, 0.34f, 0.4f ) );
drawManager.sphere( MPoint( 2, 2, 2 ), 0.8, true );
drawManager.endDrawable();
}
/*
Keep a reference of per-frame render targets on the operation
*/
void
viewRenderSceneRender::setRenderTargets(MHWRender::MRenderTarget **targets)
{
mTargets = targets;
}
/*
Offscreen target override.
For this render loop the scene render will always render to
an offscreen color and depth target (listSize returned = 2).
*/
viewRenderSceneRender::targetOverrideList(unsigned int &listSize)
{
if (mTargets)
{
listSize = 2;
return &mTargets[kMyColorTarget];
}
return NULL;
}
/*
Indicate whether to enable SRGB write
*/
bool viewRenderSceneRender::enableSRGBWrite()
{
return mEnableSRGBWrite;
}
/*
Sample of accessing the view to get a camera path and using that as
the camera override. Other camera paths or direct matrix setting
*/
viewRenderSceneRender::cameraOverride()
{
M3dView mView;
if (mPanelName.length() &&
{
mView.getCamera( mCameraOverride.mCameraPath );
return &mCameraOverride;
}
printf("\t%s : Query custom scene camera override -- no override set\n", mName.asChar());
return NULL;
}
/*
Depending on what is required either the scene filter will return whether
to draw the opaque, transparent of non-shaded (UI) items.
*/
viewRenderSceneRender::renderFilterOverride()
{
return mSceneFilter;
}
/*
Example display mode override. In this example we override so that
the scene will always be drawn in "shaded" or "flat shade selected" mode
and in bounding box mode (bounding boxes will also be drawn). This is fact not a
'regular' viewport display mode available from the viewport menus.
*/
viewRenderSceneRender::displayModeOverride()
{
if (mOverrideDisplayMode)
{
if (mOverrideDisplayModeFlatActive)
{
}
else
{
}
}
}
/*
Example Lighting mode override. In this example
the override would set to draw with only selected lights.
*/
viewRenderSceneRender::lightModeOverride()
{
if (mOverrideLightingMode)
{
}
}
/*
Example culling mode override. When enable
this example would force to cull backfacing
polygons.
*/
viewRenderSceneRender::cullingOverride()
{
if (mOverrideCullingMode)
{
}
}
/*
Per scene operation pre-render.
In this example the display style for the given panel / view
M3dView is set to be consistent with the draw override
for the scene operation.
*/
void
viewRenderSceneRender::preRender()
{
if ( mOverrrideM3dViewDisplayMode )
{
M3dView mView;
if (mPanelName.length() &&
{
mPrevDisplayStyle = mView.displayStyle();
}
}
}
/*
Post-render example.
In this example we can debug the resource handle of the active render target
after this operation. The matching for for the pre-render M3dView override
also resides here to restore the M3dView state.
*/
void
viewRenderSceneRender::postRender()
{
if (mDebugTargetResourceHandle)
{
// Get the id's for the textures which are used as the color and
// depth render targets. These id's could arbitrarily change
// so they should not be held on to.
void * colorResourceHandle = (mTargets[kMyColorTarget]) ? mTargets[kMyColorTarget]->resourceHandle() : NULL;
if (colorResourceHandle)
printf("\t - Color target resource handle = %d\n", *( (int *)colorResourceHandle) );
void * depthStencilResourceHandle = (mTargets[kMyDepthTarget]) ? mTargets[kMyDepthTarget]->resourceHandle() : NULL;
if (depthStencilResourceHandle)
printf("\t - Depth target resource handle = %d\n", *( (int *)depthStencilResourceHandle) );
}
// Example of set the display style for the given panel / view
// via M3dView vs using the scene operation override
//
if ( mOverrrideM3dViewDisplayMode )
{
M3dView mView;
if (mPanelName.length() &&
{
// Simple example of restoring display style
mView.setDisplayStyle( mPrevDisplayStyle );
}
}
}
/*
Object type exclusions example.
In this example we want to hide cameras and the grid (ground plane)
*/
MUint64
viewRenderSceneRender::getObjectTypeExclusions()
{
// Example of hiding by type.
}
/*
Example scene override logic.
In this example, the scene to draw can be filtered by a returned
selection list. If an empty selection list is returned then we can
essentially disable scene drawing. The other option coded here
is to look at the current active selection list and return that.
This results in only rendering what has been selected by the user
when this operation is executed.
If this filtering is required across more than one operation it
is better to precompute these values in the setup phase of
override and cache the information per operation as required.
*/
viewRenderSceneRender::objectSetOverride()
{
mSelectionList.clear();
// If you set this to true you can make the
// scene draw draw no part of the scene, only the
// additional UI elements
//
if (mFilterDrawNothing)
return &mSelectionList;
// Turn this on to query the active list and only
// use that for drawing
//
if (mFilterDrawSelected)
{
MSelectionList selList;
if (selList.length())
{
MItSelectionList iter( selList );
for ( ; !iter.isDone(); iter.next() )
{
MDagPath item;
MObject component;
iter.getDagPath( item, component );
/* MStatus sStatus = */ mSelectionList.add( item, component );
/*
if (sStatus == MStatus::kSuccess)
{
printf("Add selection item to other list\n");
}
else if (sStatus == MStatus::kInvalidParameter)
{
printf("Can't Add invalid selection item to other list\n");
}
else
printf("Can't Add selection item to other list\n");
*/
}
}
if (mSelectionList.length())
{
printf("\t%s : Filtering render with active object list\n",
mName.asChar());
return &mSelectionList;
}
}
return NULL;
}
/*
Custom clear override.
Depending on whether we are drawing the "UI" or "non-UI"
parts of the scene we will clear different channels.
Color is never cleared since there is a separate operation
to clear the background.
*/
viewRenderSceneRender::clearOperation()
{
if ( mSceneFilter &
MHWRender::MSceneRender::kRenderUIItems) ){
mClearOperation.setClearGradient(false);
} else{
// Force a gradient clear with some sample colors.
//
float val1[4] = { 0.0f, 0.2f, 0.8f, 1.0f };
float val2[4] = { 0.5f, 0.4f, 0.1f, 1.0f };
mClearOperation.setClearColor(val1);
mClearOperation.setClearColor2(val2);
mClearOperation.setClearGradient(true);
}
mClearOperation.setMask(mClearMask);
return mClearOperation;
}
/*
Return shadow override. For the UI pass we don't want to compute shadows.
*/
const bool* viewRenderSceneRender::shadowEnableOverride()
{
if ( (mSceneFilter & MHWRender::MSceneRender::kRenderShadedItems) == 0 )
{
static const bool noShadowsForUI = false;
return &noShadowsForUI; // UI doesn't need shadows
}
// For all other cases, just use whatever is currently set
return NULL;
}
// Shader override helpers:
// As part of a shader override it is possible to attach callbacks which
// are invoked when the shader is to be used. The following are some examples
// of what could be performed.
/*
Example utility used by a callback to:
1. Print out the shader parameters for a give MShaderInsrtance
2. Examine the list of render items which will be rendered with this MShaderInstance
3. Examine the pass context and print out information in the context.
*/
static void callbackDataPrint(
const MHWRender::MRenderItemList& renderItemList,
MHWRender::MShaderInstance *shaderInstance)
{
if (shaderInstance)
{
MStringArray paramNames;
shaderInstance->parameterList( paramNames );
unsigned int paramCount = paramNames.length();
printf("\tSHADER: # of parameters = %d\n", paramCount );
for (unsigned int i=0; i<paramCount; i++)
{
printf("\t\tPARAM[%s]\n", paramNames[i].asChar());
}
}
int numItems = renderItemList.length();
const MHWRender::MRenderItem* item = NULL;
for (int i=0; i<numItems; i++)
{
item = renderItemList.itemAt(i);
if (item)
{
MDagPath path = item->sourceDagPath();
printf("\tRENDER ITEM: '%s' -- SOURCE: '%s'\n", item->name().asChar(), path.fullPathName().asChar());
}
}
const MHWRender::MPassContext & passCtx = context.getPassContext();
const MString & passId = passCtx.passIdentifier();
const MStringArray & passSem = passCtx.passSemantics();
printf("PASS ID[%s], PASS SEMANTICS[", passId.asChar());
for (unsigned int i=0; i<passSem.length(); i++)
printf(" %s", passSem[i].asChar());
printf("\n");
}
/*
Example utility used by callback to bind lighting information to a shader instance.
This callback works specific with the MayaBlinnDirectionLightShadow shader example.
It will explicitly binding lighting and shadowing information to the shader instance.
*/
static void shaderOverrideCallbackBindLightingInfo(
const MHWRender::MRenderItemList& renderItemList,
MHWRender::MShaderInstance *shaderInstance)
{
if (!shaderInstance)
return;
// Defaults in case there are no lights
//
bool globalShadowsOn = false;
bool localShadowsOn = false;
MFloatVector direction(0.0f, 0.0f, 1.0f);
float lightIntensity = 0.0f; // If no lights then black out the light
float lightColor[3] = { 0.0f, 0.0f, 0.0f };
MStatus status;
// Scan to find the first light that has a direction component in it
// It's possible we find no lights.
//
unsigned int lightCount = drawContext.numberOfActiveLights(considerAllSceneLights);
if (lightCount)
{
MFloatArray floatVals;
MIntArray intVals;
shadowResource.texture = NULL;
MMatrix shadowViewProj;
float shadowColor[3] = { 0.0f, 0.0f, 0.0f };
unsigned int i=0;
bool foundDirectional = false;
for (i=0; i<lightCount && !foundDirectional ; i++)
{
globalShadowsOn = false;
localShadowsOn = false;
direction = MFloatVector(0.0f, 0.0f, 1.0f);
lightIntensity = 0.0f;
lightColor[0] = lightColor[1] = lightColor[2] = 0.0f;
MHWRender::MLightParameterInformation *lightParam = drawContext.getLightParameterInformation( i, considerAllSceneLights );
if (lightParam)
{
MStringArray params;
lightParam->parameterList(params);
for (unsigned int p=0; p<params.length(); p++)
{
MString pname = params[p];
switch (semantic)
{
// Pick a few light parameters to pick up as an example
lightParam->getParameter( pname, floatVals );
direction = MFloatVector( floatVals[0], floatVals[1], floatVals[2] );
foundDirectional = true;
break;
lightParam->getParameter( pname, floatVals );
lightIntensity = floatVals[0];
break;
lightParam->getParameter( pname, floatVals );
lightColor[0] = floatVals[0];
lightColor[1] = floatVals[1];
lightColor[2] = floatVals[2];
break;
// Pick up shadowing parameters
lightParam->getParameter( pname, intVals );
if (intVals.length())
globalShadowsOn = (intVals[0] != 0) ? true : false;
break;
lightParam->getParameter( pname, intVals );
if (intVals.length())
localShadowsOn = (intVals[0] != 0) ? true : false;
break;
lightParam->getParameter( pname, shadowViewProj);
break;
lightParam->getParameter( pname, shadowResource );
break;
lightParam->getParameter( pname, samplerDesc );
break;
lightParam->getParameter( pname, floatVals );
shadowColor[0] = floatVals[0];
shadowColor[1] = floatVals[1];
shadowColor[2] = floatVals[2];
break;
default:
break;
}
} /* for params */
}
// Set shadow map and projection if shadows are turned on.
//
if (foundDirectional && globalShadowsOn && localShadowsOn && shadowResource.texture)
{
void *resourceHandle = shadowResource.texture->resourceHandle();
if (resourceHandle)
{
bool debugShadowBindings = false;
status = shaderInstance->setParameter("mayaShadowPCF1_shadowMap", shadowResource );
if (status == MStatus::kSuccess && debugShadowBindings)
printf("Bound shadow map to shader param mayaShadowPCF1_shadowMap\n");
status = shaderInstance->setParameter("mayaShadowPCF1_shadowViewProj", shadowViewProj );
if (status == MStatus::kSuccess && debugShadowBindings)
printf("Bound shadow map transform to shader param mayaShadowPCF1_shadowViewProj\n");
status = shaderInstance->setParameter("mayaShadowPCF1_shadowColor", &shadowColor[0] );
if (status == MStatus::kSuccess && debugShadowBindings)
printf("Bound shadow map color to shader param mayaShadowPCF1_shadowColor\n");
}
if (renderer)
{
MHWRender::MTextureManager* textureManager = renderer->getTextureManager();
if (textureManager)
{
textureManager->releaseTexture(shadowResource.texture);
}
}
shadowResource.texture = NULL;
}
}
}
// Set up parameters which should be set regardless of light existence.
status = shaderInstance->setParameter("mayaDirectionalLight_direction", &( direction[0] ));
status = shaderInstance->setParameter("mayaDirectionalLight_intensity", lightIntensity );
status = shaderInstance->setParameter("mayaDirectionalLight_color", &( lightColor[0] ));
status = shaderInstance->setParameter("mayaShadowPCF1_mayaGlobalShadowOn", globalShadowsOn);
status = shaderInstance->setParameter("mayaShadowPCF1_mayaShadowOn", localShadowsOn);
}
/*
Example pre-render callback attached to a shader instance
*/
static void shaderOverridePreDrawCallback(
const MHWRender::MRenderItemList& renderItemList,
MHWRender::MShaderInstance *shaderInstance)
{
printf("PRE-draw callback triggered for render item list with data:\n");
callbackDataPrint(context, renderItemList, shaderInstance);
printf("\n");
printf("\tLIGHTS\n");
viewRenderOverrideUtilities::printDrawContextLightInfo( context );
printf("\n");
}
/*
Example post-render callback attached to a shader instance
*/
static void shaderOverridePostDrawCallback(
const MHWRender::MRenderItemList& renderItemList,
MHWRender::MShaderInstance *shaderInstance)
{
printf("POST-draw callback triggered for render item list with data:\n");
callbackDataPrint(context, renderItemList, shaderInstance);
printf("\n");
}
/*
Example of setting a shader override.
Some variations are presented based on some member flags:
- Use a stock shader or not
- Attach pre and post shader instance callbacks
- Use a shadow shader
*/
viewRenderSceneRender::shaderOverride()
{
if (mUseShaderOverride)
{
if (!mShaderOverride)
{
const MHWRender::MShaderManager *shaderManager = theRenderer ? theRenderer->getShaderManager() : NULL;
if (shaderManager)
{
if (!mUseStockShaderOverride)
{
if (mUseShadowShader)
{
// This shader has parameters which can be updated
// by the attached pre-callback.
mShaderOverride = shaderManager->getEffectsFileShader(
"MayaBlinnDirectionalLightShadow", "", 0, 0, true,
shaderOverrideCallbackBindLightingInfo,
NULL);
}
else
{
// Use a sample Gooch shader
mShaderOverride = shaderManager->getEffectsFileShader(
"Gooch", "", 0, 0, true,
mAttachPrePostShaderCallback ? shaderOverridePreDrawCallback : NULL,
mAttachPrePostShaderCallback ? shaderOverridePostDrawCallback : NULL);
}
}
else
{
// Use a stock shader available from the shader manager
// In this case the stock Blinn shader.
mShaderOverride = shaderManager->getStockShader(
mAttachPrePostShaderCallback ? shaderOverridePreDrawCallback : NULL,
mAttachPrePostShaderCallback ? shaderOverridePostDrawCallback : NULL);
if (mShaderOverride)
{
printf("\t%s : Set stock shader override %d\n", mName.asChar(), MHWRender::MShaderManager::k3dBlinnShader );
static const float diffColor[] = {0.0f, 0.4f, 1.0f, 1.0f};
MStatus status = mShaderOverride->setParameter("diffuseColor", diffColor);
if (status != MStatus::kSuccess)
{
printf("Could not set diffuseColor on shader\n");
}
}
}
}
}
return mShaderOverride;
}
// No override so return NULL
return NULL;
}