907 lines
23 KiB
C++
907 lines
23 KiB
C++
|
|
/********************************************************************
|
||
|
|
aGLSL.cpp
|
||
|
|
Version: 0.9.4 - For OpenGL 2.0
|
||
|
|
|
||
|
|
License: BSD
|
||
|
|
(c) 2003-2005 by Martin Christen. All Rights reserved.
|
||
|
|
*********************************************************************/
|
||
|
|
|
||
|
|
#include "glsl.h"
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
// Error, Warning and Info Strings
|
||
|
|
char* aGLSLStrings[] = {
|
||
|
|
"[e00] GLSL is not available!",
|
||
|
|
"[e01] Not a valid program object!",
|
||
|
|
"[e02] Not a valid object!",
|
||
|
|
"[e03] Out of memory!",
|
||
|
|
"[e04] Unknown compiler error!",
|
||
|
|
"[e05] Linker log is not available!",
|
||
|
|
"[e06] Compiler log is not available!",
|
||
|
|
"[Empty]"
|
||
|
|
};
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
// GL ERROR CHECK
|
||
|
|
int CheckGLError(char *file, int line)
|
||
|
|
{
|
||
|
|
//return 0;
|
||
|
|
GLenum glErr,glErr2;
|
||
|
|
int retCode = 0;
|
||
|
|
|
||
|
|
glErr = glErr2 = glGetError();
|
||
|
|
while (glErr != GL_NO_ERROR)
|
||
|
|
{
|
||
|
|
char* str1 = (char*)gluErrorString(glErr);
|
||
|
|
if (str1)
|
||
|
|
cout << "GL Error #" << glErr << "(" << str1 << ") " << " in File " << file << " at line: " << line << endl;
|
||
|
|
else
|
||
|
|
cout << "GL Error #" << glErr << " in File " << file << " at line: " << line << endl;
|
||
|
|
retCode = 1;
|
||
|
|
glErr = glGetError();
|
||
|
|
}
|
||
|
|
if (glErr2 != GL_NO_ERROR) while(1)Sleep(100);;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
// ************************************************************************
|
||
|
|
// Implementation of glShader class
|
||
|
|
// ************************************************************************
|
||
|
|
|
||
|
|
glShader::glShader()
|
||
|
|
{
|
||
|
|
ProgramObject = 0;
|
||
|
|
linker_log = 0;
|
||
|
|
is_linked = false;
|
||
|
|
enabled = false;
|
||
|
|
_mM = false;
|
||
|
|
_noshader = true;
|
||
|
|
|
||
|
|
ProgramObject = glCreateProgram();
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
glShader::~glShader()
|
||
|
|
{
|
||
|
|
if (linker_log!=0) free(linker_log);
|
||
|
|
|
||
|
|
for (unsigned int i=0;i<ShaderList.size();i++)
|
||
|
|
{
|
||
|
|
glDetachShader(ProgramObject, ShaderList[i]->ShaderObject);
|
||
|
|
CHECK_GL_ERROR(); // if you get an error here, you deleted the Program object first and then
|
||
|
|
// the ShaderObject! Always delete ShaderObjects last!
|
||
|
|
if (_mM) delete ShaderList[i];
|
||
|
|
}
|
||
|
|
glDeleteShader(ProgramObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
void glShader::addShader(glShaderObject* ShaderProgram)
|
||
|
|
{
|
||
|
|
if (ShaderProgram==0) return;
|
||
|
|
if (!ShaderProgram->is_compiled)
|
||
|
|
{
|
||
|
|
cout << "**warning** please compile program before adding object! trying to compile now...\n";
|
||
|
|
if (!ShaderProgram->compile())
|
||
|
|
{
|
||
|
|
cout << "...compile ERROR!\n";
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
cout << "...ok!\n";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
ShaderList.push_back(ShaderProgram);
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::link(void)
|
||
|
|
{
|
||
|
|
unsigned int i;
|
||
|
|
|
||
|
|
if (is_linked) // already linked, detach everything first
|
||
|
|
{
|
||
|
|
cout << "**warning** Object is already linked, trying to link again" << endl;
|
||
|
|
for (i=0;i<ShaderList.size();i++)
|
||
|
|
{
|
||
|
|
glDetachShader(ProgramObject, ShaderList[i]->ShaderObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i=0;i<ShaderList.size();i++)
|
||
|
|
{
|
||
|
|
glAttachShader(ProgramObject, ShaderList[i]->ShaderObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
//cout << "attaching ProgramObj [" << i << "] @ 0x" << hex << ShaderList[i]->ProgramObject << " in ShaderObj @ 0x" << ShaderObject << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
int linked;
|
||
|
|
glLinkProgram(ProgramObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
if (linked)
|
||
|
|
{
|
||
|
|
is_linked = true;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
cout << "**linker error**\n";
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
// Compiler Log: Ausgabe der Compiler Meldungen in String
|
||
|
|
|
||
|
|
char* glShader::getLinkerLog(void)
|
||
|
|
{
|
||
|
|
int blen = 0;
|
||
|
|
int slen = 0;
|
||
|
|
|
||
|
|
if (ProgramObject==0) return aGLSLStrings[2];
|
||
|
|
glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH , &blen);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
if (blen > 1)
|
||
|
|
{
|
||
|
|
if (linker_log!=0)
|
||
|
|
{
|
||
|
|
free(linker_log);
|
||
|
|
linker_log =0;
|
||
|
|
}
|
||
|
|
if ((linker_log = (GLcharARB*)malloc(blen)) == NULL)
|
||
|
|
{
|
||
|
|
printf("ERROR: Could not allocate compiler_log buffer\n");
|
||
|
|
return aGLSLStrings[3];
|
||
|
|
}
|
||
|
|
|
||
|
|
glGetProgramInfoLog(ProgramObject, blen, &slen, linker_log);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
if (linker_log!=0)
|
||
|
|
return (char*) linker_log;
|
||
|
|
else
|
||
|
|
return aGLSLStrings[5];
|
||
|
|
|
||
|
|
return aGLSLStrings[4];
|
||
|
|
}
|
||
|
|
|
||
|
|
void glShader::begin(void)
|
||
|
|
{
|
||
|
|
enabled = true;
|
||
|
|
|
||
|
|
if (ProgramObject == 0) return;
|
||
|
|
if (!_noshader) return;
|
||
|
|
|
||
|
|
if (is_linked)
|
||
|
|
{
|
||
|
|
glUseProgram(ProgramObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
void glShader::end(void)
|
||
|
|
{
|
||
|
|
enabled = false;
|
||
|
|
|
||
|
|
if (!_noshader) return;
|
||
|
|
glUseProgram(0);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform1f(char* varname, GLfloat v0)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform1f(loc, v0);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform2f(char* varname, GLfloat v0, GLfloat v1)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform2f(loc, v0, v1);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform3f(char* varname, GLfloat v0, GLfloat v1, GLfloat v2)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform3f(loc, v0, v1, v2);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform4f(char* varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform4f(loc, v0, v1, v2, v3);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform1i(char* varname, GLint v0)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform1i(loc, v0);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
bool glShader::setUniform2i(char* varname, GLint v0, GLint v1)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform2i(loc, v0, v1);
|
||
|
|
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform3i(char* varname, GLint v0, GLint v1, GLint v2)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform3i(loc, v0, v1, v2);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
bool glShader::setUniform4i(char* varname, GLint v0, GLint v1, GLint v2, GLint v3)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform4i(loc, v0, v1, v2, v3);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform1fv(char* varname, GLsizei count, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform1fv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
bool glShader::setUniform2fv(char* varname, GLsizei count, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform2fv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform3fv(char* varname, GLsizei count, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform3fv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform4fv(char* varname, GLsizei count, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform4fv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform1iv(char* varname, GLsizei count, GLint *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform1iv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform2iv(char* varname, GLsizei count, GLint *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform2iv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform3iv(char* varname, GLsizei count, GLint *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform3iv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniform4iv(char* varname, GLsizei count, GLint *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniform4iv(loc, count, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniformMatrix2fv(char* varname, GLsizei count, GLboolean transpose, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniformMatrix2fv(loc, count, transpose, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniformMatrix3fv(char* varname, GLsizei count, GLboolean transpose, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniformMatrix3fv(loc, count, transpose, value);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShader::setUniformMatrix4fv(char* varname, GLsizei count, GLboolean transpose, GLfloat *value)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
GLint loc = GetUniLoc(varname);
|
||
|
|
if (loc==-1) return false; // can't find variable
|
||
|
|
|
||
|
|
glUniformMatrix4fv(loc, count, transpose, value);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
GLint glShader::GetUniLoc(const GLcharARB *name)
|
||
|
|
{
|
||
|
|
GLint loc;
|
||
|
|
|
||
|
|
loc = glGetUniformLocation(ProgramObject, name);
|
||
|
|
if (loc == -1)
|
||
|
|
{
|
||
|
|
cout << "Error: can't find uniform variable \"" << name << "\"\n";
|
||
|
|
}
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
return loc;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
void glShader::GetUniformfv(char* name, GLfloat* values)
|
||
|
|
{
|
||
|
|
GLint loc;
|
||
|
|
|
||
|
|
loc = glGetUniformLocation(ProgramObject, name);
|
||
|
|
if (loc == -1)
|
||
|
|
{
|
||
|
|
cout << "Error: can't find uniform variable \"" << name << "\"\n";
|
||
|
|
}
|
||
|
|
glGetUniformfv(ProgramObject, loc, values);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
void glShader::GetUniformiv(char* name, GLint* values)
|
||
|
|
{
|
||
|
|
GLint loc;
|
||
|
|
|
||
|
|
loc = glGetUniformLocation(ProgramObject, name);
|
||
|
|
if (loc == -1)
|
||
|
|
{
|
||
|
|
cout << "Error: can't find uniform variable \"" << name << "\"\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
glGetUniformiv(ProgramObject, loc, values);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
bool glShader::setVertexAttrib1f(GLuint index, GLfloat v0)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
glVertexAttrib1f(index, v0);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool glShader::setVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
glVertexAttrib2f(index, v0, v1);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool glShader::setVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
glVertexAttrib3f(index, v0, v1, v2);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool glShader::setVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
|
||
|
|
{
|
||
|
|
if (!_noshader) return true;
|
||
|
|
|
||
|
|
glVertexAttrib4f(index, v0, v1, v2, v3);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ************************************************************************
|
||
|
|
// Shader Program : Manage Shader Programs (Vertex/Fragment)
|
||
|
|
// ************************************************************************
|
||
|
|
|
||
|
|
|
||
|
|
glShaderObject::glShaderObject(int type)
|
||
|
|
{
|
||
|
|
program_type = type;
|
||
|
|
program_str = "empty";
|
||
|
|
|
||
|
|
if (type==GL_VERTEX_SHADER) program_str=string("GL_VERTEX_SHADER");
|
||
|
|
if (type==GL_TESS_CONTROL_SHADER) program_str=string("GL_TESS_CONTROL_SHADER");
|
||
|
|
if (type==GL_TESS_EVALUATION_SHADER) program_str=string("GL_TESS_EVALUATION_SHADER");
|
||
|
|
if (type==GL_GEOMETRY_SHADER) program_str=string("GL_GEOMETRY_SHADER");
|
||
|
|
if (type==GL_FRAGMENT_SHADER) program_str=string("GL_FRAGMENT_SHADER");
|
||
|
|
|
||
|
|
//GL_VERTEX_SHADER
|
||
|
|
//GL_TESS_CONTROL_SHADER
|
||
|
|
//GL_TESS_EVALUATION_SHADER
|
||
|
|
//GL_GEOMETRY_SHADER
|
||
|
|
//GL_FRAGMENT_SHADER
|
||
|
|
|
||
|
|
ShaderObject = glCreateShaderObjectARB(type);
|
||
|
|
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
compiler_log = 0;
|
||
|
|
is_compiled = false;
|
||
|
|
ShaderObject = 0;
|
||
|
|
ShaderSource = 0;
|
||
|
|
_memalloc = false;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
glShaderObject::~glShaderObject()
|
||
|
|
{
|
||
|
|
if (compiler_log!=0) free(compiler_log);
|
||
|
|
if (ShaderSource!=0)
|
||
|
|
{
|
||
|
|
if (_memalloc)
|
||
|
|
delete[] ShaderSource; // free ASCII Source
|
||
|
|
}
|
||
|
|
|
||
|
|
if (is_compiled)
|
||
|
|
{
|
||
|
|
glDeleteObjectARB(ShaderObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
unsigned long getFileLength(ifstream& file)
|
||
|
|
{
|
||
|
|
if(!file.good()) return 0;
|
||
|
|
|
||
|
|
unsigned long pos=file.tellg();
|
||
|
|
file.seekg(0,ios::end);
|
||
|
|
unsigned long len = file.tellg();
|
||
|
|
file.seekg(ios::beg);
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
int glShaderObject::load(char* filename)
|
||
|
|
{
|
||
|
|
printf("Loading Shader %s ...\n",filename);
|
||
|
|
|
||
|
|
ifstream file;
|
||
|
|
file.open(filename, ios::in);
|
||
|
|
if(!file)
|
||
|
|
{
|
||
|
|
printf("File not found :%s ...\n",filename);
|
||
|
|
while(1);
|
||
|
|
};
|
||
|
|
|
||
|
|
unsigned long len = getFileLength(file);
|
||
|
|
file.close();
|
||
|
|
|
||
|
|
if (len==0) return -2; // "Empty File"
|
||
|
|
|
||
|
|
if (ShaderSource!=0) // there is already a source loaded, free it!
|
||
|
|
{
|
||
|
|
if (_memalloc)
|
||
|
|
delete[] ShaderSource;
|
||
|
|
}
|
||
|
|
|
||
|
|
ShaderSource = (GLubyte*) new char[len+1];
|
||
|
|
if (ShaderSource == 0) return -3; // can't reserve memory
|
||
|
|
_memalloc = true;
|
||
|
|
|
||
|
|
printf("Loading Shader %s ...\n",filename);
|
||
|
|
ShaderSource[len] = 0; // len isn't always strlen cause some characters are stripped in ascii read...
|
||
|
|
// it is important to 0-terminate the real length later, len is just max possible value...
|
||
|
|
|
||
|
|
FILE* fn=fopen(filename, "rb");
|
||
|
|
fseek(fn,0,SEEK_SET);
|
||
|
|
int numbytes=(int)fread(ShaderSource, 1 , len, fn);
|
||
|
|
fclose(fn);
|
||
|
|
|
||
|
|
printf("Read %d of %d bytes\n",numbytes,len);
|
||
|
|
//printf("Program: %s\n",ShaderSource);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
void glShaderObject::loadFromMemory(const char* program)
|
||
|
|
{
|
||
|
|
if (ShaderSource!=0) // there is already a source loaded, free it!
|
||
|
|
{
|
||
|
|
if (_memalloc)
|
||
|
|
delete[] ShaderSource;
|
||
|
|
}
|
||
|
|
_memalloc = false;
|
||
|
|
ShaderSource = (GLubyte*) program;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// Compiler Log: Ausgabe der Compiler Meldungen in String
|
||
|
|
|
||
|
|
char* glShaderObject::getCompilerLog(void)
|
||
|
|
{
|
||
|
|
int blen = 0;
|
||
|
|
int slen = 0;
|
||
|
|
|
||
|
|
if (ShaderObject==0) return aGLSLStrings[1]; // not a valid program object
|
||
|
|
|
||
|
|
glGetShaderiv(ShaderObject, GL_INFO_LOG_LENGTH , &blen);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
if (blen > 1)
|
||
|
|
{
|
||
|
|
if (compiler_log!=0)
|
||
|
|
{
|
||
|
|
free(compiler_log);
|
||
|
|
compiler_log =0;
|
||
|
|
}
|
||
|
|
if ((compiler_log = (GLcharARB*)malloc(blen)) == NULL)
|
||
|
|
{
|
||
|
|
printf("ERROR: Could not allocate compiler_log buffer\n");
|
||
|
|
return aGLSLStrings[3];
|
||
|
|
}
|
||
|
|
|
||
|
|
glGetInfoLogARB(ShaderObject, blen, &slen, compiler_log);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
//cout << "compiler_log: \n", compiler_log);
|
||
|
|
}
|
||
|
|
if (compiler_log!=0)
|
||
|
|
return (char*) compiler_log;
|
||
|
|
else
|
||
|
|
return aGLSLStrings[6];
|
||
|
|
|
||
|
|
return aGLSLStrings[4];
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShaderObject::compile(void)
|
||
|
|
{
|
||
|
|
is_compiled = false;
|
||
|
|
|
||
|
|
int compiled = 0;
|
||
|
|
|
||
|
|
if (ShaderSource==0) return false;
|
||
|
|
|
||
|
|
GLint length = (GLint) strlen((const char*)ShaderSource);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
glShaderSource(ShaderObject, 1, (const GLchar **)&ShaderSource, &length);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
glCompileShader(ShaderObject);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
glGetObjectParameterivARB(ShaderObject, GL_COMPILE_STATUS, &compiled);
|
||
|
|
CHECK_GL_ERROR();
|
||
|
|
|
||
|
|
if (compiled) is_compiled=true;
|
||
|
|
|
||
|
|
return is_compiled;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
GLint glShaderObject::getAttribLocation(char* attribName)
|
||
|
|
{
|
||
|
|
return glGetAttribLocationARB(ShaderObject, attribName);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
// ShaderManager: Easy use of (multiple) Shaders
|
||
|
|
|
||
|
|
glShaderManager::glShaderManager()
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
glShaderManager::~glShaderManager()
|
||
|
|
{
|
||
|
|
// free objects
|
||
|
|
vector<glShader*>::iterator i=_shaderObjectList.begin();
|
||
|
|
while (i!=_shaderObjectList.end())
|
||
|
|
{
|
||
|
|
//glShader* o = *i;
|
||
|
|
i=_shaderObjectList.erase(i);
|
||
|
|
//delete o;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
glShader* glShaderManager::loadfromFile(char* vertexFile, char* fragmentFile, char* tesscontrolFile, char* tessevalFile, char* geometryFile)
|
||
|
|
{
|
||
|
|
glShader* o = new glShader();
|
||
|
|
|
||
|
|
glShaderObject* shaders[5];
|
||
|
|
shaders[0]= new glShaderObject(GL_VERTEX_SHADER);
|
||
|
|
shaders[1]= new glShaderObject(GL_TESS_CONTROL_SHADER);
|
||
|
|
shaders[2]= new glShaderObject(GL_TESS_EVALUATION_SHADER);
|
||
|
|
shaders[3]= new glShaderObject(GL_GEOMETRY_SHADER);
|
||
|
|
shaders[4]= new glShaderObject(GL_FRAGMENT_SHADER);
|
||
|
|
|
||
|
|
char* filename[5];
|
||
|
|
filename[0]=vertexFile;
|
||
|
|
filename[1]=tesscontrolFile;
|
||
|
|
filename[2]=tessevalFile;
|
||
|
|
filename[3]=geometryFile;
|
||
|
|
filename[4]=fragmentFile;
|
||
|
|
|
||
|
|
for (int i=0;i<5;i++)
|
||
|
|
{
|
||
|
|
if(filename[i]!=0)
|
||
|
|
{
|
||
|
|
printf("Loading: %s\n",filename[i]);
|
||
|
|
// Load program
|
||
|
|
if (shaders[i]->load(filename[i]) != 0)
|
||
|
|
{
|
||
|
|
cout << "error: can't load " << filename[i] << endl;
|
||
|
|
while(1);
|
||
|
|
}
|
||
|
|
printf("Compiling: %s\n",filename[i]);
|
||
|
|
|
||
|
|
// Compile vertex program
|
||
|
|
if (!shaders[i]->compile())
|
||
|
|
{
|
||
|
|
cout << "***COMPILER ERROR (" << shaders[i]->program_str.c_str() << "):\n";
|
||
|
|
cout << shaders[i]->getCompilerLog() << endl;
|
||
|
|
while(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
cout << "***GLSL Compiler Log (" << shaders[i]->program_str.c_str() << "):\n";
|
||
|
|
cout << shaders[i]->getCompilerLog() << "\n";
|
||
|
|
|
||
|
|
// Add to object
|
||
|
|
o->addShader(shaders[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// link
|
||
|
|
if (!o->link())
|
||
|
|
{
|
||
|
|
cout << "**LINKER ERROR\n";
|
||
|
|
cout << o->getLinkerLog() << endl;
|
||
|
|
while(1);
|
||
|
|
}
|
||
|
|
cout << "***GLSL Linker Log:\n";
|
||
|
|
cout << o->getLinkerLog() << endl;
|
||
|
|
|
||
|
|
_shaderObjectList.push_back(o);
|
||
|
|
o->manageMemory();
|
||
|
|
|
||
|
|
return o;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
glShader* glShaderManager::loadfromMemory(char* vertexMem, char* fragmentMem, char* tesscontrolMem, char* tessevalMem, char* geometryMem)
|
||
|
|
{
|
||
|
|
glShader* o = new glShader();
|
||
|
|
|
||
|
|
glShaderObject* shaders[5];
|
||
|
|
shaders[0]= new glShaderObject(GL_VERTEX_SHADER);
|
||
|
|
shaders[1]= new glShaderObject(GL_TESS_CONTROL_SHADER);
|
||
|
|
shaders[2]= new glShaderObject(GL_TESS_EVALUATION_SHADER);
|
||
|
|
shaders[3]= new glShaderObject(GL_GEOMETRY_SHADER);
|
||
|
|
shaders[4]= new glShaderObject(GL_FRAGMENT_SHADER);
|
||
|
|
|
||
|
|
char* mem[5];
|
||
|
|
mem[0]=vertexMem;
|
||
|
|
mem[1]=tesscontrolMem;
|
||
|
|
mem[2]=tessevalMem;
|
||
|
|
mem[3]=geometryMem;
|
||
|
|
mem[4]=fragmentMem;
|
||
|
|
|
||
|
|
for (int i=0;i<5;i++)
|
||
|
|
{
|
||
|
|
if(mem[i]!=0)
|
||
|
|
{
|
||
|
|
// Load program
|
||
|
|
shaders[i]->loadFromMemory(mem[i]);
|
||
|
|
|
||
|
|
// Compile vertex program
|
||
|
|
if (!shaders[i]->compile())
|
||
|
|
{
|
||
|
|
cout << "***COMPILER ERROR (" << shaders[i]->program_str.c_str() << "):\n";
|
||
|
|
cout << shaders[i]->getCompilerLog() << endl;
|
||
|
|
while(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
cout << "***GLSL Compiler Log (" << shaders[i]->program_str.c_str() << "):\n";
|
||
|
|
cout << shaders[i]->getCompilerLog() << "\n";
|
||
|
|
|
||
|
|
// Add to object
|
||
|
|
o->addShader(shaders[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// link
|
||
|
|
if (!o->link())
|
||
|
|
{
|
||
|
|
cout << "**LINKER ERROR\n";
|
||
|
|
cout << o->getLinkerLog() << endl;
|
||
|
|
while(1);
|
||
|
|
}
|
||
|
|
cout << "***GLSL Linker Log:\n";
|
||
|
|
cout << o->getLinkerLog() << endl;
|
||
|
|
|
||
|
|
_shaderObjectList.push_back(o);
|
||
|
|
o->manageMemory();
|
||
|
|
|
||
|
|
return o;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool glShaderManager::free(glShader* o)
|
||
|
|
{
|
||
|
|
vector<glShader*>::iterator i=_shaderObjectList.begin();
|
||
|
|
while (i!=_shaderObjectList.end())
|
||
|
|
{
|
||
|
|
if ((*i)==o)
|
||
|
|
{
|
||
|
|
_shaderObjectList.erase(i);
|
||
|
|
delete o;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
|