#ifdef WIN32
#pragma warning( disable : 4786 ) // Disable stupid STL warnings.
#endif
#include <maya/MIOStream.h>
#include <math.h>
#include <maya/MString.h>
#include <maya/MPlug.h>
#include <maya/MDagPath.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFnStringData.h>
#include <maya/MFnPlugin.h>
#include <maya/MGlobal.h>
#include <maya/MSceneMessage.h>
#include <maya/MPoint.h>
#include <maya/MMatrix.h>
#include <maya/MVector.h>
#include <maya/MQuaternion.h>
#include <maya/MEulerRotation.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "glh_extensions.h"
#undef GL_NV_vertex_array_range
#include "glh_obs.h"
using namespace glh;
#include "hwRefractReflectShader_NV20.h"
#include "ShadingConnection.h"
MTypeId hwRefractReflectShader_NV20::id( 0x00105445 );
void hwRefractReflectShader_NV20::postConstructor( )
{
setMPSafe(false);
}
MObject hwRefractReflectShader_NV20::color;
MObject hwRefractReflectShader_NV20::colorR;
MObject hwRefractReflectShader_NV20::colorG;
MObject hwRefractReflectShader_NV20::colorB;
MObject hwRefractReflectShader_NV20::refractionIndex;
MObject hwRefractReflectShader_NV20::reflectivity;
char vertexProgramString[] =
"!!VP1.0 # Refraction and Reflection\n"
"DP4 o[HPOS].x, c[0], v[OPOS];"
"DP4 o[HPOS].y, c[1], v[OPOS];"
"DP4 o[HPOS].z, c[2], v[OPOS];"
"DP4 o[HPOS].w, c[3], v[OPOS];"
"DP4 R9.x, c[8], v[OPOS];"
"DP4 R9.y, c[9], v[OPOS];"
"DP4 R9.z, c[10], v[OPOS];"
"DP4 R9.w, c[11], v[OPOS];"
"DP3 R0.x, c[4], v[NRML];"
"DP3 R0.y, c[5], v[NRML];"
"DP3 R0.z, c[6], v[NRML];"
"DP3 R11.w, R0, R0;"
"RSQ R11.w, R11.w;"
"MUL R11, R0, R11.w;"
"ADD R0, -R9, c[59];"
"DP3 R8.w, R0, R0;"
"RSQ R8.w, R8.w;"
"MUL R8, R0, R8.w;"
"DP3 R0.x, R11, -R8;"
"MAD R1.x, -R0.x, R0.x, c[64].y;"
"MUL R1.x, R1.x, c[58].y;"
"ADD R1.x, c[64].y, -R1.x;"
"RSQ R2.x, R1.x;"
"RCP R2.x, R2.x;"
"MAD R2.x, c[58].x, R0.x, R2.x;"
"MUL R2, R11, R2.x;"
"MAD R2, c[58].x, -R8, R2;"
"DP3 o[TEX0].x, c[12], R2;"
"DP3 o[TEX0].y, c[13], R2;"
"DP3 o[TEX0].z, c[14], R2;"
"MUL R0, R11, c[64].z;"
"DP3 R3.w, R11, R8;"
"MAD R3, R3.w, R0, -R8;"
"DP3 o[TEX1].x, c[12], R3;"
"DP3 o[TEX1].y, c[13], R3;"
"DP3 o[TEX1].z, c[14], R3;"
"END";
void initVertexProgram(const char vertexProgramCode[], GLuint* pVertexProgramId)
{
glGenProgramsNV(1, pVertexProgramId);
GLenum error = glGetError();
assert(error == GL_NO_ERROR);
unsigned int length = strlen(vertexProgramCode);
glLoadProgramNV(GL_VERTEX_PROGRAM_NV, *pVertexProgramId, length,
(const GLubyte *) vertexProgramCode);
error = glGetError();
if (error != GL_NO_ERROR)
{
if (error == GL_INVALID_OPERATION)
{
int error_position = -2;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &error_position);
assert(0);
}
}
}
void hwRefractReflectShader_NV20::loadVertexProgramGL(
M3dView& view )
{
{
if (vertex_program_id == 0)
initVertexProgram(vertexProgramString, &vertex_program_id);
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 8, GL_MODELVIEW, GL_IDENTITY_NV);
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 12, GL_TEXTURE, GL_IDENTITY_NV);
float rIdx = fRefractionIndex;
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 58, rIdx, rIdx*rIdx, 0.0, 0.0);
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 59, 0.0, 0.0, 0.0, 1.0);
glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, 64, 0.0, 1.0, 2.0, 3.0);
}
}
{
bool gotAllEnvironmentMaps = TRUE;
if (colorConnection.type() == ShadingConnection::TEXTURE &&
{
MString envNames[6] = {
"top",
"bottom",
"left",
"right",
"front",
"back" };
for (int i=0; i<6; i++)
{
envNames[i]);
if (conn.type() == ShadingConnection::TEXTURE &&
{
MPlug filenamePlug( conn.texture(), envNode.attribute(
MString(
"fileTextureName")) );
if (decalName.
length() == 0) decalName =
"internalDefaultTexture";
decalNames.
append( decalName );
}
else
{
decalName = "internalDefaultTexture";
decalNames.
append( decalName );
}
}
}
else
{
decalName = "internalDefaultTexture";
for (int i=0; i<6; i++)
{
decalNames.
append( decalName );
}
}
bool reload = FALSE;
for (int i=0; i<6; i++)
{
if (currentTextureNames[i] != decalNames[i])
{
reload = TRUE;
break;
}
}
{
if ( reload )
{
if (! (stat = theImage_XP.readFromFile(xpTexName)) )
return MS::kFailure;
if (! (stat = theImage_XN.readFromFile(xnTexName)) )
return MS::kFailure;
if (! (stat = theImage_YP.readFromFile(ypTexName)) )
return MS::kFailure;
if (! (stat = theImage_YN.readFromFile(ynTexName)) )
return MS::kFailure;
if (! (stat = theImage_ZP.readFromFile(zpTexName)) )
return MS::kFailure;
if (! (stat = theImage_ZN.readFromFile(znTexName)) )
return MS::kFailure;
if (fTextureName == -1) glGenTextures(1, &fTextureName);
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
glEnable( GL_TEXTURE_CUBE_MAP_ARB );
unsigned int width, height;
stat = theImage_XP.getSize( width, height );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_XP.pixels() );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_XN.pixels() );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_YP.pixels() );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_YN.pixels() );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_ZP.pixels() );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, theImage_ZN.pixels() );
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
for (i=0; i<6; i++) currentTextureNames[i] = decalNames[i];
}
glActiveTextureARB( GL_TEXTURE0_ARB );
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
glEnable( GL_TEXTURE_CUBE_MAP_ARB );
glActiveTextureARB( GL_TEXTURE1_ARB );
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
glEnable( GL_TEXTURE_CUBE_MAP_ARB );
}
}
{
{
glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
{
float refractivity[4], reflectivity[4];
refractivity[0] = refractivity[1] = refractivity[2] = refractivity[3] = 1.0f - fReflectivity;
reflectivity[0] = reflectivity[1] = reflectivity[2] = reflectivity[3] = fReflectivity;
glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, refractivity);
glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, reflectivity);
}
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
}
}
{
MStatus stat = loadTextures( request, view);
MPlug tPlug(thisMObject(), reflectivity);
if( tPlug.getValue( fReflectivity ) )
{
if( fReflectivity < 0.01f ) fReflectivity = 0.01f;
if( fReflectivity > 1.0f ) fReflectivity = 1.0f;
}
else fReflectivity = 0.5f;
MPlug rPlug(thisMObject(), refractionIndex);
if( rPlug.getValue( fRefractionIndex ) )
{
if ( fRefractionIndex < 1.0f ) fRefractionIndex = 1.0f;
if ( fRefractionIndex > 2.0f ) fRefractionIndex = 2.0f;
}
else fRefractionIndex = 1.0f;
initCombiners( request, view );
double camTheta;
camTheta *= 57.295779513082320876798154814105;
glMatrixMode( GL_TEXTURE );
glPushMatrix();
glLoadIdentity();
glScalef(1.0, -1.0, 1.0);
glRotated( camTheta, camAxis[0], camAxis[1], camAxis[2]);
glMatrixMode( GL_MODELVIEW );
return stat;
}
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)
{
glPushAttrib( GL_ALL_ATTRIB_BITS );
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
MStatus preDrawStatus = preDraw( request, view );
{
loadVertexProgramGL( view );
{
glEnable(GL_REGISTER_COMBINERS_NV);
glBindProgramNV(GL_VERTEX_PROGRAM_NV, vertex_program_id);
glEnable(GL_VERTEX_PROGRAM_NV);
{
glVertexAttribPointerNV( 0, 3, GL_FLOAT, 0, vertexArray );
glVertexAttribPointerNV( 2, 3, GL_FLOAT, 0, normalArrays[0] );
glEnableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV );
glEnableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV );
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, indexArray);
glDisableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV );
glDisableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV );
}
glDisable(GL_VERTEX_PROGRAM_NV);
glDisable(GL_REGISTER_COMBINERS_NV);
}
postDraw( request, view );
}
glPopClientAttrib();
glPopAttrib();
return preDrawStatus;
}
MStatus hwRefractReflectShader_NV20::postDraw(
{
{
glMatrixMode( GL_TEXTURE );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glActiveTextureARB( GL_TEXTURE1_ARB );
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, 0 );
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
glActiveTextureARB( GL_TEXTURE0_ARB );
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, 0 );
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
}
}
int hwRefractReflectShader_NV20::normalsPerVertex()
{
return 1;
}
int hwRefractReflectShader_NV20::texCoordsPerVertex()
{
return 1;
}
void hwRefractReflectShader_NV20::init_ext(const char * ext)
{
if(!glh_init_extension(ext))
{ cerr << "Failed to initialize " << ext << "!" << endl; exit(0); }
}
hwRefractReflectShader_NV20::hwRefractReflectShader_NV20()
{
m_pTextureCache = MTextureCache::instance();
init_ext("GL_ARB_multitexture");
init_ext("GL_NV_register_combiners");
init_ext("GL_NV_vertex_program");
fTextureName = -1;
currentTextureNames[0] = "";
currentTextureNames[1] = "";
currentTextureNames[2] = "";
currentTextureNames[3] = "";
currentTextureNames[4] = "";
currentTextureNames[5] = "";
fBeforeNewCB = 0;
fBeforeOpenCB = 0;
fBeforeRemoveReferenceCB = 0;
fMayaExitingCB = 0;
attachSceneCallbacks();
vertex_program_id = 0;
}
hwRefractReflectShader_NV20::~hwRefractReflectShader_NV20()
{
detachSceneCallbacks();
}
void releaseVertexProgram(GLuint* pVertexProgramId)
{
if (*pVertexProgramId > 0)
{
glBindProgramNV(GL_VERTEX_PROGRAM_NV, 0);
glDeleteProgramsNV(1, pVertexProgramId);
*pVertexProgramId = 0;
}
}
void hwRefractReflectShader_NV20::releaseEverything()
{
if (fTextureName != -1) glDeleteTextures(1, &fTextureName);
releaseVertexProgram(&vertex_program_id);
m_pTextureCache->release();
if(!MTextureCache::getReferenceCount())
{
m_pTextureCache = 0;
}
}
void hwRefractReflectShader_NV20::attachSceneCallbacks()
{
releaseCallback, this);
}
void hwRefractReflectShader_NV20::releaseCallback(void* clientData)
{
hwRefractReflectShader_NV20 *pThis = (hwRefractReflectShader_NV20*) clientData;
pThis->releaseEverything();
}
void hwRefractReflectShader_NV20::detachSceneCallbacks()
{
fBeforeNewCB = 0;
fBeforeOpenCB = 0;
fBeforeRemoveReferenceCB = 0;
fMayaExitingCB = 0;
}
{
const MString UserClassify(
"shader/surface/utility" );
MFnPlugin plugin( obj, PLUGIN_COMPANY,
"4.0",
"Any");
status = plugin.registerNode( "hwRefractReflectShader_NV20", hwRefractReflectShader_NV20::id,
hwRefractReflectShader_NV20::creator, hwRefractReflectShader_NV20::initialize,
if (!status) {
status.
perror(
"registerNode");
return status;
}
}
{
status = plugin.deregisterNode( hwRefractReflectShader_NV20::id );
if (!status) {
status.
perror(
"deregisterNode");
return status;
}
}
void * hwRefractReflectShader_NV20::creator()
{
return new hwRefractReflectShader_NV20();
}
MStatus hwRefractReflectShader_NV20::initialize()
{
color = nAttr.
create(
"color",
"c", colorR, colorG, colorB);
addAttribute(color);
addAttribute(refractionIndex);
addAttribute(reflectivity);
attributeAffects (colorR, outColor);
attributeAffects (colorG, outColor);
attributeAffects (colorB, outColor);
attributeAffects (color, outColor);
attributeAffects (refractionIndex, outColor);
attributeAffects (reflectivity, outColor);
}
MStatus hwRefractReflectShader_NV20::compute(
{
bool k = false;
k |= (plug==outColor);
k |= (plug==outColorR);
k |= (plug==outColorG);
k |= (plug==outColorB);
outColor = resultColor;
}