#include <maya/MGlobal.h>
#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<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
delete *it;
}
deleteShaders();
}
void hlslFXShader::deleteShaders() {
{
for (std::vector<GLuint>::iterator it = m_vShader.begin(); it < m_vShader.end(); it++) {
ResourceManager::destroyAsmProgram( *it);
}
}
m_vShader.clear();
{
for (std::vector<GLuint>::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);
m_stale = true;
try {
if (!fx->parse()) {
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 {
delete fx;
m_error = "FX file lacked a valid shader";
return false;
}
if (!parseParameters(fx))
return false;
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<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
delete *it;
}
m_stateList.clear();
int totalPasses =0;
stateObserver *observer = new stateObserver;
fx->attach( (IObserveFX*)observer);
for (int ii=0; ii<m_techniqueCount; ii++) {
int passCount = fx->getNumPasses(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; jj<passCount; jj++) {
std::string vString;
std::string fString;
std::string orgVString;
std::string orgFString;
IAshli *ashli = new IAshli;
ashli->setNative(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("")) {
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 {
const char* error = ashli->getError();
m_error = "Shader failed to compile\n";
m_error += error;
m_error += std::string("\n");
}
m_vertexShaders.push_back(vString);
m_fragmentShaders.push_back(fString);
m_orgVertexShaders.push_back(orgVString);
m_orgFragmentShaders.push_back(orgFString);
m_stateList.push_back(new passState);
observer->setPassMonitor(m_stateList.back());
for (int kk=0; kk<fx->getNumStates( 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;
int maxVInstructions, maxVTemps, maxVParameters, maxALU, maxTexInst, maxTexIndirections,
maxFInstructions, maxFTemps, maxFParameters;
if (fx->getNumTechniques()) {
}
else {
m_error = "FX file lacked a valid shader";
return false;
}
if (!parseParameters(fx))
return false;
glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &maxVInstructions);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &maxFInstructions);
glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &maxVTemps);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &maxFTemps);
glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &maxVParameters);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &maxFParameters);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &maxALU);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, &maxTexInst);
glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, &maxTexIndirections);
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<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
delete *it;
}
m_stateList.clear();
int totalPasses =0;
stateObserver *observer = new stateObserver;
fx->attach( (IObserveFX*)observer);
bool success = true;
for (int ii=0; ii<m_techniqueCount; ii++) {
int passCount = fx->getNumPasses(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; jj<passCount; jj++) {
std::string vString;
std::string fString;
std::string orgVString;
std::string orgFString;
IAshli *ashli = new IAshli;
ashli->setNative(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);
ashli->setResource( IAshli::Vertex, IAshli::InstructionSlots, maxVInstructions);
ashli->setResource( IAshli::Vertex, IAshli::ALUInstructions, maxVInstructions);
ashli->setResource( IAshli::Vertex, IAshli::FloatConstantRegisters, maxVParameters);
ashli->setResource( IAshli::Vertex, IAshli::TemporaryRegisters, maxVTemps);
ashli->setResource( IAshli::Pixel, IAshli::InstructionSlots, maxFInstructions);
ashli->setResource( IAshli::Pixel, IAshli::ALUInstructions, maxALU);
ashli->setResource( IAshli::Pixel, IAshli::TextureInstructions, maxTexInst);
ashli->setResource( IAshli::Pixel, IAshli::TextureDependency, maxTexIndirections);
ashli->setResource( IAshli::Pixel, IAshli::FloatConstantRegisters, maxFParameters);
ashli->setResource( IAshli::Pixel, IAshli::TemporaryRegisters, maxFTemps);
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("")) {
if ( ashli->getNumSegments() == 1 ) {
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 {
success = false;
m_error = "Shader exceeded available resources\n";
}
}
else {
success = false;
const char* error = ashli->getError();
m_error = "Shader failed to compile\n";
m_error += error;
m_error += std::string("\n");
}
m_vertexShaders.push_back(vString);
m_fragmentShaders.push_back(fString);
m_orgVertexShaders.push_back(orgVString);
m_orgFragmentShaders.push_back(orgFString);
m_stateList.push_back(new passState);
observer->setPassMonitor(m_stateList.back());
for (int kk=0; kk<fx->getNumStates( ii,jj); kk++) {
fx->getStateItem( ii, jj, kk);
}
observer->finalizePassMonitor();
}
totalPasses += passCount;
}
fx->attach(NULL);
delete observer;
m_valid = success;
return success;
}
bool hlslFXShader::parseParameters(const IAshliFX *fx) {
int passCount =0, ii;
for (ii=0; ii<fx->getNumTechniques(); ii++) {
passCount = std::max<int>( fx->getNumPasses(ii), passCount);
}
for (ii=0; ii<fx->getNumParameters(); 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)) {
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;
parseExpression( u, expression);
if (dt != shader::dtString)
m_uniformList.push_back(u);
}
else {
shader::SamplerType st = parseSamplerType( type);
sampler s;
s.texUnit.resize( passCount, -1);
s.type = st;
s.name = name;
m_samplerList.push_back(s);
}
}
else {
}
}
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;
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;
}
else if (!strcasecmp( "ViewPosition", semantic)) {
return smViewPosition;
}
else if (!strcasecmp( "Time", semantic)) {
return smTime;
}
else if (!strcasecmp( "RenderTargetDimensions", semantic)) {
return smViewportSize;
}
else if (!strcasecmp( "Ambient", semantic)) {
return smAmbient;
}
else if (!strcasecmp( "Diffuse", semantic)) {
return smDiffuse;
}
else if (!strcasecmp( "Emissive", semantic)) {
return smEmissive;
}
else if (!strcasecmp( "Specular", semantic)) {
return smSpecular;
}
else if (!strcasecmp( "Opacity", semantic)) {
return smOpacity;
}
else if (!strcasecmp( "SpecularPower", semantic)) {
return smSpecularPower;
}
else if (!strcasecmp( "Height", semantic)) {
return smHeight;
}
else if (!strcasecmp( "Normal", semantic)) {
return smNormal;
}
return shader::smUnknown;
}
void hlslFXShader::parseExpression( hlslFXShader::uniform &u, const char *exp) {
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:
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;
}
return shader::stUnknown;
}
void hlslFXShader::updateHandles() {
int offset = m_techniqueOffset[m_activeTechnique];
for ( int jj=0; jj<m_passCount[m_activeTechnique]; jj++) {
for (std::vector<uniform>::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<sampler>::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;
}
it->dirty = true;
}
}
for (std::vector<attribute>::iterator it2 = m_attributeList.begin(); it2 < m_attributeList.end(); it2++) {
}
}
}
bool hlslFXShader::buildShaders() {
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<m_passCount[m_activeTechnique]; ii++) {
if ( m_vertexShaders[offset+ii].length() > 0) {
const char *program = m_vertexShaders[offset+ii].c_str();
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) {
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) {
const char *program = m_fragmentShaders[offset+ii].c_str();
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) {
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<m_techniqueCount)
return m_techniqueNames[n].c_str();
return NULL;
}
bool hlslFXShader::build() {
if (m_stale) {
m_stale = false;
if (!buildShaders())
return false;
updateHandles();
}
return true;
}
void hlslFXShader::bind() {
GL_CHECK;
if (m_fShader[m_activePass]) {
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fShader[m_activePass]);
glEnable( GL_FRAGMENT_PROGRAM_ARB);
}
if (m_vShader[m_activePass]) {
glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vShader[m_activePass]);
glEnable( GL_VERTEX_PROGRAM_ARB);
}
GL_CHECK;
GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D, GL_TEXTURE_2D};
for (std::vector<sampler>::iterator it2 = m_samplerList.begin(); it2<m_samplerList.end(); it2++) {
if (it2->texUnit[m_activePass] >= 0) {
glActiveTexture( GL_TEXTURE0_ARB + it2->texUnit[m_activePass]);
glBindTexture( targets[it2->type], it2->texObject);
}
}
glActiveTexture( GL_TEXTURE0_ARB);
GL_CHECK;
m_stateList[m_techniqueOffset[m_activeTechnique] + m_activePass]->setState();
return;
}
void hlslFXShader::setShapeDependentState() {
GL_CHECK;
for (std::vector<uniform>::iterator it = m_uniformList.begin(); it<m_uniformList.end(); it++) {
if ( it->dirty) {
if (m_activePass == (m_passCount[m_activeTechnique]-1)) {
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_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[2], 0.0f, 0.0f);
glProgramLocalParameter4fARB( GL_FRAGMENT_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_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[3], it->fVal[6], 0.0f);
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass]+1, it->fVal[1], it->fVal[4], it->fVal[7], 0.0f);
glProgramLocalParameter4fARB( GL_FRAGMENT_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_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass], it->fVal[0], it->fVal[4], it->fVal[8], it->fVal[12]);
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass]+1, it->fVal[1], it->fVal[5], it->fVal[9], it->fVal[13]);
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass]+2, it->fVal[2], it->fVal[6], it->fVal[10], it->fVal[14]);
glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, it->fReg[m_activePass]+3, it->fVal[3], it->fVal[7], it->fVal[11], it->fVal[15]);
}
break;
default:
break;
};
GL_CHECK;
}
}
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) {
return m_uniformList[i].name.c_str();
}
shader::DataType hlslFXShader::uniformType(int i) {
return m_uniformList[i].type;
}
shader::Semantic hlslFXShader::uniformSemantic(int i) {
return m_uniformList[i].usage;
}
float* hlslFXShader::uniformDefault(int i) {
return m_uniformList[i].defaultVal;
}
const char* hlslFXShader::samplerName(int i) {
return m_samplerList[i].name.c_str();
}
shader::SamplerType hlslFXShader::samplerType(int i) {
return m_samplerList[i].type;
}
const char* hlslFXShader::attributeName(int i) {
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<size(m_uniformList[i].type); ii++) {
m_uniformList[i].fVal[ii] = val[ii] ? 0.0f : 1.0f;
}
m_uniformList[i].dirty = true;
}
void hlslFXShader::updateUniformIVec( int i, const int* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].fVal[ii] = (float)val[ii];
}
m_uniformList[i].dirty = true;
}
void hlslFXShader::updateUniformVec( int i, const float* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].fVal[ii] = val[ii];
}
m_uniformList[i].dirty = true;
}
void hlslFXShader::updateUniformMat( int i, const float* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].fVal[ii] = val[ii];
}
m_uniformList[i].dirty = true;
}
void hlslFXShader::updateUniformMat( int i, const double* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].fVal[ii] = (float)val[ii];
}
m_uniformList[i].dirty = true;
}
void hlslFXShader::updateSampler( int i, unsigned int val) {
m_samplerList[i].texObject = val;
}
bool hlslFXShader::usesColor() {
return m_color;
}
bool hlslFXShader::usesNormal() {
return m_normal;
}
bool hlslFXShader::usesTexCoord( int set) {
return ((m_texMask>>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;
}