Autodesk Maya 2014

OpenMaya Render

UI Drawing enhancements

Geometry Enhancements

Shader Override Enhancements

  • There is now a new type of shader override (MPxShadingNodeOverride) based on shader fragments. This new system is a direct exposure of the internal system Maya uses to dynamically build effects for its shading networks. MPxShadingNodeOverride differs from the pre-existing MPxShaderOverride in that implementations of MPxShaderOverride are required to produce the whole shading effect for a shading network (including lighting), while MPxShadingNodeOverride is only required to produce a small fragment for an individual node within the network.
  • Implementations of MPxShadingNodeOverride define a shader fragment or graph of shader fragments to be used to draw a specific node in Viewport 2.0. This fragment or fragment graph is then connected to the fragments for the other nodes in the shading network (both those defined internally and by other plug-ins). The final composite fragment graph is then compiled to a shading effect and used to draw the objects associated with the shading network for which it was produced.
  • Shading fragments and fragment graphs are managed by the new MFragmentManager class. This class allows plug-ins to define new fragments for both GL and DX using XML to define the structure, parameters and source code of the fragment. MFragmentManager can also be used to query the XML definitions of Maya internal fragments in order to get examples of how to write new fragments that integrate well with the Maya fragment-based shader system.
  • A subclass of MPxShadingNodeOverride, called MPxSurfaceShadingNodeOverride, has also been introduced. This class provides extra functionality for supporting surface shaders (in other words, nodes that can be connected to the surface slot on the shading engine, generally classified with shader/surface).
  • For more details, see the API documentation for the new classes: MPxShadingNodeOverride, MFragmentManager and MPxSurfaceShadingNodeOverride, as well as the updates to the Maya Viewport 2.0 API Guide.

Shader Instance Enhancements

  • Addition of new simple stock shader to render color for depth passes.
  • Addition of stock shaders for drawing UI:
    • dashed or non-dashed, thick or non-thick, using constant color or color per vertex variations of shaders for lines
    • stipple face shader
  • A uniform semantic RelativeViewportDimensions can be specified to obtain the relative viewport dimensions. This semantic can be used to adjust the UV transform on quad render operations.

    The following example modifies the texture coordinates:

    float4 gUVTransform : RelativeViewportDimensions;
    In.UV * gUVTransform.zw + gUVTransform.xy”

    The following shaders have been modified to use the new semantic:

    • OpenGL: BlendGL.cgfx, BlurGL.cgfx, ThresholdGL.cgfx, AnaglyphGL.cgfx, FreeViewGL.cgfx, CheckerBoardGL.cgfx, InterlaceGL.cgfx
    • Direct3D10: Blend10.fx, Blur.fx, Threshold10.fx, Anaglyph10.fx, FreeView10.fx
  • Addition of new fragment-based shader instance creation method: MShaderManager::getFragmentShader(). It returns a new instance of a shader generated from a name shader fragment or fragment graph.
  • MShaderInstance objects now support a clone() interface for use in situations where many identical shaders are needed in a high-performance manner.

Texturing Enhancements

  • There have been a number of modifications to the texture API that enhances how color textures are acquired, cached and updated:
    • For acquisition, the acquireTexture() methods on MTextureManager have been modified to allow NULL data to be passed over on creation and to allow for unnamed textures (empty string). Unnamed textures are not cached by the internal texture caching system; as a result, the acquisition creates a new texture for each method call. The behavior of named textures remains the same. If a texture with that name exists in the cache, then it is returned.
    • In general, continuously reacquiring a texture is not recommended. Therefore, new interfaces that perform updates of existing textures have been added to MTexture:
      • MStatus update(const void* pixelData, bool generateMipMaps, unsigned int rowPitch=0);
      • MStatus update(const MImage &image, bool generateMipMaps);
    • Along with the new method MTexture::bytesPerPixel(), and the existing method MTexture::rawData() there are a number of different ways that textures can be updated:
      • The raw data can be extracted from an existing MTexture and used for updating. In this case, it is important that the rowPitch from the MTexture be used during the update() call to ensure proper data transfer when there is row padding. This affects textures created under DirectX.
      • New raw data can be passed to update an existing MTexture. It is the responsibility of the caller to ensure that the data is of the correct size.
      • Data from an MImage can be used to update an existing MTexture. It is the responsibility of the caller to ensure that the format of the texture matches that of the MImage which is currently 4-byte, 8 bytes per channel RGBA color. The bytesPerPixel() method can be used to query the MTexture for a matching format.

        The update mechanism is currently restricted to updating 2D non-array textures.

        Each method call has an inherent cost. Different situations may warrant using different methods.

      • RawData() copies memory back to the CPU from the GPU
      • Update(), using raw pixel data, transfers CPU data to the GPU.
      • Update(), using MImage, maps GPU memory to the CPU, performs a copy and then maps back to GPU.

      The existing plug-in hwAPITextureTest and a new plug-in viewImageBlitOverride demonstrate various methods of performing a color texture update. The first has a new option to invert the pixels in a texture before displaying, and the latter allows the updating of a texture for each refresh of a render override (MRenderOverride).

  • MRenderUtil::eval2dTexture() allows the evaluation of supported texture nodes at one or more (u,v) positions.
  • New interfaces have been added as convenience methods to acquire textures which are suitable for rendering to the depth buffer:
    • MTexture* acquireDepthTexture(const MString &textureName, const MImage &image, bool generateMipMaps, const MDepthNormalizationDescription *normalizationDesc);
    • MTexture* acquireDepthTexture(const MString &textureName, float *pixelData, unsigned int width, unsigned int height, bool generateMipMaps, const MDepthNormalizationDescription *normalizationDesc);
    • The internal format used for these interfaces is R32F (single channel 32-bit floating point stored as the red channel, as opposed to a depth format).
    • The methods can normalize the input data to the [0…1] range, which is suitable for just performing a blit of the data to the depth buffer. The new structure MDepthNormalizationDescription is a way for the plug-in writer to provide input parameters for normalization. It assumes that input data adheres to the convention used for depth buffers produced by Maya’s software renderer, and hence what is stored in an MImage’s depth buffer. If textures are created unnormalized, then it is up to the plug-in writer to provide suitable shader logic to normalize them at render time.
    • The acquireDepthTexture() interface, which takes an MImage as an input, assumes that there is a valid depth buffer stored.
    • A new method has been added to MImage, which can be used to aid in the computation of normalized data. The method returns the depth value ranges for the depth buffer in an MImage:
      • MStatus getDepthMapRange( float &minValue, float &maxValue ) const;
    • The plug-in viewImageBlitOverride provides example code for both generating raw data to fill in a normalized depth texture, as well as for reading an existing depth buffer from an iff file on disk.

      In order to blit to depth, a depth-stencil state override is used on a custom MQuadRender.

    • Refer to related modifications for MQuadRender (see MQuadRender) for details on state setting changes.

Lighting Enhancements

  • Unlimited light access:
  • Shadow updates “by request”
    • It is possible to ask to compute shadow maps on specific light DAG objects even if they are beyond the Viewport 2.0 renderer’s light limit setting. The method MRenderer::setLightRequiresShadows() can be used to either queue or remove from queue such a request. This method does not force a given shadow map to be computed, nor does it force any refresh or new render to occur. It triggers a check for the need for a shadow map update. MRenderer::setLightsAndShadowsDirty() (see Change Management) can be used to force computation, if necessary.
    • If this method is called from within the rendering of a frame, then any shadow map computation update occurs on the next scene update. For example, if this is called from within a hardware shader plug-in (MPxShaderOverride), then updates occur in the next frame (refresh). If called from a render override operation, then the next scene render triggers an update. The scene render is either the next MSceneRender called from within an override, or the next scene render called by the renderer internally when there is no render override.
    • Example code using this interface can be found in the dx11Shader (MPxShaderOverride) and viewRenderOverrideShadows (MRenderOverride) plug-ins. The dx11Shader plug-in has code that illustrates invoking an additional refresh on light binding changes.

  • Enhanced lighting / shadowing interfaces for render overrides
    • Generally, lighting information is only updated during a scene render (MSceneRender). If a shadow request is performed from within a user operation (MUserRenderOperation) in a custom render override, then only the last available lighting information is available. If a user operation requires lighting information, the new virtual method MUserRenderOperation::requiresLightData() can be overridden and set to return true.
    • To allow for a scene render in a render override to access information such as shadow maps after update, two new methods have been added: MSceneRender::preSceneRender() and MSceneRender::postSceneRender(). They are called before and after either: shadow map update, or the rendering of the scene. At this time, the current draw context is available, and hence lighting/shadowing information (MLightParameterInformation).
    • An example which uses the new interfaces is the new viewRenderOverrideShadows render override plug-in. This plug-in performs a user operation to queue shadow requests and then uses them in a custom scene render. The pre-scene render method is overridden to extract the requested shadow maps for use during scene rendering by a custom shader. Light and shadow information beyond the light limit can be accessed.

Render Item Enhancements

  • Instances of MRenderItem may no longer be created or deleted directly. Plug-ins must now use the static Create() and Destroy() methods on MRenderItem. This change addresses stability issues encountered when the allocation/deallocation of the memory occurs in different DLLs.
  • Can now specify the “Bounding Box” viewport mode for render items.
  • Can now set the transform matrix for render items.
  • Can now set whether or not a render item should be included in post-effects such as screen-space ambient occlusion or motion blur.
  • The “depth priority” of a render item can now be set. “Depth priority” sets how far towards the active camera a render item is moved when drawing. This helps to avoid depth-fighting which can occur for render items with drawing that overlaps each other in depth. For example, a render item drawing wireframe and another drawing filled could be drawn at the same depth. To avoid the wireframe item from being obscured by the shaded item, the depth priority on the wireframe item can be “raised” to avoid being obscured. See depthPriority() methods for more information.
  • Previously, any MRenderItems created by a plug-in had their status for casting and receiving shadows automatically set each time MPxGeometryOverride::updateRenderItems() was called. This continues to occur for internally created render items, but this is no longer the case for render items created by the plug-in. It is the responsibility of the plug-in to either track the status on any associated DAG object, or set the values based on other logic. Any items that are marked as drawing in wireframe mode never cast nor receive shadows. Note that render items that draw using lines or points can still cast shadows as long as they are not marked to draw in wireframe mode. The plug-in apiMeshShape provides an example that demonstrates various usage scenarios.
  • Although the following methods are exposed on MRenderItem, they have no effect on internally created render items:
    • setDrawMode()
    • setMatrix()
    • setShader()
    • setExcludedFromPostEffects()
    • castShadows()
    • receivesShadows()
    • depthPriority()
  • The setExclucedFromPostEffects() method only disables screen-space ambient occlusion if the render item is marked as drawing in shaded or textured mode. If the item is marked as drawing in wireframe mode, then all post-effects are disabled (screen-space ambient occlusion, motion blur and depth-of-field).

State Enhancements

  • The methods on MStateManager for acquiring state objects are now static; therefore, states can now be both created and deleted without access to an MDrawContext. Only activating states require a draw context.

Pass Information Enhancements

  • There are a few new pass context semantics which have been exposed as part of the addition of the MUIDrawManager interface:
    • UI geometry : UI is being drawn
      • Pre-UI geometry : UI drawn before the scene (for example, the ground plane).
      • Post UI geometry: UI drawn relative to filled drawing (for example, wireframe or components on a surface).
      • Opaque UI : Opaque UI is being drawn.
      • Transparent UI : Transparent UI is being drawn.
      • Xray UI : UI in x-ray mode is being drawn.

Render Override Enhancements

  • Fixed so that post-effects do not affect scene render operations which only draw the UI.
  • Ability to explicitly disable post-effects for scene render operations.
  • MQuadRender now allows for the specification of state setters. By default, when rendering the geometry for a quad render operation, blending is disabled, depth write is disabled, and culling is disabled. Any of the following methods can be implemented by classes derived from MQuadRender to replace the default behavior for a given state:
    • virtual const MDepthStencilState* depthStencilStateOverride(); // Override depth-stencil state
    • virtual const MRasterizerState* rastersizerStateOverride(); // Override rasterizer state
    • virtual const MBlendState* blendStateOverride(); // Override blend state

    If an override is specified for a given state, then the default state is used for those other states that are not overridden.

    The viewImageBlitOverride plug-in from the devkit provides an example of overriding the depth write state.

  • MRenderer::theRenderer() now takes an optional initializeRenderer parameter. Passing false suppresses full initialization of the renderer. This can speed up the loading of plug-ins by allowing them to register their rendering overrides without the overhead of full renderer initialization.

Change Management Enhancements

  • There is a new method on MRenderer that informs Maya that lights and shadow maps in the scene need to be re-evaluated: MRenderer::setLightsAndShadowsDirty(). This is useful, for example, for shaders that can modify the geometry of an object through hardware tessellation. Maya cannot automatically detect that the geometry has changed in such a case; therefore, it is up to the shader to notify Maya when changes occur that would require shadows to be recomputed.
  • MRenderer::disableChangeManagementUntilNextRefresh() can be used to avoid the overhead of Viewport 2.0 processing changes to the scene when large changes are being made that do not require viewport updates.

Draw Override Enhancements

  • The prepareForDraw() interface now accepts MFrameContext as a parameter as follows:

    virtual MUserData* prepareForDraw( const MDagPath& objPath, const MDagPath& cameraPath, const MFrameContext& frameContext, MUserData* oldData) = 0

  • Because occasionally geometry information is computed based on viewport attributes (for example, viewport size); therefore, plug-in developers may require this information in preparing for the draw data stage.

Geometry Override Enhancements

  • Switching between templating and not templating a Maya DAG object automatically toggles the visibility of shaded render items, which makes this consistent with the logic used for the default viewport interface. Plug-ins can override this behavior as desired to disable/enable any or all of these items.
  • Improvements to the apiMeshShape example that uses MPxGeometryOverride. The code demonstrates the following:
    • Drawing the wireframe in different display modes (display mode detection), and not just when the object is active (active display mode) .
    • Drawing of dormant and active vertices using the “fat point” stock shader.
    • Sample code for acquiring thick line and dash line stock shaders.
    • Support for hiding render items when the object is templated and appropriate render items for drawing templates.
    • Usage of new MRenderItem::depthPriority() methods to avoid depth-fighting between UI drawing (for example active and dormant vertex drawing).

Maya Callback Enhancements

MFrameContext

MFrameContext is a new interface for Maya 2014. It is designed to provide information which is available per frame render. This includes information such as render targets, viewport size and camera information.

In terms of relative scope, MFrameContext can be thought of as encompassing the time period for a one or more "passes" (MPassContext) and the time period for actual drawing (MDrawContext).

MDrawContext is derived from MFrameContext and provides its own implementation for all virtual methods. The values returned from these methods may differ slightly between MFrameContext and MDrawContext as MFrameContext retrieves the values from Maya and MDrawContext retrieves the values from the GPU device state. Also, MFrameContext::getMatrix() is not able to return values for any matrix type requiring the object-to-world matrix, as that information is only available at draw time.

Frame context information available includes:

  • Camera and view information.
  • Viewport and active render target information.
  • Display style (mimicking the Viewport 2.0 render globals and viewport options)
  • Lighting mode and light limit (same)
  • Indication of which post effects are active
  • Indication of which transparency algorithm is used
  • Global line width setting in the viewport Shading menu

MPxSubSceneOverride

MPxSubSceneOverride is a new interface for Maya 2014. It is an alternative to MPxDrawOverride and MPxGeometryOverride, and is specifically optimized for representing plug-in DAG objects in Viewport 2.0 that need to produce a large number of independent drawable objects. For example, a plug-in node that can define a whole sub-scene (such as the gpuCache plug-in) is a good fit for this interface as a single node may need to produce tens of thousands of drawable objects.

MPxSubSceneOverride falls in between MPxDrawOverride and MPxGeometryOverride with respect to the amount of control given to the implementation. MPxDrawOverride allows full control over the entire draw of the object, but as a result the implementation is entirely responsible for the draw. MPxGeometryOverride is relatively simple to work with, but as a result only limited control of the draw is available. MPxSubSceneOverride can fully define all render items, geometry and shaders, providing a high degree of control. However, this definition is abstracted from the hardware draw API; therefore, only one implementation is needed to get support for both DirectX and OpenGL. Furthermore, Maya handles drawing of the render items and thus the items can participate more fully in the Maya rendering pipeline (including screen-space effects such as screen-space ambient occlusion, transparency sorting, shadow casting/receiving, and so forth).

Ghosting support

The Maya 2014 API explicitly does not call back to render overrides to render ghosted objects.

Previously, when the dag object for which an override is attached to is set to be ghosted, it is possible for the render item or draw code to be called multiple times – once for each ghost.

This no longer occurs. Thus, it is up to the plug-in writer to write code to perform the plug-in's own ghosting.

MPxDrawOverride, MPxGeometryOverride and MPxSubSceneOverride are the affected classes.

.NET API

The port of the MetaData C++ API to the .NET API has been revamped and improved significantly to:

  • support standard .NET interfaces such as IDictionary and IEnumerable on key classes
  • simplify the concept of data description and data access where the user can now simply provide a .NET type for the data. This completely replaces the need for using the classes Structure and Handle as they are now created automatically from this client type.

For more information, see MetaData.

New API for Reference Edits

  • MPxEditData gives you the ability to create your own custom data to associate with reference edits.

New API for Generic Metadata (blind data)

  • MFileIO - Added the setMetadata(), deleteMetadata() and metadata() methods to allow the specification of persistent scene-level metadata (that is, it is stored with the scene file).

New External Content API

  • MExternalContentInfoTable is used to store the locations of all the external content (files, textures, and so forth) that is needed by a node to perform its work. MExternalContentLocationTable is used to pass updates to those locations to the node (for example, from the File Path Editor).
  • getExternalContent(), setExternalContent() and addExternalContentForFileAttr() have been added to MFnDependencyNode and MPxNode to access and modify the external content of nodes.

Miscellaneous

  • MnObject::fnObject and fOwn have been made private. These should not been used and if they are, modifications must be made accordingly.
  • MRampAttribute has had a number of methods added to make it easier to use. setRamp() makes it easier to set new values on the ramp and createRamp() makes it easier to create a ramp with initial values. Also added are sort(), pack(), and hasIndex().
  • The evalNoSelectNotify command executes a command with selection change notifications disabled. This can significantly improve performance in those situations where a script is executing a large number of commands which change the current selection (for example, createNode), but where only the final selection state is significant.

Documentation

Plug-in transforms

  • Plug-in writers should be aware that, in order for a plug-in transform to be recognized in Viewport 2.0, the appropriate classification string drawdb/geometry/transform must be added when registering the transform. This must be done so that:
    • Local rotation axis and pivots draw.
    • Transforming the object moves any children parented under it in the DAG.

    For example, for the rockingTransform plug-in, the code is as follows:

    // Classify the node as a transform.  This causes Viewport
    // 2.0 to treat the node the same way it treats a regular
    // transform node.
    const MString classification = "drawdb/geometry/transform";
    status = plugin.registerTransform("rockingTransform", 								
                                       rockingTransformNode::id, 					 				
                                       &rockingTransformNode::creator, 								
                                       &rockingTransformNode::initialize,
                                       &rockingTransformMatrix::creator,
                                       rockingTransformMatrix::id,
                                       &classification);
    

    This functionality was available beginning Maya 2012.

    In Maya 2014, registerTransform() has been updated to automatically add the drawdb/geometry/transform classification if no other drawdb classification is specified. The getClassification command documentation has also been updated with the general list of classifications recognized by Viewport 2.0.

Updates to Viewport 2.0 API chapter