#include <algorithm>
#include "Platform.h"
#include "glslFXShader.h"
#include "ResourceManager.h"
#include "Platform.h"
glslFXShader::glslFXShader() : m_techniqueCount(0), m_valid(false), m_stale(false), m_color(true), m_activePass(0), m_activeTechnique(0), m_normal(true),
m_tangent(true), m_binormal(true), m_texMask(0x1), m_error("") {
}
glslFXShader::~glslFXShader() {
for (std::vector<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
delete *it;
}
deleteShaders();
}
void glslFXShader::deleteShaders() {
{
for (std::vector<GLuint>::iterator it=m_programList.begin(); it<m_programList.end(); it++) {
ResourceManager::destroyProgram( *it);
}
}
m_programList.clear();
{
for (std::vector<GLuint>::iterator it=m_vShaderList.begin(); it<m_vShaderList.end(); it++) {
ResourceManager::destroyProgram( *it);
}
}
m_vShaderList.clear();
{
for (std::vector<GLuint>::iterator it=m_fShaderList.begin(); it<m_fShaderList.end(); it++) {
ResourceManager::destroyProgram( *it);
}
}
m_fShaderList.clear();
}
bool glslFXShader::createFromFile( const char *filename) {
m_error = "";
IAshliFX *fx = new IAshliFX;
fx->init();
fx->setBinding( IAshliFX::GLSL);
fx->setFX( filename);
m_stale = true;
m_valid = false;
if (!fx->parse()) {
m_error = "Unable to load FX file\n ";
m_error += fx->getError();
delete fx;
return false;
}
if ( fx->getNumTechniques()) {
}
else {
m_error = "FX file lacked a valid shader";
delete fx;
return false;
}
if (!parseParameters(fx)) {
delete fx;
return false;
}
m_techniqueCount = fx->getNumTechniques();
m_techniqueNames.clear();
m_passCount.clear();
m_techniqueOffset.clear();
m_vertexShaders.clear();
m_fragmentShaders.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;
if (!fx->isVertexNull(ii,jj))
vString = fx->getVertexShader( ii, jj);
if (!fx->isPixelNull(ii,jj))
fString = fx->getPixelShader( ii, jj);
m_vertexShaders.push_back(vString);
m_fragmentShaders.push_back(fString);
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;
delete fx;
m_valid = true;
return true;
}
bool glslFXShader::createFromFX( IAshliFX *fx) {
m_error = "";
m_stale = true;
m_valid = false;
if ( fx->getNumTechniques()) {
}
else {
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();
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;
if (!fx->isVertexNull(ii,jj))
vString = fx->getVertexShader( ii, jj);
if (!fx->isPixelNull(ii,jj))
fString = fx->getPixelShader( ii, jj);
m_vertexShaders.push_back(vString);
m_fragmentShaders.push_back(fString);
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 = true;
return true;
}
bool glslFXShader::parseParameters(const IAshliFX *fx) {
int numPasses = 0, ii;
for (ii=0; ii<fx->getNumTechniques(); ii++) {
int count = fx->getNumPasses( ii);
numPasses = std::max<int>(numPasses, count);
}
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( "uniform", usage)) {
if (strncmp( "sampler", type, 7)) {
shader::DataType dt = parseUniformType( type);
shader::Semantic sm = parseUniformSemantic( semantic);
uniform u;
u.type = dt;
u.handle.resize( numPasses, -1);
u.usage = sm;
u.name = name;
parseExpression( u, expression);
m_uniformList.push_back(u);
}
else {
shader::SamplerType st = parseSamplerType( type);
sampler s;
s.handle.resize( numPasses, -1);
s.type = st;
s.texUnit.resize( numPasses, -1);
s.name = name;
m_samplerList.push_back(s);
}
}
else if (!strcmp( "attribute", usage)) {
shader::DataType dt = parseUniformType( type);
attribute a;
a.type = dt;
a.handle.resize( numPasses, -1);
a.name = name;
m_attributeList.push_back(a);
}
else {
}
}
return true;
}
shader::DataType glslFXShader::parseUniformType( const char *type) {
if (!strcmp( "float", type)) {
return shader::dtFloat;
}
else if (!strcmp( "vec2", type)) {
return shader::dtVec2;
}
else if (!strcmp( "vec3", type)) {
return shader::dtVec3;
}
else if (!strcmp( "vec4", type)) {
return shader::dtVec4;
}
else if (!strcmp( "int", type)) {
return shader::dtInt;
}
else if (!strcmp( "ivec2", type)) {
return shader::dtIVec2;
}
else if (!strcmp( "ivec3", type)) {
return shader::dtIVec3;
}
else if (!strcmp( "ivec4", type)) {
return shader::dtIVec4;
}
else if (!strcmp( "bool", type)) {
return shader::dtBool;
}
else if (!strcmp( "bvec2", type)) {
return shader::dtBVec2;
}
else if (!strcmp( "bvec3", type)) {
return shader::dtBVec3;
}
else if (!strcmp( "bvec4", type)) {
return shader::dtBVec4;
}
else if (!strcmp( "mat2", type)) {
return shader::dtMat2;
}
else if (!strcmp( "mat3", type)) {
return shader::dtMat3;
}
else if (!strcmp( "mat4", type)) {
return shader::dtMat4;
}
return shader::dtUnknown;
}
shader::Semantic glslFXShader::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 glslFXShader::parseExpression( glslFXShader::uniform &u, const char *exp) {
for (int ii=0; ii<16; ii++)
u.fDefault[ii] = 0.0f;
switch ( u.type) {
case shader::dtInt:
if ( 1 == sscanf( exp, " int ( %f )", &u.fDefault[0])) {
}
else if ( 1 == sscanf( exp, " %f ", &u.fDefault[0])) {
}
else {
u.iDefault[0] = 0;
}
break;
case shader::dtFloat:
if ( 1 == sscanf( exp, " float ( %f )", &u.fDefault[0])) {
}
else if ( 1 == sscanf( exp, " %f ", &u.fDefault[0])) {
}
else {
u.fDefault[0] = 0.0f;
}
break;
case shader::dtVec2:
if ( 2 != sscanf( exp, " vec2 ( %f , %f )", &u.fDefault[0], &u.fDefault[1])) {
u.fDefault[0] = 0.0f;
u.fDefault[1] = 0.0f;
}
break;
case shader::dtVec3:
if ( 3 != sscanf( exp, " vec3 ( %f , %f , %f )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2])) {
u.fDefault[0] = 0.0f;
u.fDefault[1] = 0.0f;
u.fDefault[2] = 0.0f;
}
break;
case shader::dtVec4:
if ( 4 != sscanf( exp, " vec4 ( %f , %f , %f , %f )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2], &u.fDefault[3])) {
u.fDefault[0] = 0.0f;
u.fDefault[1] = 0.0f;
u.fDefault[2] = 0.0f;
u.fDefault[3] = 0.0f;
}
break;
default:
break;
};
}
shader::SamplerType glslFXShader::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;
}
else if (!strcmp( "sampler1DShadow", type)) {
return shader::st1DShadow;
}
else if (!strcmp( "sampler2DShadow", type)) {
return shader::st2DShadow;
}
return shader::stUnknown;
}
void glslFXShader::updateHandles() {
int passNum=0;
for (std::vector<GLuint>::iterator pit=m_programList.begin(); pit<m_programList.end(); pit++,passNum++) {
int texNum = 0;
{
for (std::vector<uniform>::iterator it = m_uniformList.begin(); it < m_uniformList.end(); it++) {
it->handle[passNum] = glGetUniformLocation( *pit, it->name.c_str());
it->dirty = true;
}
}
{
for (std::vector<sampler>::iterator it = m_samplerList.begin(); it < m_samplerList.end(); it++) {
it->handle[passNum] = glGetUniformLocation( *pit, it->name.c_str());
it->texUnit[passNum] = texNum++;
it->dirty = true;
}
}
{
for (std::vector<attribute>::iterator it = m_attributeList.begin(); it < m_attributeList.end(); it++) {
it->handle[passNum] = glGetAttribLocation( *pit, it->name.c_str());
}
}
}
}
bool glslFXShader::buildShaders() {
deleteShaders();
m_programList.resize( m_passCount[m_activeTechnique], 0);
m_vShaderList.resize( m_passCount[m_activeTechnique], 0);
m_fShaderList.resize( m_passCount[m_activeTechnique], 0);
int offset = m_techniqueOffset[m_activeTechnique];
for (int ii=0; ii<m_passCount[m_activeTechnique]; ii++) {
GLuint program = glCreateProgramObject();
m_programList[ii] = program;
bool fail = false;
GL_CHECK;
if (m_vertexShaders[offset+ii].length() > 0) {
const char* temp;
GLuint vShader = glCreateShaderObject( GL_VERTEX_SHADER);
m_vShaderList[ii] = vShader;
glAttachObject( program, vShader);
temp = m_vertexShaders[offset+ii].c_str();
glShaderSource( vShader, 1, &temp, NULL);
glCompileShader(vShader);
GLint success;
glGetObjectParameteriv( vShader, GL_COMPILE_STATUS, &success);
if (!success) {
char log[256];
glGetInfoLog( vShader, 256, NULL, log);
fail = true;
m_error = "Vertex shader failed compile:\n";
m_error += log;
m_error += "\n";
}
}
GL_CHECK;
if (m_fragmentShaders[offset+ii].length() > 0) {
const char* temp;
GLuint fShader = glCreateShaderObject( GL_FRAGMENT_SHADER);
m_fShaderList[ii] = fShader;
glAttachObject( program, fShader);
temp = m_fragmentShaders[offset+ii].c_str();
glShaderSource( fShader, 1, &temp, NULL);
glCompileShader(fShader);
GLint success;
glGetObjectParameteriv( fShader, GL_COMPILE_STATUS, &success);
if (!success) {
char log[256];
glGetInfoLog( fShader, 256, NULL, log);
fail = true;
m_error += "Fragment shader failed compile:\n";
m_error += log;
}
}
GL_CHECK;
if (fail) {
glDeleteObject( m_programList[ii]);
m_programList[ii] = 0;
if (m_fShaderList[ii]) {
glDeleteObject( m_fShaderList[ii]);
m_fShaderList[ii] = 0;
}
if (m_vShaderList[ii]) {
glDeleteObject( m_vShaderList[ii]);
m_vShaderList[ii] = 0;
}
return false;
}
glLinkProgram(program);
GLint success;
glGetObjectParameteriv( program, GL_LINK_STATUS, &success);
if (!success) {
char log[256];
glGetInfoLog( program, 256, NULL, log);
m_error = "Link failed:\n";
m_error += log;
glDeleteObject( m_programList[ii]);
m_programList[ii] = 0;
if (m_fShaderList[ii]) {
glDeleteObject( m_fShaderList[ii]);
m_fShaderList[ii] = 0;
}
if (m_vShaderList[ii]) {
glDeleteObject( m_vShaderList[ii]);
m_vShaderList[ii] = 0;
}
GL_CHECK;
return false;
}
GL_CHECK;
}
return true;
}
bool glslFXShader::valid() {
return m_valid;
}
int glslFXShader::passCount() {
if (m_techniqueCount)
return m_passCount[m_activeTechnique];
return 0;
}
int glslFXShader::techniqueCount() {
return m_techniqueCount;
}
const char* glslFXShader::techniqueName( int n) {
if ( n<m_techniqueCount)
return m_techniqueNames[n].c_str();
return NULL;
}
bool glslFXShader::build() {
if (m_stale) {
m_stale = false;
if (!buildShaders())
return false;
updateHandles();
}
return true;
}
void glslFXShader::bind() {
glUseProgramObject( m_programList[m_activePass]);
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->handle[m_activePass] != -1) {
if (it2->dirty) {
glUniform1i( it2->handle[m_activePass], it2->texUnit[m_activePass]);
}
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();
GL_CHECK;
return;
}
void glslFXShader::setShapeDependentState() {
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;
if ( it->handle[m_activePass] == -1)
continue;
switch (it->type) {
case shader::dtBool:
glUniform1i( it->handle[m_activePass], it->iVal[0]);
break;
case shader::dtBVec2:
glUniform2iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtBVec3:
glUniform3iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtBVec4:
glUniform4iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtInt:
glUniform1i( it->handle[m_activePass], it->iVal[0]);
break;
case shader::dtIVec2:
glUniform2iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtIVec3:
glUniform3iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtIVec4:
glUniform4iv( it->handle[m_activePass], 1, it->iVal);
break;
case shader::dtFloat:
glUniform1f( it->handle[m_activePass], it->fVal[0]);
break;
case shader::dtVec2:
glUniform2fv( it->handle[m_activePass], 1, it->fVal);
break;
case shader::dtVec3:
glUniform3fv( it->handle[m_activePass], 1, it->fVal);
break;
case shader::dtVec4:
glUniform4fv( it->handle[m_activePass], 1, it->fVal);
break;
case shader::dtMat2:
glUniformMatrix2fv( it->handle[m_activePass], 1, false, it->fVal);
break;
case shader::dtMat3:
glUniformMatrix3fv( it->handle[m_activePass], 1, false, it->fVal);
break;
case shader::dtMat4:
glUniformMatrix4fv( it->handle[m_activePass], 1, false, it->fVal);
break;
default:
break;
};
GL_CHECK;
}
}
return;
}
void glslFXShader::unbind() {
glUseProgramObject(0);
}
void glslFXShader::setTechnique( int t) {
if ( t != m_activeTechnique) {
m_activeTechnique = t;
m_stale = true;
}
}
void glslFXShader::setPass( int p) {
m_activePass = p;
}
int glslFXShader::uniformCount() {
return (int)m_uniformList.size();
}
int glslFXShader::samplerCount() {
return (int)m_samplerList.size();
}
int glslFXShader::attributeCount() {
return (int)m_attributeList.size();
}
const char* glslFXShader::uniformName(int i) {
return m_uniformList[i].name.c_str();
}
shader::DataType glslFXShader::uniformType(int i) {
return m_uniformList[i].type;
}
shader::Semantic glslFXShader::uniformSemantic(int i) {
return m_uniformList[i].usage;
}
float* glslFXShader::uniformDefault(int i) {
return m_uniformList[i].fDefault;
}
const char* glslFXShader::samplerName(int i) {
return m_samplerList[i].name.c_str();
}
shader::SamplerType glslFXShader::samplerType(int i) {
return m_samplerList[i].type;
}
const char* glslFXShader::attributeName(int i) {
return m_attributeList[i].name.c_str();
}
shader::DataType glslFXShader::attributeType(int i) {
return m_attributeList[i].type;
}
int glslFXShader::attributeHandle(int i) {
return m_attributeList[i].handle[m_activePass];
}
void glslFXShader::updateUniformBool( int i, bool val) {
m_uniformList[i].iVal[0] = val ? 1 : 0;
m_uniformList[i].dirty = true;
}
void glslFXShader::updateUniformInt( int i, int val) {
m_uniformList[i].iVal[0] = val;
m_uniformList[i].dirty = true;
}
void glslFXShader::updateUniformFloat( int i, float val) {
m_uniformList[i].fVal[0] = val;
m_uniformList[i].dirty = true;
}
void glslFXShader::updateUniformBVec( int i, const bool* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].iVal[ii] = val[ii] ? 0 : 1;
}
m_uniformList[i].dirty = true;
}
void glslFXShader::updateUniformIVec( int i, const int* val) {
for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
m_uniformList[i].iVal[ii] = val[ii];
}
m_uniformList[i].dirty = true;
}
void glslFXShader::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 glslFXShader::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 glslFXShader::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 glslFXShader::updateSampler( int i, unsigned int val) {
m_samplerList[i].texObject = val;
}
bool glslFXShader::usesColor() {
return m_color;
}
bool glslFXShader::usesNormal() {
return m_normal;
}
bool glslFXShader::usesTexCoord( int set) {
return ((m_texMask>>set) & 0x1) == 1;
}
bool glslFXShader::usesTangent() {
return m_tangent;
}
bool glslFXShader::usesBinormal() {
return m_binormal;
}
int glslFXShader::tangentSlot() {
return m_tangentSlot;
}
int glslFXShader::binormalSlot() {
return m_binormalSlot;
}
const char* glslFXShader::errorString() {
return m_error.c_str();
}
const char* glslFXShader::getVertexShader( int pass) {
if (m_activeTechnique < m_techniqueCount) {
if ( pass < m_passCount[m_activeTechnique]) {
return m_vertexShaders[m_techniqueOffset[m_activeTechnique]+pass].c_str();
}
}
return NULL;
}
const char* glslFXShader::getPixelShader( int pass) {
if (m_activeTechnique < m_techniqueCount) {
if ( pass < m_passCount[m_activeTechnique]) {
return m_fragmentShaders[m_techniqueOffset[m_activeTechnique]+pass].c_str();
}
}
return NULL;
}