#ifndef GLSL_SHADER_NODE_H
#define GLSL_SHADER_NODE_H
#include <vector>
#include <maya/MFnNumericAttribute.h>
#include <maya/MNodeMessage.h>
#include <maya/MObjectArray.h>
#include <maya/MPxHwShaderNode.h>
#include <maya/MDGModifier.h>
#include <maya/MPxNode.h>
#include <maya/MStringArray.h>
#include <maya/MTypeId.h>
#include <IAshliFX.h>
#include "Shader.h"
#include "DefaultShader.h"
#include "glslFXShader.h"
class glStateCache
{
public:
inline glStateCache() { reset(); }
inline void reset() { bits = 0; textureUnit = -1; }
inline void enablePosition() { if( !(bits & (1 << kPosition))) { glEnableClientState(GL_VERTEX_ARRAY); bits |= (1 << kPosition); } }
inline void disablePosition() { if( bits & (1 << kPosition)) { glDisableClientState(GL_VERTEX_ARRAY); bits &= ~(1 << kPosition); } }
inline void enableNormal() { if( !(bits & (1 << kNormal))) { glEnableClientState(GL_NORMAL_ARRAY); bits |= (1 << kNormal); } }
inline void disableNormal() { if( bits & (1 << kNormal)) { glDisableClientState(GL_NORMAL_ARRAY); bits &= ~(1 << kNormal); } }
inline void enableColor() { if( !(bits & (1 << kColor0))) { glEnableClientState(GL_COLOR_ARRAY); bits |= (1 << kColor0); } }
inline void disableColor() { if( bits & (1 << kColor0)) { glDisableClientState(GL_COLOR_ARRAY); bits &= ~(1 << kColor0); } }
inline void activeTexture( int i) { if( i != textureUnit) { textureUnit = i; glClientActiveTexture( GL_TEXTURE0 + i); } }
inline void enableAndActivateTexCoord( int i) { activeTexture( i); if( !(bits & (1 << (kTexCoord0 + i)))) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); bits |= (1 << (kTexCoord0 + i)); } }
inline void disableTexCoord( int i) { if( bits & (1 << (kTexCoord0 + i))) { activeTexture( i); glDisableClientState(GL_TEXTURE_COORD_ARRAY); bits &= ~(1 << (kTexCoord0 + i)); } }
private:
enum
{
kPosition,
kNormal,
kColor0,
kColor1,
kTexCoord0
};
int bits;
int textureUnit;
};
class MImage;
class MGeometryData;
class glslShaderNode : public MPxHwShaderNode
{
public:
glslShaderNode();
virtual ~glslShaderNode();
virtual void postConstructor();
virtual MStatus compute( const MPlug& plug, MDataBlock& data );
static void* creator();
static MStatus initialize();
virtual MStatus glBind(const MDagPath& shapePath);
virtual MStatus glUnbind(const MDagPath& shapePath);
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);
virtual bool supportsBatching() const;
virtual MStatus renderSwatchImage( MImage & image );
virtual MStatus connectionMade( const MPlug& plug, const MPlug& otherPlug, bool asSrc );
virtual MStatus connectionBroken( const MPlug& plug, const MPlug& otherPlug, bool asSrc );
virtual bool getInternalValueInContext( const MPlug&,
MDataHandle&,
MDGContext&);
virtual bool setInternalValueInContext( const MPlug&,
const MDataHandle&,
MDGContext&);
virtual void copyInternalData ( MPxNode * );
virtual unsigned int dirtyMask() { return kDirtyAll;};
virtual int normalsPerVertex();
virtual int colorsPerVertex();
virtual int texCoordsPerVertex();
virtual int getColorSetNames( MStringArray &names);
virtual int getTexCoordSetNames( MStringArray &names);
bool printVertexShader( int pass);
bool printPixelShader( int pass);
static glslShaderNode* findNodeByName(const MString &name);
static MTypeId sId;
static MObject sShader;
static MObject sTechnique;
static MObject sTechniqueList;
static MObject sShaderPath;
static MObject sNakedTexCoords[8];
static MObject sNakedColors[2];
static const char *nakedSetNames[8];
static void rejigShaders( void *data);
private:
enum CubeFace { cfLeft, cfRight, cfTop, cfBottom, cfFront, cfBack};
enum MayaType {
kNonMaya,
kNormal,
kTangent,
kBinormal,
kUvSet,
kColorSet
};
MString m_nakedTexSets[8];
int m_setNums[8];
int m_maxSetNum;
MayaType m_mayaType[8];
glStateCache m_glState;
MString m_nakedColorSets[2];
int m_colorSetNums[2];
MayaType m_colorMayaType[2];
MObject findFileTextureNode( const MPlug &plug);
MObject findEnvCubeNode( const MPlug &plug);
void loadCubeFace( CubeFace cf, MObject &cube, MFnDependencyNode &dn);
void updateBoundAttributes( const MDagPath& shapePath);
void configureUniformAttrib( MString &name, int pNum, shader::DataType type, shader::Semantic sm, float* defVal,
MFnDependencyNode &dn, MDGModifier &mod);
void BindSamplerData();
void BindUniformData();
MString m_shaderName;
MString m_shaderPath;
MString m_techniqueName;
MString m_techniqueList;
int m_technique;
shader *m_shader;
bool m_shaderDirty;
int m_passCount;
static shader *sDefShader;
struct uniformAttrib {
MString name;
MObject attrib;
MObject attrib2;
shader::DataType type;
int pNum;
bool dirty;
};
std::vector<uniformAttrib> m_uniformAttribList;
struct samplerAttrib {
MString name;
MObject attrib;
MObject minFilterAttrib;
MObject magFilterAttrib;
MObject wrapAttrib;
MObject anisoAttrib;
int pNum;
GLuint texName;
GLenum minFilter;
GLenum magFilter;
GLenum wrapMode;
float maxAniso;
bool dirty;
};
std::vector<samplerAttrib> m_samplerAttribList;
struct attributeAttrib {
MString name;
MString setName;
MObject attrib;
int handle;
int set;
MayaType mtype;
int pNum;
};
std::vector<attributeAttrib> m_attributeAttribList;
bool m_parsedUserAttribList;
int m_numUVsets;
MStringArray m_uvSetNames;
int m_numColorSets;
MStringArray m_colorSetNames;
int m_numNormals;
void parseUserAttributeList();
struct boundUniform {
MString name;
int pNum;
shader::Semantic usage;
};
std::vector<boundUniform> m_boundUniformList;
bool rebuildShader();
void configureAttribs();
void configureTexCoords( int normalCount, const float ** normalArrays, int texCoordCount,
const float ** texCoordArrays,
int colorCount, const float **colorArrays );
bool locateFile( const MString &name, MString &path);
static std::vector<glslShaderNode*> sNodeList;
};
#endif //GLSL_SHADER_NODE_H