MPxShaderOverride Class Reference


Detailed Description

Base class for user defined shading effect draw overrides.

MPxShaderOverride allows the user to create a custom override for associating a "full shading effect" with a shading node (custom or standard) in Maya. Its primary use is for associating hardware effects with pre-existing plugin software shaders.

A "full shading effect" defines the complete shading and lighting involved to render a given object. Input resources for shading such as geometry, textures, and lights are defined and bound to the shading effect via the override as required. The override is fully responsible for these tasks.

As an example, for hardware shading, this can be thought of as implementing a CgFx or HLSL effect file renderer which can use the resources defined within a Maya scene.

There are three main phases that the override must implement:

1) Initialization Phase : This phase occurs when Maya determines that the hardware shader generated through this override needs to be rebuilt. This may be due to a new object using the shader, or because something has changed on the shader that requires a complete rebuild. During the initialization phase the geometric stream requirements can be specified using addGeometryRequirement(). The requirements will determine which geometric streams are required from objects to which the given shading effect is assigned. If no requirements are specified then a single position stream requirement will be used.

The initialize() method must return a string representing the shader key. It often happens that different instances of the MPxShaderOverride represent essentially the same shader, but with different shader parameters. The shader key is used to identify the MPxShaderOverride instances representing the same shader. To optimize rendering, the Viewport 2.0 will make an effort to regroup the rendering of objects with the same MPxShaderOverride shader key. This allows the plug-in to perform its setup only once for the entire sequence. It is up to each plug-in to decide what the meaning of representing the same shader is.

2) Data Update Phase : In this phase, updating of all data values required for shading is performed. The interface has an explicit split of when the dependency graph can be accessed (updateDG()), and when the draw API (e.g. OpenGL) can be accessed (updateDevice()). Any intermediate data can be cleaned up when endUpdate() is called.

As an example the override may require input from an attribute on a given node.

  • updateDG() would evaluate the plug for the attribute and cache its value temporarily on the override.
  • updateDevice() would take the temporarily cached value and bind it to a shader stored on the graphic device.
  • endUpdate() would reset the temporary data on the override.

Note that the override can provide a draw hint as to whether shading will involve semi-transparency. This hint can be provided by overriding the isTransparent() method which gets called between updateDevice() and endUpdate().

3) Drawing Phase : The actual drawing using the shader is performed in the pure virtual draw() method. The callback method should return true if it was able to draw successfully. If false is returned then drawing will be done using the default shader used for unsupported materials.

Drawing is explicitly not intermixed with the data update on purpose. By the time draw is being called all evaluation should have been completed. If there is user data that needs to be passed between the update and drawing phases the override must cache that data itself. It is an error to access the Maya dependency graph during draw and attempts to do so may result in instability.

Although it is possible for implementations of the draw() method to handle all shader setup and geometry draw, the expected use of the draw() method is to do shader setup only. Then drawGeometry() can be called to allow Maya to handle the actual geometry drawing. If manual geometry binding is required however, it is possible to query the hardware resource handles through the geometry on each render item in the render item list passed into the draw() method.

The activateKey() and terminateKey() method will also be invoked in the draw phase each time a render item is drawn with a different shader key (see the discussion above about shader keys). The activateKey() and terminateKey() methods can be used to optimize rendering by configuring the rendering state only once for a batch of draw() calls that are sharing the same shader key.

The sequence of invocations will look like:

  • shaderOverrideA->activateKey(...)
  • shaderOverrideA->draw(...)
  • shaderOverrideB->draw(...)
  • shaderOverrideC->draw(...)
  • ...
  • shaderOverrideA->terminateKey(...)
  • shaderOverrideX->activateKey(...) Note that the terminateKey() callback is always invoked on the same MPxShaderOverride instance as the one used to invoked the activateKey() callback.

Note if full draw control is desired, the proxy class MPxDrawOverride may be more appropriate.

Implementations of MPxShaderOverride must be registered with Maya through MDrawRegistry.

Examples:

cgfxShaderNode.cpp, cgfxShaderNode.h, hwColorPerVertexShader.cpp, and hwPhongShader.cpp.

#include <MPxShaderOverride.h>

List of all members.

Public Member Functions

  MPxShaderOverride (const MObject &obj)
  Construct an MPxShaderOverride.
virtual  ~MPxShaderOverride ()
  Destructor.
virtual MString  initialize (MObject object)=0
  Initialization occurs when Maya determines that the hardware shader needs to be rebuilt.
virtual void  updateDG (MObject object)
  This is the first part of the update phase.
virtual void  updateDevice ()
  This is the second part of the update phase.
virtual void  endUpdate ()
  This is the final part of the update phase.
virtual void  activateKey (MDrawContext &context)
  This is the activateKey callback.
virtual bool  draw (MDrawContext &context, const MRenderItemList &renderItemList) const =0
  This is the draw callback, the method is called during the draw phase.
virtual void  terminateKey (MDrawContext &context)
  This is the terminateKey callback.
virtual bool  isTransparent ()
  During the update phase the override will be called to return whether it will be drawing with semi-transparency.
virtual bool  overridesDrawState ()
  During the draw phase this method will be called to determine whether the override will override the draw state when drawing.
virtual bool  rebuildAlways ()
  If this method returns true, it will force shader and geometry data to be rebuilt on any change to the shader.

Static Public Member Functions

static const char *  className ()
  Returns the name of this class.

Protected Member Functions

MStatus  addGeometryRequirement (const MVertexBufferDescriptor &desc)
  During the initialization phase the geometry requirements for the shading effect can be updated.
void  drawGeometry (const MDrawContext &context) const
  This method may be called from draw() and will cause Maya to immediately draw the current geometry using the current state of the draw API.

Constructor & Destructor Documentation

MPxShaderOverride ( const MObject obj )

Construct an MPxShaderOverride.

Parameters:
[in] obj The Maya shading node this override will be used for

Member Function Documentation

MString initialize ( MObject  object ) [pure virtual]

Initialization occurs when Maya determines that the hardware shader needs to be rebuilt.

Any initialization work may be performed here. Also, this is the only time that calls to addGeometryRequirement() may occur.

Changes to parameter values on the Maya shading node will not trigger a call to this method by default. If parameter value changes may cause the shader to alter its geometry requirements, rebuildAlways() should be overridden to return true. This will cause initialize() to be called before every update.

The implementation of this method must return the shader key that is used to identify the MPxShaderOverride instances representing the same shader.

Parameters:
[in] object The Maya shading node this override is used for.
Returns:
The shader key.
void updateDG ( MObject  obj ) [virtual]

This is the first part of the update phase.

Perform any work required to update the shading effect which is related to evaluating the dependency graph. This should be the only place that dependency graph evaluation occurs. Data retrieved from Maya may be cached on the override for use in later stages.

Parameters:
[in] obj The Maya shading node this override is used for.
void updateDevice ( ) [virtual]

This is the second part of the update phase.

Perform any work required to update the shading effect which is related to accessing the underlying graphics device. This is the only place that the graphics device may be safely accessed other than at draw time.

void endUpdate ( ) [virtual]

This is the final part of the update phase.

This method is called by Maya to allow the plugin to clean up any data or state from the previous update stages. No dependency graph evaluation, nor graphics device access should be performed during this phase.

void activateKey ( MDrawContext context ) [virtual]

This is the activateKey callback.

This method is called during the draw phase before invoking any draw() callback that are sharing a common shader key.

The default implementation is empty.

Parameters:
[in,out] context The current draw context
bool draw ( MDrawContext context,
const MRenderItemList renderItemList 
) const [pure virtual]

This is the draw callback, the method is called during the draw phase.

The expected implementation of this method is to do shader setup and then call drawGeometry() to allow Maya to handle the actual geometry drawing. It is however possible to do all shader setup and geometry draw here directly by accessing the hardware resource handles for geometry and index buffers through the geometry associated with each render item in the render item list.

No dependency graph evaluation should occur during this phase. If data from Maya is needed here it must be cached on this object (or elsewhere) during the update phase.

This method should return true on successful draw. If false is returned, Maya will attempt to draw using the default internal draw mechanism.

Information about the current GPU state may be accessed through the MDrawContext object passed to this method. The MRenderItemList object contains one render item for each object that is meant to be drawn by this method.

Parameters:
[in,out] context The current draw context
[in] renderItemList The list of renderable items to draw
Returns:
True if draw was successful, false otherwise.
void terminateKey ( MDrawContext context ) [virtual]

This is the terminateKey callback.

This method is called during the draw phase after invoking draw() callbacks that are sharing a common shader key.

The default implementation is empty.

Parameters:
[in,out] context The current draw context
bool isTransparent ( ) [virtual]

During the update phase the override will be called to return whether it will be drawing with semi-transparency.

This call occurs after updateDevice() which allows for any device evaluation to occur to determine the transparency state.

The default return value is false.

Returns:
True if semi-transparent drawing should occur.
bool overridesDrawState ( ) [virtual]

During the draw phase this method will be called to determine whether the override will override the draw state when drawing.

This call occurs after updateDevice() which allows for any device evaluation to occur to determine if the override will override the draw state.

The Viewport 2.0 renderer will skip setting the draw state for plugins that will override the draw state when drawing. Note that the MPxShaderOverride::terminateKey() should still return the draw state to the value it had when activateKey was called.

The default return value is false.

Returns:
True if the override overrides the draw state.
bool rebuildAlways ( ) [virtual]

If this method returns true, it will force shader and geometry data to be rebuilt on any change to the shader.

This may be necessary for shaders that request specific named data sets like UVs or CPVs. Any change to the required data set means that geometry needs to be rebuilt.

The default return value is false.

Returns:
True if the shader and geometry should be rebuilt on every update.
const char * className ( ) [static]

Returns the name of this class.

Returns:
Name of this class.
MStatus addGeometryRequirement ( const MVertexBufferDescriptor desc ) [protected]

During the initialization phase the geometry requirements for the shading effect can be updated.

The update is accomplished by calling this method once for each new data stream that needs to be added to the list of requirements.

If the geometry has multiple fields of the same type associated with it (e.g. multiple UV sets) the 'name' attribute of the vertex descriptor can be used to select the desired one. If that member is empty or does not match any of the fields then the default field of that type will be used.

Not all combinations of the 'semantic', 'dataType' and 'dimension' attributes of the vertex descriptor are permitted. Currently position, tangent and bitangent vectors are 3-float, texture coordinates are 2-float, and colors are 4-float.

Parameters:
[in] desc The description of the geometry requirement to add
Returns:
Status code
Status Codes:
  • MS::kSuccess Requirement was added.
  • MS::kInvalidParameter An unsupported 'semantic' was specified; or the 'dataType'/'dimension' was not compatible with the 'semantic'.
  • MS::kNotImplemented Requirement could not be added because method was called from outside of initialization phase.
void drawGeometry ( const MDrawContext context ) const [protected]

This method may be called from draw() and will cause Maya to immediately draw the current geometry using the current state of the draw API.

Parameters:
[in] context The current draw context
Examples:
hwPhongShader.cpp.

MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride
MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride MPxShaderOverride