#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 - +1-415-893-1023
// - Multiple UV sets; user-specified texcoord assignment;
// error handling.
// 12/2003 Kurt Harriman - +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;
namespace MHWRender {
class MTexture;
// Largest possible number of texture units (GL_MAX_TEXTURE_UNITS) for any
// OpenGL implementation, according to the OpenGL 1.2 multitexture spec.
class cgfxShaderNode : public MPxHwShaderNode
friend class cgfxAttrDef; // For setTexturesByName().
friend class cgfxShaderOverride;
virtual void postConstructor();
virtual ~cgfxShaderNode();
// Typically, hardware shaders to not need to compute any outputs.
virtual MStatus compute( const MPlug& plug, MDataBlock& data );
// 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.
virtual void copyInternalData( MPxNode* pSrc );
virtual bool getInternalValueInContext( const MPlug&,
virtual bool setInternalValueInContext( const MPlug&,
const MDataHandle&,
// Tell Maya that Cg effects can be batched
virtual bool supportsBatching() const;
// Tell Maya we require inverted texture coordinates
virtual bool invertTexCoords() const;
// Indicate pass transparency options
virtual bool hasTransparency();
virtual unsigned int transparencyOptions();
// Set up the graphics pipeline for drawing with the shader
virtual MStatus glBind(const MDagPath& shapePath);
void bindAttrValues();
void bindViewAttrValues(const MDagPath& shapePath);
// Render a swatch
virtual MStatus renderSwatchImage( MImage & image );
// Restore the graphics pipeline back to its original state
virtual MStatus glUnbind(const MDagPath& shapePath);
// Put the pixels on the screen
virtual 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);
// Return the desired number of texture coordinates per vertex
virtual int getTexCoordSetNames( MStringArray& names );
// Return the desired colours per vertex
virtual int getColorSetNames( MStringArray& names );
virtual int colorsPerVertex();
// Return the desired number of normals per vertex
virtual int normalsPerVertex();
virtual MStatus getAvailableImages( const MString& uvSetName,
MStringArray& imageNames);
virtual MStatus renderImage( const MString& imageName,
floatRegion region,
int& imageWidth,
int& imageHeight);
const MString& imageName,
floatRegion region,
int& imageWidth,
int& imageHeight);
// 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 );
// Get cgfxShader version string.
static MString getPluginVersion();
// 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 = "";
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);
// 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);
// 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;
typedef std::set<cgfxShaderNode*> NodeList;
static void getNodesUsingEffect(const cgfxRCPtr<const cgfxEffect>& effect, NodeList &nodes);
// 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
// ===================================================================================
namespace MHWRender
class MDrawContext;
// Override for the cgfxShaderNode
class cgfxShaderOverride : public MHWRender::MPxShaderOverride
static MHWRender::MPxShaderOverride* Creator(const MObject& obj);
virtual ~cgfxShaderOverride();
// Initialize phase
virtual MString initialize(MObject shader);
// Update phase
virtual void updateDG(MObject object);
virtual void updateDevice();
virtual void endUpdate();
// Draw phase
virtual void activateKey(MHWRender::MDrawContext& context);
virtual bool draw(MHWRender::MDrawContext& context,
const MHWRender::MRenderItemList& renderItemList) const;
virtual void terminateKey(MHWRender::MDrawContext& context);
// Override properties
virtual bool isTransparent();
virtual bool overridesDrawState();
virtual bool rebuildAlways()
return !fShaderNode ||
fShaderNode->fGeomReqDataVersionId != fGeomReqDataVersionId;
static const MString drawDbClassification;
static const MString drawRegistrantId;
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_ */