44 #include <ACG/GL/acg_glew.hh> 46 #include <QApplication> 52 #include <ACG/GL/gl.hh> 53 #include <ACG/GL/GLState.hh> 54 #include <ACG/GL/GLError.hh> 56 #include "GLSLShader.hh" 57 #include <ACG/GL/ShaderGenerator.hh> 61 #define snprintf sprintf_s 82 std::cerr <<
"Shaders not supported with OpenGL Version less than 2.0" << std::endl;
86 this->m_shaderId = glCreateShader(shaderType);
87 if ( this->m_shaderId == 0 ) {
88 std::cerr <<
"could not create shader" << std::endl;
96 if (this->m_shaderId) {
97 glDeleteShader(m_shaderId);
105 if ( this->m_shaderId == 0 ) {
106 std::cerr <<
"shader not initialized" << std::endl;
110 const char **stringArray =
new const char*[source.size()];
113 for (StringList::const_iterator it = source.begin();it != source.end();++it) {
114 stringArray[index] = (*it).c_str();
118 glShaderSource(this->m_shaderId,
int(source.size()), stringArray, 0);
120 delete[] stringArray;
128 if ( this->m_shaderId == 0 ) {
129 std::cerr <<
"shader not initialized" << std::endl;
135 for (QStringList::const_iterator it = source.begin();it != source.end();++it)
136 strlist.push_back(std::string((
const char*)it->toLatin1()) +
'\n');
147 if ( this->m_shaderId == 0 ) {
148 std::cerr <<
"shader not initialized" << std::endl;
152 glCompileShader(m_shaderId);
155 glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &compileStatus);
156 if (compileStatus == GL_FALSE) {
159 GLchar *errorLog =
new GLchar[GLSL_MAX_LOGSIZE];
160 GLsizei errorLength, srcLength;
161 glGetShaderiv(m_shaderId, GL_SHADER_SOURCE_LENGTH, &srcLength);
162 GLchar* shaderSource =
new GLchar[srcLength];
163 glGetShaderSource(m_shaderId, srcLength, &errorLength, shaderSource);
164 std::cout <<
"shader source: " << std::endl << shaderSource << std::endl;
165 glGetShaderInfoLog(m_shaderId, GLSL_MAX_LOGSIZE, &errorLength, errorLog);
166 std::cout <<
"GLSL compile error:" << std::endl << errorLog << std::endl;
168 delete[] shaderSource;
181 VertexShader::VertexShader() :
Shader(GL_VERTEX_SHADER) {}
182 VertexShader::~VertexShader() {}
188 FragmentShader::FragmentShader() :
Shader(GL_FRAGMENT_SHADER) {}
189 FragmentShader::~FragmentShader() {}
195 GeometryShader::GeometryShader() :
Shader(GL_GEOMETRY_SHADER_EXT) {}
196 GeometryShader::~GeometryShader() {}
202 #ifdef GL_ARB_tessellation_shader 204 TessControlShader::TessControlShader() :
Shader(GL_TESS_CONTROL_SHADER) {}
205 TessControlShader::~TessControlShader() {}
211 TessEvaluationShader::TessEvaluationShader() :
Shader(GL_TESS_EVALUATION_SHADER) {}
212 TessEvaluationShader::~TessEvaluationShader() {}
214 #endif // GL_ARB_tessellation_shader 222 bool ComputeShader::capsInitialized_ =
false;
224 ComputeShader::ComputeShader() :
Shader(
225 #ifdef GL_ARB_compute_shader
231 ComputeShader::~ComputeShader() {}
234 if (!capsInitialized_) {
235 capsInitialized_ =
true;
237 #ifdef GL_ARB_compute_shader 238 glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &caps_.maxUniformBlocks_);
239 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &caps_.maxTextureImageUnits_);
240 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &caps_.maxImageUniforms_);
241 glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &caps_.maxSharedMemorySize_);
242 glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &caps_.maxUniformComponents_);
243 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &caps_.maxAtomicCounterBufs_);
244 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &caps_.maxAtomicCounters_);
245 glGetIntegerv(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, &caps_.maxCombinedUniformComponents_);
246 glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &caps_.maxWorkGroupInvocations_);
248 for (
int i = 0; i < 3; ++i) {
249 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, caps_.maxWorkGroupCount_ + i);
250 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, caps_.maxWorkGroupSize_ + i);
253 memset(&caps_, 0,
sizeof(caps_));
267 std::cerr <<
"Shaders not supported with OpenGL Version less than 2.0" << std::endl;
271 this->m_programId = glCreateProgram();
273 if ( this->m_programId == 0 ) {
274 std::cerr <<
"could not create GLSL program" << std::endl;
283 if (this->m_programId) {
284 glDeleteProgram(this->m_programId);
287 this->m_linkedShaders.clear();
293 if ( this->m_programId == 0 ) {
294 std::cerr <<
"attach invalid program" << std::endl;
298 if ( _shader->m_shaderId == 0 ) {
299 std::cerr <<
"attach invalid shader" << std::endl;
303 glAttachShader(this->m_programId, _shader->m_shaderId);
304 m_linkedShaders.push_back(_shader);
310 if ( this->m_programId == 0 ) {
311 std::cerr <<
"detach invalid program" << std::endl;
315 if ( _shader->m_shaderId == 0 ) {
316 std::cerr <<
"detach invalid shader" << std::endl;
320 glDetachShader(this->m_programId, _shader->m_shaderId);
321 m_linkedShaders.remove(_shader);
327 glLinkProgram(this->m_programId);
328 checkGLError2(
"link program failed");
330 GLint status = GL_FALSE;
331 glGetProgramiv(this->m_programId, GL_LINK_STATUS, &status);
333 GLint InfoLogLength = 0;
334 glGetProgramiv(this->m_programId, GL_INFO_LOG_LENGTH, &InfoLogLength);
335 std::string errorlog(InfoLogLength,
'\0');
336 glGetProgramInfoLog(this->m_programId, InfoLogLength, NULL, &errorlog[0]);
337 std::cerr <<
"program link error: " << errorlog << std::endl;
340 m_linkStatus = status;
349 checkGLError2(
"use program failed");
357 checkGLError2(
"shader disable failed");
364 glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
365 return programId == this->m_programId;
371 return m_linkStatus != GL_FALSE;
377 return (GLuint)m_programId;
387 GLint location = glGetUniformLocation(this->m_programId, _name);
388 checkGLError2(_name);
389 glUniform1i(location, _value);
390 checkGLError2(_name);
400 GLint location = glGetUniformLocation(this->m_programId, _name);
401 checkGLError2(_name);
402 glUniform2iv(location, 1, _value.
data());
413 GLint location = glGetUniformLocation(this->m_programId, _name);
414 checkGLError2(_name);
415 glUniform3iv(location, 1, _value.
data());
426 GLint location = glGetUniformLocation(this->m_programId, _name);
427 checkGLError2(_name);
428 glUniform4iv(location, 1, _value.
data());
439 GLint location = glGetUniformLocation(this->m_programId, _name);
440 checkGLError2(_name);
441 glUniform1ui(location, _value);
442 checkGLError2(_name);
452 GLint location = glGetUniformLocation(this->m_programId, _name);
453 checkGLError2(_name);
454 glUniform2uiv(location, 1, _value.
data());
465 GLint location = glGetUniformLocation(this->m_programId, _name);
466 checkGLError2(_name);
467 glUniform3uiv(location, 1, _value.
data());
478 GLint location = glGetUniformLocation(this->m_programId, _name);
479 checkGLError2(_name);
480 glUniform4uiv(location, 1, _value.
data());
490 checkGLError2(
"prev opengl error");
491 GLint location = glGetUniformLocation(this->m_programId, _name);
492 checkGLError2(_name);
493 glUniform1f(location, _value);
494 checkGLError2(_name);
504 GLint location = glGetUniformLocation(this->m_programId, _name);
505 checkGLError2(_name);
506 glUniform2fv(location, 1, _value.
data());
517 GLint location = glGetUniformLocation(this->m_programId, _name);
518 checkGLError2(_name);
519 glUniform3fv(location, 1, _value.
data());
530 GLint location = glGetUniformLocation(this->m_programId, _name);
531 checkGLError2(_name);
532 glUniform4fv(location, 1, _value.
data());
544 GLint location = glGetUniformLocation(this->m_programId, _name);
545 checkGLError2(_name);
546 glUniform1iv(location, _count, _values);
558 GLint location = glGetUniformLocation(this->m_programId, _name);
559 checkGLError2(_name);
560 glUniform1fv(location, _count, _values);
572 GLint location = glGetUniformLocation(this->m_programId, _name);
573 checkGLError2(_name);
574 glUniform2fv(location, _count, (GLfloat*)_values);
586 GLint location = glGetUniformLocation(this->m_programId, _name);
587 checkGLError2(_name);
588 glUniform3fv(location, _count, (GLfloat*)_values);
600 GLint location = glGetUniformLocation(this->m_programId, _name);
601 checkGLError2(_name);
602 glUniform4fv(location, _count, (GLfloat*)_values);
614 snprintf(varName, 1024,
"%s[%d]", _name, _index);
626 snprintf(varName, 1024,
"%s[%d]", _name, _index);
638 snprintf(varName, 1024,
"%s[%d]", _name, _index);
651 GLint location = glGetUniformLocation(this->m_programId, _name);
652 checkGLError2(_name);
653 glUniformMatrix4fv(location, 1, _transposed, _value.data());
665 GLint location = glGetUniformLocation(this->m_programId, _name);
666 checkGLError2(_name);
669 for (
int i = 0; i < 3; ++i)
670 for (
int k = 0; k < 3; ++k)
671 tmp[i*3+k] = _value.data()[i*4+k];
673 glUniformMatrix3fv(location, 1, _transposed, tmp);
683 glBindAttribLocation(this->m_programId, _index, _name);
684 checkGLError2(_name);
693 glBindFragDataLocation(this->m_programId, _index, _name);
694 checkGLError2(_name);
703 int attributeLocation = glGetAttribLocation(this->m_programId, _name);
704 checkGLError2(_name);
705 return attributeLocation;
714 int attributeLocation = glGetUniformLocation(this->m_programId, _name);
715 checkGLError2(_name);
716 return attributeLocation;
725 int attributeLocation = glGetFragDataLocation(this->m_programId, _name);
726 checkGLError2(_name);
727 return attributeLocation;
737 glProgramParameteri(this->m_programId, GL_GEOMETRY_INPUT_TYPE_EXT, _type);
747 glProgramParameteri(this->m_programId, GL_GEOMETRY_OUTPUT_TYPE_EXT, _type);
757 glProgramParameteri(this->m_programId, GL_GEOMETRY_VERTICES_OUT_EXT, _numVerticesOut);
768 #ifdef GL_ARB_uniform_buffer_object 769 GLuint idx = glGetUniformBlockIndex(m_programId, _name);
770 checkGLError2(_name);
784 #ifdef GL_ARB_uniform_buffer_object 785 glUniformBlockBinding(m_programId, _index, GLuint(_binding));
809 #ifdef GL_ARB_uniform_buffer_object 810 glGetActiveUniformBlockiv(m_programId, _index, GL_UNIFORM_BLOCK_DATA_SIZE, &bufsize);
835 #ifdef GL_ARB_uniform_buffer_object 836 GLuint* idx =
new GLuint[_numUniforms];
837 glGetUniformIndices(m_programId, _numUniforms, _names, idx);
839 glGetActiveUniformsiv(m_programId, _numUniforms, idx, GL_UNIFORM_OFFSET, _outOffsets);
855 void loadShaderRec(
const char *filename,
bool appendNewLineChar, std::map<QString, int>& includeMap, GLSL::StringList& shaderSource){
857 if (QDir(filename).isRelative()) {
858 path_file = qApp->applicationDirPath() + QString(
"/../shader/")
861 path_file = QString::fromLatin1(filename);
865 std::map<QString, int>::iterator includeIter = includeMap.find(path_file);
867 if (includeIter == includeMap.end()){
868 includeMap[path_file] = 1;
870 std::ifstream iShader(path_file.toLatin1());
872 std::cout <<
"ERROR: Could not open file " << path_file.toStdString() << std::endl;
876 while (!iShader.eof()) {
878 std::getline(iShader, strLine);
881 QString qstrLine = strLine.c_str();
882 if (qstrLine.trimmed().startsWith(
"#include")) {
885 QString strIncludeFile = qstrLine.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
886 QFileInfo loadedShaderFile(path_file);
887 QString includePath = loadedShaderFile.absolutePath();
889 if (strIncludeFile.isEmpty())
890 std::cout <<
"wrong include syntax: " << strLine.c_str() << std::endl;
892 QString fullPathToIncludeFile = includePath + QDir::separator() + strIncludeFile;
894 loadShaderRec(fullPathToIncludeFile.toLatin1(), appendNewLineChar, includeMap, shaderSource);
898 if (appendNewLineChar)
900 shaderSource.push_back(strLine);
921 GLSL::StringList
loadShader(
const char *filename,
const GLSL::StringList *macros,
bool appendNewLineChar, GLSL::StringList* outIncludes) {
923 GLSL::StringList src;
925 std::map<QString, int> includeMap;
930 if (macros && !macros->empty() && !macros->front().empty())
932 bool foundVersionDirective =
false;
934 for (GLSL::StringList::iterator it = src.begin(); it != src.end(); ++it)
936 QString qstr = it->c_str();
937 if (qstr.trimmed().startsWith(
"#version "))
939 foundVersionDirective =
true;
943 for (GLSL::StringList::const_iterator itMacro = macros->begin(); itMacro != macros->end(); ++itMacro)
944 src.insert(it, *itMacro +
"\n");
950 if (!foundVersionDirective)
954 for (GLSL::StringList::const_reverse_iterator it = macros->rbegin(); it != macros->rend(); ++it)
955 src.push_front(*it +
"\n");
961 for (std::map<QString, int>::iterator it = includeMap.begin(); it != includeMap.end(); ++it)
962 outIncludes->push_back(it->first.toStdString());
971 StringList sourceVertex =
loadShader(name, macros);
973 if (!sourceVertex.empty() ) {
976 vertexShader->
compile(verbose);
985 StringList sourceVertex =
loadShader(name, macros);
987 if ( !sourceVertex.empty() ) {
990 if (!fragmentShader->
compile(verbose)) {
991 delete fragmentShader;
995 return fragmentShader;
1002 StringList sourceVertex =
loadShader(name, macros);
1004 if (!sourceVertex.empty()) {
1006 geometryShader->
setSource(sourceVertex);
1007 if (!geometryShader->
compile(verbose)) {
1008 delete geometryShader;
1012 return geometryShader;
1020 #ifdef GL_ARB_tessellation_shader 1024 shader =
new GLSL::TessControlShader();
1026 if (!shader->
compile(verbose)) {
1031 #endif // GL_ARB_tessellation_shader 1039 #ifdef GL_ARB_tessellation_shader 1043 shader =
new GLSL::TessEvaluationShader();
1045 if (!shader->
compile(verbose)) {
1050 #endif // GL_ARB_tessellation_shader 1059 #ifdef GL_ARB_compute_shader 1065 if (!shader->
compile(verbose)) {
1070 #endif // GL_ARB_compute_shader 1077 const char *tessControlShaderFile,
1078 const char *tessEvaluationShaderFile,
1079 const char *geometryShaderFile,
1080 const char *fragmentShaderFile,
1081 const GLSL::StringList *macros,
1086 const int numShaders = 5;
1087 const char* ShaderFiles[numShaders] = {vertexShaderFile, tessControlShaderFile, tessEvaluationShaderFile, geometryShaderFile, fragmentShaderFile};
1090 for (
int i = 0; i < numShaders; ++i) {
1092 QString inputFile = ShaderFiles[i];
1093 if (ShaderFiles[i] && !inputFile.isEmpty()) {
1094 QDir inputFileDir = inputFile;
1097 QString shaderFile = inputFile;
1098 if (inputFileDir.isRelative())
1103 else if (i == 1 && tessControlShaderFile)
1105 else if (i == 2 && tessEvaluationShaderFile)
1107 else if (i == 3 && geometryShaderFile)
1112 if (!tempShaders[i] && ShaderFiles[i]) {
1114 std::cerr << ShaderFiles[i] <<
" could not be loaded and compiled" << std::endl;
1117 for (
int k = 0; k < numShaders; ++k)
1118 delete tempShaders[k];
1128 for (
int i = 0; i < numShaders; ++i)
1130 result->
attach(tempShaders[i]);
1133 for (
int i = 0; i < numShaders; ++i)
1134 delete tempShaders[i];
1143 GLSL::PtrProgram loadProgram(
const char *vertexShaderFile,
const char *geometryShaderFile,
const char *fragmentShaderFile,
const GLSL::StringList *macros,
bool verbose){
1145 return loadProgram(vertexShaderFile, 0, 0, geometryShaderFile, fragmentShaderFile, macros, verbose);
1150 return loadProgram(vertexShaderFile, 0, fragmentShaderFile, macros, verbose);
1157 QString inputFile = computeShaderFile;
1158 if (computeShaderFile && !inputFile.isEmpty()) {
1159 QDir inputFileDir = inputFile;
1162 QString shaderFile = inputFile;
1163 if (inputFileDir.isRelative())
1170 std::cerr << computeShaderFile <<
" could not be loaded and compiled" << std::endl;
static QString getShaderDir()
int getUniformLocation(const char *_name)
Get location of the specified uniform.
void setSource(const StringList &source)
Upload the source of the shader.
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
void use()
Enables the program object for using.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
bool compile(bool verbose=true)
Compile the shader object.
Program()
Creates a new GLSL program object.
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
virtual ~Shader()
Deletes the shader object.
GLuint getProgramId()
Returns opengl id.
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
bool isLinked()
Returns if the program object has been succesfully linked.
Scalar * data()
access to Scalar array
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
void setGeometryInputType(GLint _type)
Set Type of Geometry.
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
bool isActive()
Returns if the program object is currently active.
This namespace contains all the classes and functions for handling GLSL shader and program objects...
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
void loadShaderRec(const char *filename, bool appendNewLineChar, std::map< QString, int > &includeMap, GLSL::StringList &shaderSource)
Loads the shader source and all recursive includes.
bool openGLVersion(const int _major, const int _minor, bool _verbose)
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
void disable()
Resets to standard rendering pipeline.
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
A generic shader base class.
Shader(GLenum shaderType)
Creates a new shader.
void link()
Links the shader objects to the program.
void setGeometryOutputType(GLint _type)
Set output type of geometry.