C++ API Reference
cgFx/cgfxShaderNode.h
#ifndef _cgfxShaderNode_h_
#define _cgfxShaderNode_h_
//
// Copyright (C) 2002-2003 NVIDIA
//
// File: cgfxShaderNode.h
//
// Dependency Graph Node: cgfxShaderNode
//
// Author: Jim Atkinson
//
// Changes:
// 10/2003 Kurt Harriman - www.octopusgraphics.com +1-415-893-1023
// - Multiple UV sets; user-specified texcoord assignment;
// error handling.
// 12/2003 Kurt Harriman - www.octopusgraphics.com +1-415-893-1023
// - attrDefList() no longer calls fAttrDefList->addRef()
// - Added members: fTechniqueList, getTechniqueList()
// - Deleted members: fCallbackSet, callbackSet(),
// setCallback(), technique()
// - Deleted class cgfxShaderNode::InternalError.
// - Made protected instead of public: setShaderFxFile,
// setTechnique, setTexCoordSource
//
//-
// ==========================================================================
// 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.
// ==========================================================================
//+
#include "cgfxShaderCommon.h"
#include <maya/MFnNumericAttribute.h>
#include <maya/MNodeMessage.h>
#include <maya/MObjectArray.h>
#include <maya/MCallbackIdArray.h>
#include <maya/MPxHwShaderNode.h>
#include <maya/MPxNode.h>
#include <maya/MStateManager.h>
#include <maya/MStringArray.h>
#include <maya/MTypeId.h>
// Viewport 2.0 includes
#include <maya/MPxShaderOverride.h>
#include "cgfxRCPtr.h"
#include "cgfxEffectDef.h"
#include "cgfxAttrDef.h"
#include <set>
#include <map>
class cgfxProfile;
class cgfxPassStateSetter;
// Largest possible number of texture units (GL_MAX_TEXTURE_UNITS) for any
// OpenGL implementation, according to the OpenGL 1.2 multitexture spec.
#define CGFXSHADERNODE_GL_TEXTURE_MAX 32 // GL_TEXTURE31-GL_TEXTURE0+1
#define CGFXSHADERNODE_GL_COLOR_MAX 1
class cgfxShaderNode : public MPxHwShaderNode
{
friend class cgfxAttrDef; // For setTexturesByName().
friend class cgfxShaderOverride;
public:
cgfxShaderNode();
void postConstructor() override;
~cgfxShaderNode() override;
// Typically, hardware shaders to not need to compute any outputs.
//
MStatus compute( const MPlug& plug, MDataBlock& data ) override;
// Create the node ...
//
static void* creator();
// ... and initialize it.
//
static MStatus initialize();
static void initializeNodeAttrs();
// We want to track the changes to the shader attribute because
// it causes us a large amount of work every time it is modified
// and we want to do that work as rarely as possible.
//
void copyInternalData( MPxNode* pSrc ) override;
bool getInternalValue( const MPlug&, MDataHandle&) override;
bool setInternalValue( const MPlug&, const MDataHandle&) override;
// Tell Maya that Cg effects can be batched
bool supportsBatching() const override;
// Tell Maya we require inverted texture coordinates
bool invertTexCoords() const override;
// Indicate pass transparency options
bool hasTransparency() override;
unsigned int transparencyOptions() override;
// Set up the graphics pipeline for drawing with the shader
//
MStatus glBind(const MDagPath& shapePath) override;
void bindAttrValues();
void bindViewAttrValues(const MDagPath& shapePath);
#if MAYA_API_VERSION >= 700
#define _SWATCH_RENDERING_SUPPORTED_ 1
#endif
#if defined(_SWATCH_RENDERING_SUPPORTED_)
// Render a swatch
MStatus renderSwatchImage( MImage & image ) override;
#endif
// Restore the graphics pipeline back to its original state
//
MStatus glUnbind(const MDagPath& shapePath) override;
// Put the pixels on the screen
//
MStatus glGeometry( const MDagPath& shapePath,
int prim,
unsigned int writable,
int indexCount,
const unsigned int * indexArray,
int vertexCount,
const int * vertexIDs,
const float * vertexArray,
int normalCount,
const float ** normalArrays,
int colorCount,
const float ** colorArrays,
int texCoordCount,
const float ** texCoordArrays) override;
// Return the desired number of texture coordinates per vertex
//
int getTexCoordSetNames( MStringArray& names ) override;
// Return the desired colours per vertex
//
#if MAYA_API_VERSION >= 700
int getColorSetNames( MStringArray& names ) override;
#else
virtual int colorsPerVertex();
#endif
// Return the desired number of normals per vertex
//
int normalsPerVertex() override;
MStatus getAvailableImages( const MString& uvSetName,
MStringArray& imageNames) override;
MStatus renderImage( const MString& imageName,
floatRegion region,
int& imageWidth,
int& imageHeight) override;
const MString& imageName,
floatRegion region,
int& imageWidth,
int& imageHeight) override;
// Data accessor for the attrDefList
//
const cgfxRCPtr<cgfxAttrDefList>& attrDefList() const { return fAttrDefList; };
void setAttrDefList(const cgfxRCPtr<cgfxAttrDefList>& list);
// Data accessor for the .fx file name (the value of the shader
// attribute).
//
MString shaderFxFile() const { return fShaderFxFile; };
bool shaderFxFileChanged() const { return fShaderFxFileChanged; }
void setShaderFxFileChanged(bool val) { fShaderFxFileChanged = val; if (val) ++fGeomReqDataVersionId; }
// Data accessor for the name of the chosen technique.
MString getTechnique() const { return fTechnique; };
const MStringArray& getTechniqueList() const { return fTechniqueList; }
// Data accessor for the name of the chosen profile.
MString getProfile() const { return fProfileName; };
// Data accessor the attribute list string (the value of the
// attributeList attribute).
//
void getAttributeList(MStringArray& attrList) const;
void setAttributeList(const MStringArray& attrList);
// Set the current per-vertex attributes the shader needs (replacing any existing set)
void setVertexAttributes( cgfxRCPtr<cgfxVertexAttribute> attributeList);
// Set the data set names that will be populating our vertex attributes
void setVertexAttributeSource( const MStringArray& sources);
// Analyse the per-vertex attributes to work out the minimum set of data we require
void analyseVertexAttributes();
// Data accessor for the texCoordSource attribute.
const MStringArray& getTexCoordSource() const;
// Data accessor for the colorSource attribute.
const MStringArray& getColorSource() const;
// Data accessor for list of empty UV sets.
const MStringArray& getEmptyUVSets() const;
const MObjectArray& getEmptyUVSetShapes() const;
// Data accessor for whether to use nodes for textures
inline bool getTexturesByName() const { return fTexturesByName; };
// // Data accessor for the effect itself.
// //
const cgfxRCPtr<const cgfxEffect>& effect() { return fEffect; };
void setEffect(const cgfxRCPtr<const cgfxEffect>& effect);
MStatus shouldSave ( const MPlug & plug, bool & ret ) override;
// Get cgfxShader version string.
static MString getPluginVersion();
protected:
// Try and create a missing effect (e.g. once a GL context is available)
bool createEffect();
// Set internal attributes.
void setShaderFxFile( const MString& fxFile )
{
if (fxFile != fShaderFxFile)
{
// Mark when the shader has changed
fShaderFxFile = fxFile;
fShaderFxFileChanged = true;
fLastShaderFxFileAtVASSet = "";
++fGeomReqDataVersionId;
}
};
void setTechnique( const MString& techn );
void setProfile( const MString& profileName );
void setProfile( const cgfxProfile* profile );
void setDataSources( const MStringArray* texCoordSources, const MStringArray* colorSources );
void updateDataSource( MStringArray& sources, MIntArray& typeList, MIntArray& indexList );
void setTexturesByName( bool texturesByName, bool updateAttributes = false);
void updateTechniqueList();
// Error reporting
void reportInternalError( const char* function, size_t errcode);
public:
// The typeid is a unique 32bit indentifier that describes this node.
// It is used to save and retrieve nodes of this type from the binary
// file format. If it is not unique, it will cause file IO problems.
//
static MTypeId sId;
// There needs to be a MObject handle declared for each attribute that
// the node will have. These handles are needed for getting and setting
// the values later.
//
// Input shader attribute
//
static MObject sShader;
static MObject sTechnique;
static MObject sProfile;
// Input list of attributes that map to CgFX uniform parameters
//
static MObject sAttributeList;
// Input list of attributes that map to CgFX varying parameters
//
static MObject sVertexAttributeList;
// Input list of where to get vertex attributes
static MObject sVertexAttributeSource;
// Input list of where to get texcoords
static MObject sTexCoordSource;
// Input list of where to get colors
static MObject sColorSource;
// Should we use string names or file texture nodes for textures?
static MObject sTexturesByName;
// Cg Context
static CGcontext sCgContext;
// Cg error callback
static void cgErrorCallBack();
// Cg error handler
static void cgErrorHandler(CGcontext cgContext, CGerror cgError, void* userData);
protected:
// Description of the effect and it's varying parameters
cgfxRCPtr<const cgfxEffect> fEffect;
// The (merged) set of varying parameters the current technique requires
// and the mapping onto Maya geometry data sets
cgfxRCPtr<cgfxVertexAttribute> fVertexAttributes;
// This is a mapping of names to cgfxAttrDef pointers. Each cgfxAttrDef
// defines one dynamic attribute
cgfxRCPtr<cgfxAttrDefList> fAttrDefList;
// Values of internal attributes
MString fShaderFxFile;
bool fShaderFxFileChanged;
MString fTechnique;
const cgfxTechnique* fCurrentTechnique;
MString fProfileName;
MStringArray fAttributeListArray;
MStringArray fVertexAttributeListArray;
MStringArray fVertexAttributeSource;
bool fTexturesByName;
// Backward compatibility: these are the old versions of fVertexAttributeSource
MStringArray fTexCoordSource;
MStringArray fColorSource;
// Used to preserve fVertexAttributeSource across file reload/fx file reload
MString fLastShaderFxFileAtVASSet;
// The list of maya data we need
MStringArray fUVSets;
MStringArray fColorSets;
int fNormalsPerVertex;
// These values are derived from the fTexCoordSource value
// For each texture coord / colour unit, we describe what kind of
// data should go in there (i.e. should this data be populated with
// a uv set, a colour set, tangent, normal, etc) AND which set of
// data to use (i.e. put uv set 0 in texcoord1, and colour set 2 in
// texcoord 5)
MIntArray fTexCoordType;
MIntArray fTexCoordIndex;
MIntArray fColorType;
MIntArray fColorIndex;
MStringArray fDataSetNames;
// Cached info derived from the current cgfxEffect.
MStringArray fTechniqueList;
// Cache of bound data streams. Used only by the non-VP2.0
// implementation.
cgfxStructureCache fBoundDataCache;
// Pass state setter used in the VP2.0 implementation.
cgfxPassStateSetter* fPassStateSetters;
// Rendering state (only valid between glBind and glUnbind)
GLboolean fDepthEnableState;
GLint fDepthFunc;
GLint fBlendSourceFactor;
GLint fBlendDestFactor;
// Error handling
bool fConstructed; // true => ok to call MPxNode member functions
short fErrorCount;
short fErrorLimit;
// Maya event callbacks
MCallbackIdArray fCallbackIds;
// Version Id for data that influences the geometry requirements
// computed by the cgfxShaderOverride node. It is incremented each
// time, one of the associated data changes.
int fGeomReqDataVersionId;
MHWRender::MTexture* fUVEditorTexture;
public:
typedef std::set<cgfxShaderNode*> NodeList;
static void getNodesUsingEffect(const cgfxRCPtr<const cgfxEffect>& effect, NodeList &nodes);
private:
// Keep track of all the effect-node association
typedef std::map<const cgfxEffect*, NodeList> Effect2NodesMap;
static Effect2NodesMap sEffect2NodesMap;
static void addAssociation(cgfxShaderNode* node, const cgfxRCPtr<const cgfxEffect>& effect);
static void removeAssociation(cgfxShaderNode* node, const cgfxRCPtr<const cgfxEffect>& effect);
// Watch for attribute removals to avoid crashes
static void attributeAddedOrRemovedCB(MNodeMessage::AttributeMessage msg, MPlug& plug, void* clientData);
};
// ===================================================================================
// viewport 2.0 implementation
// ===================================================================================
// Override for the cgfxShaderNode
class cgfxShaderOverride : public MHWRender::MPxShaderOverride
{
public:
static MHWRender::MPxShaderOverride* Creator(const MObject& obj);
~cgfxShaderOverride() override;
// Initialize phase
MString initialize(MObject shader) override;
// Update phase
void updateDG(MObject object) override;
void updateDevice() override;
void endUpdate() override;
// Draw phase
bool handlesDraw(MHWRender::MDrawContext& context) override;
void activateKey(MHWRender::MDrawContext& context) override;
const MHWRender::MRenderItemList& renderItemList) const override;
void terminateKey(MHWRender::MDrawContext& context) override;
// Override properties
MHWRender::DrawAPI supportedDrawAPIs() const override;
bool isTransparent() override;
bool overridesDrawState() override;
bool rebuildAlways() override
{
return !fShaderNode ||
fShaderNode->fGeomReqDataVersionId != fGeomReqDataVersionId;
}
public:
static const MString drawDbClassification;
static const MString drawRegistrantId;
protected:
cgfxShaderOverride(const MObject& obj);
// bind uniform attributes
bool bindAttrValues() const;
// bind varying attributes
void bindViewAttrValues(const MHWRender::MDrawContext& context) const;
cgfxShaderNode *fShaderNode;
int fGeomReqDataVersionId;
mutable bool fNeedPassSetterInit;
const MHWRender::MBlendState* fOldBlendState;
const MHWRender::MDepthStencilState* fOldDepthStencilState;
const MHWRender::MRasterizerState* fOldRasterizerState;
static cgfxShaderNode* sActiveShaderNode;
static cgfxShaderNode* sLastDrawShaderNode;
};
#endif /* _cgfxShaderNode_h_ */