//- // ========================================================================== // Copyright (C) 2005 ATI Technologies Inc. All rights reserved. // // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ #include #include "Platform.h" #include "hlslFXShader.h" #include "ResourceManager.h" // // // //////////////////////////////////////////////////////////////////////////////// hlslFXShader::hlslFXShader() : m_valid(false), m_fShader(0), m_vShader(0), m_activePass(0), m_activeTechnique(0), m_stale(false), m_color(true), m_normal(true), m_tangent(true), m_binormal(true), m_texMask(0x1), m_error("") { } // // // //////////////////////////////////////////////////////////////////////////////// hlslFXShader::~hlslFXShader() { for (std::vector::iterator it=m_stateList.begin(); it::iterator it = m_vShader.begin(); it < m_vShader.end(); it++) { ResourceManager::destroyAsmProgram( *it); } } m_vShader.clear(); { for (std::vector::iterator it = m_fShader.begin(); it < m_fShader.end(); it++) { ResourceManager::destroyAsmProgram( *it); } } m_fShader.clear(); } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::createFromFile( const char *filename) { m_error = ""; IAshliFX *fx = new IAshliFX; fx->init(); fx->setBinding( IAshliFX::DXSL); fx->setFX( filename); //may need to do some path searching here m_stale = true; try { if (!fx->parse()) { //should store a string describing the failure for query m_error = "Unable to load FX file\n "; m_error += fx->getError(); delete fx; return false; } } catch(...){ printf("Unexpected Error!!\n"); }; if ( fx->getNumTechniques()) { } else { //message about no valid first technique/incorrect number of passes delete fx; m_error = "FX file lacked a valid shader"; return false; } //this will move to bind time //if (!buildShaders()) // return false; if (!parseParameters(fx)) return false; //need to extract all shader data from the fx file here //these are to hold the ASHLIFX data m_techniqueCount = fx->getNumTechniques(); m_techniqueNames.clear(); m_passCount.clear(); m_techniqueOffset.clear(); m_vertexShaders.clear(); m_fragmentShaders.clear(); m_orgVertexShaders.clear(); m_orgFragmentShaders.clear(); for (std::vector::iterator it=m_stateList.begin(); itattach( (IObserveFX*)observer); for (int ii=0; iigetNumPasses(ii); m_techniqueOffset.push_back(totalPasses); ITechniqueFX tech; fx->getTechnique(ii, tech); m_techniqueNames.push_back(tech.getId()); m_passCount.push_back(passCount); for (int jj=0; jjsetNative(IAshli::DXSL); ashli->setFlag( IAshli::UnpackedScalars, true); ashli->setFlag( IAshli::ContiguousMatrix, true); ashli->setFlag( IAshli::ContiguousArray, true); ashli->setFlag( IAshli::MultiPass, false); ashli->init( IAshli::Stream, IAshli::GL, IAshli::Stream); if ( !fx->isVertexNull( ii, jj)) { orgVString = fx->getVertexShader( ii, jj); ashli->addShaderItem( orgVString.c_str()); ashli->addShaderInstance( ashli->addShader( IAshli::Vertex, fx->getVertexEntry( ii, jj))); } if ( !fx->isPixelNull( ii, jj)) { orgFString = fx->getPixelShader( ii, jj); ashli->addShaderItem( orgFString.c_str()); ashli->addShaderInstance( ashli->addShader( IAshli::Pixel, fx->getPixelEntry( ii, jj))); } if ( ashli->invoke("")) { //compile succeeded fx->setMetadata( ii, jj, ashli->getFormals()); fx->setVertexAssembly( ii, jj, ashli->getVertexShader()); fx->setPixelAssembly( ii, jj, ashli->getPixelShader()); if (fx->getVertexAssembly( ii, jj)) vString = fx->getVertexAssembly( ii, jj); if (fx->getPixelAssembly( ii, jj)) fString = fx->getPixelAssembly( ii, jj); } else { //compile failed const char* error = ashli->getError(); m_error = "Shader failed to compile\n"; m_error += error; m_error += std::string("\n"); // would like to print the offending text, but the parsing seems to difficult } m_vertexShaders.push_back(vString); m_fragmentShaders.push_back(fString); m_orgVertexShaders.push_back(orgVString); m_orgFragmentShaders.push_back(orgFString); //accumulate the state data m_stateList.push_back(new passState); observer->setPassMonitor(m_stateList.back()); for (int kk=0; kkgetNumStates( ii,jj); kk++) { fx->getStateItem( ii, jj, kk); } observer->finalizePassMonitor(); delete ashli; } totalPasses += passCount; } fx->attach(NULL); delete observer; delete fx; m_valid = true; return true; } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::createFromFX( IAshliFX *fx) { m_error = ""; m_stale = true; m_valid = false; if (fx->getNumTechniques()) { } else { //message about no valid first technique/incorrect number of passes m_error = "FX file lacked a valid shader"; return false; } if (!parseParameters(fx)) return false; //need to extract all shader data from the fx file here //these are to hold the ASHLIFX data m_techniqueCount = fx->getNumTechniques(); m_techniqueNames.clear(); m_passCount.clear(); m_techniqueOffset.clear(); m_vertexShaders.clear(); m_fragmentShaders.clear(); m_orgVertexShaders.clear(); m_orgFragmentShaders.clear(); for (std::vector::iterator it=m_stateList.begin(); itattach( (IObserveFX*)observer); for (int ii=0; iigetNumPasses(ii); m_techniqueOffset.push_back(totalPasses); ITechniqueFX tech; fx->getTechnique(ii, tech); m_techniqueNames.push_back(tech.getId()); m_passCount.push_back(passCount); for (int jj=0; jjsetNative(IAshli::DXSL); ashli->setFlag( IAshli::UnpackedScalars, true); ashli->setFlag( IAshli::ContiguousMatrix, true); ashli->setFlag( IAshli::ContiguousArray, true); ashli->setFlag( IAshli::MultiPass, false); ashli->init( IAshli::Stream, IAshli::GL, IAshli::Stream); if ( !fx->isVertexNull( ii, jj)) { orgVString = fx->getVertexShader( ii, jj); ashli->addShaderItem( orgVString.c_str()); ashli->addShaderInstance( ashli->addShader( IAshli::Vertex, fx->getVertexEntry( ii, jj))); } if ( !fx->isPixelNull( ii, jj)) { orgFString = fx->getPixelShader( ii, jj); ashli->addShaderItem( orgFString.c_str()); ashli->addShaderInstance( ashli->addShader( IAshli::Pixel, fx->getPixelEntry( ii, jj))); } if ( ashli->invoke("")) { //compile succeeded fx->setMetadata( ii, jj, ashli->getFormals()); fx->setVertexAssembly( ii, jj, ashli->getVertexShader()); fx->setPixelAssembly( ii, jj, ashli->getPixelShader()); if (fx->getVertexAssembly( ii, jj)) vString = fx->getVertexAssembly( ii, jj); if (fx->getPixelAssembly( ii, jj)) fString = fx->getPixelAssembly( ii, jj); } else { //compile failed const char* error = ashli->getError(); m_error = "Shader failed to compile\n"; m_error += error; m_error += std::string("\n"); // would like to print the offending text, but the parsing seems to difficult } m_vertexShaders.push_back(vString); m_fragmentShaders.push_back(fString); m_orgVertexShaders.push_back(orgVString); m_orgFragmentShaders.push_back(orgFString); //accumulate the state data m_stateList.push_back(new passState); observer->setPassMonitor(m_stateList.back()); for (int kk=0; kkgetNumStates( ii,jj); kk++) { fx->getStateItem( ii, jj, kk); } observer->finalizePassMonitor(); // Commented out as this causes a access violation. //delete ashli; } totalPasses += passCount; } fx->attach(NULL); delete observer; m_valid = true; return true; } // // // //////////////////////////////////////////////////////////////////////////////// //new method, parsing parameters from AshliFX bool hlslFXShader::parseParameters(const IAshliFX *fx) { int passCount =0; for (int ii=0; iigetNumTechniques(); ii++) { passCount = std::max( fx->getNumPasses(ii), passCount); } //process the exposed shader parameters for (ii=0; iigetNumParameters(); ii++) { IParameterFX parm; fx->getParameter( "", ii, parm); const char *usage = parm.getUsage(); const char *type = parm.getType(); const char *name = parm.getId(); const char *semantic = parm.getSemantic(); const char *expression = parm.getExpression(); if (strcmp( "const", usage)) { if (strncmp( "sampler", type, 7)) { // this is a regular uniform (not a sampler) //should verify the compatibility of the following pieces of data shader::DataType dt = parseUniformType( type); shader::Semantic sm = parseUniformSemantic( semantic); uniform u; u.type = dt; u.fReg.resize( passCount, -1); u.vReg.resize( passCount, -1); u.usage = sm; u.name = name; //parse the expression to extract a default value parseExpression( u, expression); m_uniformList.push_back(u); } else { // this is a sampler uniform shader::SamplerType st = parseSamplerType( type); sampler s; s.texUnit.resize( passCount, -1); s.type = st; s.name = name; m_samplerList.push_back(s); } } else { //don't know what else we could encounter, might want to create warnings } } return true; } // // // //////////////////////////////////////////////////////////////////////////////// shader::DataType hlslFXShader::parseUniformType( const char *type) { if (!strcmp( "float", type)) { return shader::dtFloat; } else if (!strcmp( "float1", type)) { return shader::dtFloat; } else if (!strcmp( "float2", type)) { return shader::dtVec2; } else if (!strcmp( "float3", type)) { return shader::dtVec3; } else if (!strcmp( "float4", type)) { return shader::dtVec4; } else if (!strcmp( "int", type)) { return shader::dtInt; } else if (!strcmp( "int1", type)) { return shader::dtInt; } else if (!strcmp( "int2", type)) { return shader::dtIVec2; } else if (!strcmp( "int3", type)) { return shader::dtIVec3; } else if (!strcmp( "int4", type)) { return shader::dtIVec4; } else if (!strcmp( "bool", type)) { return shader::dtBool; } else if (!strcmp( "bool1", type)) { return shader::dtBVec2; } else if (!strcmp( "bool2", type)) { return shader::dtBVec2; } else if (!strcmp( "bool3", type)) { return shader::dtBVec3; } else if (!strcmp( "bool4", type)) { return shader::dtBVec4; } else if (!strcmp( "float2x2", type)) { return shader::dtMat2; } else if (!strcmp( "float3x3", type)) { return shader::dtMat3; } else if (!strcmp( "float4x4", type)) { return shader::dtMat4; } return shader::dtUnknown; } // // // //////////////////////////////////////////////////////////////////////////////// shader::Semantic hlslFXShader::parseUniformSemantic( const char *semantic) { if (semantic == NULL) return shader::smNone; //this would be more efficient as a map if (!strcasecmp( "World", semantic)) { return shader::smWorld; } else if (!strcasecmp( "View", semantic)) { return shader::smView; } else if (!strcasecmp( "Projection", semantic)) { return shader::smProjection; } else if (!strcasecmp( "WorldView", semantic)) { return shader::smWorldView; } else if (!strcasecmp( "ViewProjection", semantic)) { return shader::smViewProjection; } else if (!strcasecmp( "WorldViewProjection", semantic)) { return shader::smWorldViewProjection; } else if ( (!strcasecmp( "WorldI", semantic)) || (!strcasecmp( "WorldInverse", semantic))) { return shader::smWorldI; } else if ( (!strcasecmp( "ViewI", semantic)) || (!strcasecmp( "ViewInverse", semantic)) ) { return shader::smViewI; } else if ( (!strcasecmp( "ProjectionI", semantic)) || (!strcasecmp( "ProjectionInverse", semantic)) ) { return shader::smProjectionI; } else if ( (!strcasecmp( "WorldViewI", semantic)) || (!strcasecmp( "WorldViewInverse", semantic)) ) { return shader::smWorldViewI; } else if ( (!strcasecmp( "ViewProjectionI", semantic)) || (!strcasecmp( "ViewProjectionInverse", semantic)) ) { return shader::smViewProjectionI; } else if ( (!strcasecmp( "WorldViewProjectionI", semantic)) || (!strcasecmp( "WorldViewProjectionInverse", semantic)) ) { return shader::smWorldViewProjectionI; } else if ( (!strcasecmp( "WorldT", semantic)) || (!strcasecmp( "WorldTranspose", semantic)) ) { return shader::smWorldT; } else if ( (!strcasecmp( "ViewT", semantic)) || (!strcasecmp( "ViewTranspose", semantic)) ) { return shader::smViewT; } else if ( (!strcasecmp( "ProjectionT", semantic)) || (!strcasecmp( "ProjectionTranspose", semantic)) ) { return shader::smProjectionT; } else if ( (!strcasecmp( "WorldViewT", semantic)) || (!strcasecmp( "WorldViewTranspose", semantic)) ) { return shader::smWorldViewT; } else if ( (!strcasecmp( "ViewProjectionT", semantic)) || (!strcasecmp( "ViewProjectionTranspose", semantic)) ) { return shader::smViewProjectionT; } else if ( (!strcasecmp( "WorldViewProjectionT", semantic)) || (!strcasecmp( "WorldViewProjectionTranspose", semantic)) ) { return shader::smWorldViewProjectionT; } else if ( (!strcasecmp( "WorldIT", semantic)) || (!strcasecmp( "WorldInverseTranspose", semantic)) ) { return shader::smWorldIT; } else if ( (!strcasecmp( "ViewIT", semantic)) || (!strcasecmp( "ViewInverseTranspose", semantic)) ) { return shader::smViewIT; } else if ( (!strcasecmp( "ProjectionIT", semantic)) || (!strcasecmp( "ProjectionInverseTranspose", semantic)) ) { return shader::smProjectionIT; } else if ( (!strcasecmp( "WorldViewIT", semantic)) || (!strcasecmp( "WorldViewInverseTranspose", semantic)) ) { return shader::smWorldViewIT; } else if ( (!strcasecmp( "ViewProjectionIT", semantic)) || (!strcasecmp( "ViewProjectionInverseTranspose", semantic)) ) { return shader::smViewProjectionIT; } else if ( (!strcasecmp( "WorldViewProjectionIT", semantic)) || (!strcasecmp( "WorldViewProjectionInverseTranspose", semantic)) ) { return shader::smWorldViewProjectionIT; } return shader::smUnknown; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::parseExpression( hlslFXShader::uniform &u, const char *exp) { //this function should call a real parser, until then only handle a subset of types for (int ii=0; ii<16; ii++) u.defaultVal[ii] = 0.0f; switch ( u.type) { case shader::dtInt: if ( 1 == sscanf( exp, " int ( %f )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " int1 ( %f )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " %f ", &u.defaultVal[0])) { } else { u.defaultVal[0] = 0.0f; } break; case shader::dtFloat: if ( 1 == sscanf( exp, " float ( %f )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " float1 ( %f )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " %f ", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " float ( %ff )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " float1 ( %ff )", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " %ff ", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " { %f } ", &u.defaultVal[0])) { } else if ( 1 == sscanf( exp, " { %ff } ", &u.defaultVal[0])) { } else { u.defaultVal[0] = 0.0f; } break; case shader::dtVec2: if ( 2 == sscanf( exp, " float2 ( %f , %f )", &u.defaultVal[0], &u.defaultVal[1])) { } else if ( 2 == sscanf( exp, " { %f , %f }", &u.defaultVal[0], &u.defaultVal[1])) { } else if ( 2 == sscanf( exp, " float2 ( %ff , %ff )", &u.defaultVal[0], &u.defaultVal[1])) { } else if ( 2 == sscanf( exp, " { %ff , %ff }", &u.defaultVal[0], &u.defaultVal[1])) { } else { u.defaultVal[0] = 0.0f; u.defaultVal[1] = 0.0f; } break; case shader::dtVec3: if ( 3 == sscanf( exp, " float3 ( %f , %f , %f )", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2])) { } else if ( 3 == sscanf( exp, " { %f , %f , %f }", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2])) { } else if ( 3 == sscanf( exp, " float3 ( %ff , %ff , %ff )", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2])) { } else if ( 3 == sscanf( exp, " { %ff , %ff , %ff }", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2])) { } else { u.defaultVal[0] = 0.0f; u.defaultVal[1] = 0.0f; u.defaultVal[2] = 0.0f; } break; case shader::dtVec4: if ( 4 == sscanf( exp, " float4 ( %f , %f , %f , %f )", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2], &u.defaultVal[3])) { } else if ( 4 == sscanf( exp, " float4 ( %ff , %ff , %ff , %ff )", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2], &u.defaultVal[3])) { } else if ( 4 == sscanf( exp, " { %f , %f , %f , %f }", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2], &u.defaultVal[3])) { } else if ( 4 == sscanf( exp, " { %ff , %ff , %ff , %ff }", &u.defaultVal[0], &u.defaultVal[1], &u.defaultVal[2], &u.defaultVal[3])) { } else { u.defaultVal[0] = 0.0f; u.defaultVal[1] = 0.0f; u.defaultVal[2] = 0.0f; u.defaultVal[3] = 0.0f; } break; default: //make gcc happy break; }; } // // // //////////////////////////////////////////////////////////////////////////////// shader::SamplerType hlslFXShader::parseSamplerType( const char *type) { if (!strcmp( "sampler1D", type)) { return shader::st1D; } else if (!strcmp( "sampler2D", type)) { return shader::st2D; } else if (!strcmp( "sampler3D", type)) { return shader::st3D; } else if (!strcmp( "samplerCUBE", type)) { return shader::stCube; } //add sampler RECT stuff here return shader::stUnknown; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::updateHandles() { int offset = m_techniqueOffset[m_activeTechnique]; for ( int jj=0; jj::iterator it = m_uniformList.begin(); it < m_uniformList.end(); it++) { std::map< std::string, int>::const_iterator it2 = m_stateList[offset+jj]->m_vRegMap.find(it->name); if ( it2 != m_stateList[offset+jj]->m_vRegMap.end()) it->vReg[jj] = it2->second; else it->vReg[jj] = -1; it2 = m_stateList[offset+jj]->m_fRegMap.find(it->name); if ( it2 != m_stateList[offset+jj]->m_fRegMap.end()) it->fReg[jj] = it2->second; else it->fReg[jj] = -1; it->dirty = true; } { for (std::vector::iterator it = m_samplerList.begin(); it < m_samplerList.end(); it++) { std::map< std::string, int>::const_iterator it2 = m_stateList[offset+jj]->m_fRegMap.find(it->name); if ( it2 != m_stateList[offset+jj]->m_fRegMap.end()) it->texUnit[jj] = it2->second; else { it->texUnit[jj] = -1; } //this should only happen once per compile, we never remap samplers it->dirty = true; } } /* //workaround for AshliFX bug { for (std::vector::iterator it = m_samplerList.begin(); it < m_samplerList.end(); it++) { const char *formals=m_ashliList[jj]->getFormals(); formals = strstr( formals, "s "); int i0; char c0[64], c1[64], c2[64]; if (formals) { while (true) { sscanf( formals, " s %d %s %s %s", &i0, c0, c1, c2); if ( c2 == it->name) { break; } formals++; formals = strstr( formals, "s "); if (formals == NULL) { i0 = -1; break; } } } it->texUnit[jj] = i0; //this should only happen once per compile, we never remap samplers it->dirty = true; } } */ for (std::vector::iterator it2 = m_attributeList.begin(); it2 < m_attributeList.end(); it2++) { //it->handle = glGetAttribLocation( m_program, it->name); //nothing to mark dirty } } } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::buildShaders() { //clean up any old shaders void deleteShaders(); m_vShader.resize(m_passCount[m_activeTechnique], 0); m_fShader.resize(m_passCount[m_activeTechnique], 0); bool fail = false; int offset = m_techniqueOffset[m_activeTechnique]; GL_CHECK; for (int ii=0; ii 0) { //compile the vertex program const char *program = m_vertexShaders[offset+ii].c_str(); //clear any the errors while ( glGetError() != GL_NO_ERROR) ; glGenProgramsARB( 1, &m_vShader[ii]); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vShader[ii]); glProgramStringARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei) strlen(program), program); if (glGetError() != GL_NO_ERROR) { //program failed compile, get the info fail = true; const char* error = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); m_error += "Vertex shader failed compile\n "; m_error += error; m_error += "\n"; } } if ( m_fragmentShaders[offset+ii].length() > 0) { //compile the fragment program const char *program = m_fragmentShaders[offset+ii].c_str(); //clear any the errors while ( glGetError() != GL_NO_ERROR) ; glGenProgramsARB( 1, &m_fShader[ii]); glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fShader[ii]); glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei) strlen(program), program); if (glGetError() != GL_NO_ERROR) { //program failed compile, get the info fail = true; const char* error = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); m_error += "Fragment shader failed compile\n "; m_error += error; } } } if (fail) return false; return true; } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::valid() { return m_valid; } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::passCount() { if (m_techniqueCount) return m_passCount[m_activeTechnique]; return 0; } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::techniqueCount() { return m_techniqueCount; } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::techniqueName( int n) { if ( n::iterator it = m_uniformList.begin(); itdirty) { if (m_activePass == (m_passCount[m_activeTechnique]-1)) { //only mark it clean on the last pass it->dirty = false; } switch (it->type) { case shader::dtBool: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); break; case shader::dtBVec2: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); break; case shader::dtBVec3: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); break; case shader::dtBVec4: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal); break; case shader::dtInt: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); break; case shader::dtIVec2: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); break; case shader::dtIVec3: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); break; case shader::dtIVec4: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal); break; case shader::dtFloat: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[0], it->fVal[0], it->fVal[0]); break; case shader::dtVec2: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], 0.0f, 0.0f); break; case shader::dtVec3: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[1], it->fVal[2], 0.0f); break; case shader::dtVec4: if ( it->vReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal); if ( it->fReg[m_activePass] >= 0) glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal); break; case shader::dtMat2: if ( it->vReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[2], 0.0f, 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+1, it->fVal[1], it->fVal[3], 0.0f, 0.0f); } if ( it->fReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[2], 0.0f, 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+1, it->fVal[1], it->fVal[3], 0.0f, 0.0f); } break; case shader::dtMat3: if ( it->vReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[3], it->fVal[6], 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+1, it->fVal[1], it->fVal[4], it->fVal[7], 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+2, it->fVal[2], it->fVal[5], it->fVal[8], 0.0f); } if ( it->fReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[3], it->fVal[6], 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+1, it->fVal[1], it->fVal[4], it->fVal[7], 0.0f); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+2, it->fVal[2], it->fVal[5], it->fVal[8], 0.0f); } break; case shader::dtMat4: if ( it->vReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass], it->fVal[0], it->fVal[4], it->fVal[8], it->fVal[12]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+1, it->fVal[1], it->fVal[5], it->fVal[9], it->fVal[13]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+2, it->fVal[2], it->fVal[6], it->fVal[10], it->fVal[14]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->vReg[m_activePass]+3, it->fVal[3], it->fVal[7], it->fVal[11], it->fVal[15]); } if ( it->fReg[m_activePass] >= 0) { glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[4], it->fVal[8], it->fVal[12]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+1, it->fVal[1], it->fVal[5], it->fVal[9], it->fVal[13]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+2, it->fVal[2], it->fVal[6], it->fVal[10], it->fVal[14]); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, it->fReg[m_activePass]+3, it->fVal[3], it->fVal[7], it->fVal[11], it->fVal[15]); } break; default: //make gcc happy break; }; GL_CHECK; } } GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D, GL_TEXTURE_2D}; //update dirty samplers for (std::vector::iterator it2 = m_samplerList.begin(); it2texUnit[m_activePass] >= 0) { glActiveTexture( GL_TEXTURE0_ARB + it2->texUnit[m_activePass]); glBindTexture( targets[it2->type], it2->texObject); } } glActiveTexture( GL_TEXTURE0_ARB); GL_CHECK; //set up the render states m_stateList[m_techniqueOffset[m_activeTechnique] + m_activePass]->setState(); return; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::unbind() { glDisable( GL_FRAGMENT_PROGRAM_ARB); glDisable( GL_VERTEX_PROGRAM_ARB); GL_CHECK; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::setTechnique( int t) { if ( t != m_activeTechnique) { m_activeTechnique = t; m_stale = true; } } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::setPass( int p) { m_activePass = p; } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::uniformCount() { return (int)m_uniformList.size(); } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::samplerCount() { return (int)m_samplerList.size(); } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::attributeCount() { return (int)m_attributeList.size(); } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::uniformName(int i) { //should check for array bounds return m_uniformList[i].name.c_str(); } // // // //////////////////////////////////////////////////////////////////////////////// shader::DataType hlslFXShader::uniformType(int i) { //should check for array bounds return m_uniformList[i].type; } // // // //////////////////////////////////////////////////////////////////////////////// shader::Semantic hlslFXShader::uniformSemantic(int i) { //might want to check array bounds return m_uniformList[i].usage; } // // // //////////////////////////////////////////////////////////////////////////////// float* hlslFXShader::uniformDefault(int i) { //might want to check array bounds return m_uniformList[i].defaultVal; } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::samplerName(int i) { //should check for array bounds return m_samplerList[i].name.c_str(); } // // // //////////////////////////////////////////////////////////////////////////////// shader::SamplerType hlslFXShader::samplerType(int i) { //should check for array bounds return m_samplerList[i].type; } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::attributeName(int i) { //should check for array bounds return m_attributeList[i].name.c_str(); } // // // //////////////////////////////////////////////////////////////////////////////// shader::DataType hlslFXShader::attributeType(int i) { return m_attributeList[i].type; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::updateUniformBool( int i, bool val) { m_uniformList[i].fVal[0] = val ? 1.0f : 0.0f; m_uniformList[i].dirty = true; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::updateUniformInt( int i, int val) { m_uniformList[i].fVal[0] = (float)val; m_uniformList[i].dirty = true; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::updateUniformFloat( int i, float val) { m_uniformList[i].fVal[0] = val; m_uniformList[i].dirty = true; } // // // //////////////////////////////////////////////////////////////////////////////// void hlslFXShader::updateUniformBVec( int i, const bool* val) { for (int ii=0; ii>set) & 0x1) == 1; } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::usesTangent() { return m_tangent; } // // // //////////////////////////////////////////////////////////////////////////////// bool hlslFXShader::usesBinormal() { return m_binormal; } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::tangentSlot() { return m_tangentSlot; } // // // //////////////////////////////////////////////////////////////////////////////// int hlslFXShader::binormalSlot() { return m_binormalSlot; } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::errorString() { return m_error.c_str(); } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::getVertexShader( int pass) { if (m_activeTechnique < m_techniqueCount) { if ( pass < m_passCount[m_activeTechnique]) { return m_orgVertexShaders[m_techniqueOffset[m_activeTechnique]+pass].c_str(); } } return NULL; } // // // //////////////////////////////////////////////////////////////////////////////// const char* hlslFXShader::getPixelShader( int pass) { if (m_activeTechnique < m_techniqueCount) { if ( pass < m_passCount[m_activeTechnique]) { return m_orgFragmentShaders[m_techniqueOffset[m_activeTechnique]+pass].c_str(); } } return NULL; }