50 #include <ACG/GL/acg_glew.hh>
52 #include <QApplication>
58 #include <ACG/GL/gl.hh>
59 #include <ACG/GL/GLState.hh>
60 #include <ACG/GL/GLError.hh>
62 #include "GLSLShader.hh"
63 #include <ACG/GL/ShaderGenerator.hh>
67 #define snprintf sprintf_s
88 std::cerr <<
"Shaders not supported with OpenGL Version less than 2.0" << std::endl;
92 this->m_shaderId = glCreateShader(shaderType);
93 if ( this->m_shaderId == 0 ) {
94 std::cerr <<
"could not create shader" << std::endl;
102 if (this->m_shaderId) {
103 glDeleteShader(m_shaderId);
111 if ( this->m_shaderId == 0 ) {
112 std::cerr <<
"shader not initialized" << std::endl;
116 const char **stringArray =
new const char*[source.size()];
119 for (StringList::const_iterator it = source.begin();it != source.end();++it) {
120 stringArray[index] = (*it).c_str();
124 glShaderSource(this->m_shaderId,
int(source.size()), stringArray, 0);
126 delete[] stringArray;
134 if ( this->m_shaderId == 0 ) {
135 std::cerr <<
"shader not initialized" << std::endl;
141 for (QStringList::const_iterator it = source.begin();it != source.end();++it)
142 strlist.push_back(std::string((
const char*)it->toLatin1()) +
'\n');
153 if ( this->m_shaderId == 0 ) {
154 std::cerr <<
"shader not initialized" << std::endl;
158 glCompileShader(m_shaderId);
161 glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &compileStatus);
162 if (compileStatus == GL_FALSE) {
165 GLchar *errorLog =
new GLchar[GLSL_MAX_LOGSIZE];
166 GLsizei errorLength, srcLength;
167 glGetShaderiv(m_shaderId, GL_SHADER_SOURCE_LENGTH, &srcLength);
168 GLchar* shaderSource =
new GLchar[srcLength];
169 glGetShaderSource(m_shaderId, srcLength, &errorLength, shaderSource);
170 std::cout <<
"shader source: " << std::endl << shaderSource << std::endl;
171 glGetShaderInfoLog(m_shaderId, GLSL_MAX_LOGSIZE, &errorLength, errorLog);
172 std::cout <<
"GLSL compile error:" << std::endl << errorLog << std::endl;
174 delete[] shaderSource;
187 VertexShader::VertexShader() :
Shader(GL_VERTEX_SHADER) {}
188 VertexShader::~VertexShader() {}
194 FragmentShader::FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
195 FragmentShader::~FragmentShader() {}
201 GeometryShader::GeometryShader() : Shader(GL_GEOMETRY_SHADER_EXT) {}
202 GeometryShader::~GeometryShader() {}
208 #ifdef GL_ARB_tessellation_shader
210 TessControlShader::TessControlShader() : Shader(GL_TESS_CONTROL_SHADER) {}
211 TessControlShader::~TessControlShader() {}
217 TessEvaluationShader::TessEvaluationShader() : Shader(GL_TESS_EVALUATION_SHADER) {}
218 TessEvaluationShader::~TessEvaluationShader() {}
220 #endif // GL_ARB_tessellation_shader
227 ComputeShader::Caps ComputeShader::caps_;
228 bool ComputeShader::capsInitialized_ =
false;
230 ComputeShader::ComputeShader() : Shader(
231 #ifdef GL_ARB_compute_shader
237 ComputeShader::~ComputeShader() {}
239 const ComputeShader::Caps& ComputeShader::caps() {
240 if (!capsInitialized_) {
241 capsInitialized_ =
true;
243 #ifdef GL_ARB_compute_shader
244 glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &caps_.maxUniformBlocks_);
245 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &caps_.maxTextureImageUnits_);
246 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &caps_.maxImageUniforms_);
247 glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &caps_.maxSharedMemorySize_);
248 glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &caps_.maxUniformComponents_);
249 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &caps_.maxAtomicCounterBufs_);
250 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &caps_.maxAtomicCounters_);
251 glGetIntegerv(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, &caps_.maxCombinedUniformComponents_);
252 glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &caps_.maxWorkGroupInvocations_);
254 for (
int i = 0; i < 3; ++i) {
255 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, caps_.maxWorkGroupCount_ + i);
256 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, caps_.maxWorkGroupSize_ + i);
259 memset(&caps_, 0,
sizeof(caps_));
273 std::cerr <<
"Shaders not supported with OpenGL Version less than 2.0" << std::endl;
277 this->m_programId = glCreateProgram();
279 if ( this->m_programId == 0 ) {
280 std::cerr <<
"could not create GLSL program" << std::endl;
289 if (this->m_programId) {
290 glDeleteProgram(this->m_programId);
293 this->m_linkedShaders.clear();
299 if ( this->m_programId == 0 ) {
300 std::cerr <<
"attach invalid program" << std::endl;
304 if ( _shader->m_shaderId == 0 ) {
305 std::cerr <<
"attach invalid shader" << std::endl;
309 glAttachShader(this->m_programId, _shader->m_shaderId);
310 m_linkedShaders.push_back(_shader);
316 if ( this->m_programId == 0 ) {
317 std::cerr <<
"detach invalid program" << std::endl;
321 if ( _shader->m_shaderId == 0 ) {
322 std::cerr <<
"detach invalid shader" << std::endl;
326 glDetachShader(this->m_programId, _shader->m_shaderId);
327 m_linkedShaders.remove(_shader);
333 glLinkProgram(this->m_programId);
334 checkGLError2(
"link program failed");
336 GLint status = GL_FALSE;
337 glGetProgramiv(this->m_programId, GL_LINK_STATUS, &status);
339 GLint InfoLogLength = 0;
340 glGetProgramiv(this->m_programId, GL_INFO_LOG_LENGTH, &InfoLogLength);
341 std::string errorlog(InfoLogLength,
'\0');
342 glGetProgramInfoLog(this->m_programId, InfoLogLength, NULL, &errorlog[0]);
343 std::cerr <<
"program link error: " << errorlog << std::endl;
346 m_linkStatus = status;
355 checkGLError2(
"use program failed");
363 checkGLError2(
"shader disable failed");
370 glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
371 return programId == this->m_programId;
377 return m_linkStatus != GL_FALSE;
383 return (GLuint)m_programId;
393 GLint location = glGetUniformLocation(this->m_programId, _name);
394 checkGLError2(_name);
395 glUniform1i(location, _value);
396 checkGLError2(_name);
406 GLint location = glGetUniformLocation(this->m_programId, _name);
407 checkGLError2(_name);
408 glUniform2iv(location, 1, _value.data());
419 GLint location = glGetUniformLocation(this->m_programId, _name);
420 checkGLError2(_name);
421 glUniform3iv(location, 1, _value.data());
432 GLint location = glGetUniformLocation(this->m_programId, _name);
433 checkGLError2(_name);
434 glUniform4iv(location, 1, _value.data());
445 GLint location = glGetUniformLocation(this->m_programId, _name);
446 checkGLError2(_name);
447 glUniform1ui(location, _value);
448 checkGLError2(_name);
458 GLint location = glGetUniformLocation(this->m_programId, _name);
459 checkGLError2(_name);
460 glUniform2uiv(location, 1, _value.data());
471 GLint location = glGetUniformLocation(this->m_programId, _name);
472 checkGLError2(_name);
473 glUniform3uiv(location, 1, _value.data());
484 GLint location = glGetUniformLocation(this->m_programId, _name);
485 checkGLError2(_name);
486 glUniform4uiv(location, 1, _value.data());
496 checkGLError2(
"prev opengl error");
497 GLint location = glGetUniformLocation(this->m_programId, _name);
498 checkGLError2(_name);
499 glUniform1f(location, _value);
500 checkGLError2(_name);
510 GLint location = glGetUniformLocation(this->m_programId, _name);
511 checkGLError2(_name);
512 glUniform2fv(location, 1, _value.data());
523 GLint location = glGetUniformLocation(this->m_programId, _name);
524 checkGLError2(_name);
525 glUniform3fv(location, 1, _value.data());
536 GLint location = glGetUniformLocation(this->m_programId, _name);
537 checkGLError2(_name);
538 glUniform4fv(location, 1, _value.data());
550 GLint location = glGetUniformLocation(this->m_programId, _name);
551 checkGLError2(_name);
552 glUniform1iv(location, _count, _values);
564 GLint location = glGetUniformLocation(this->m_programId, _name);
565 checkGLError2(_name);
566 glUniform1fv(location, _count, _values);
578 GLint location = glGetUniformLocation(this->m_programId, _name);
579 checkGLError2(_name);
580 glUniform2fv(location, _count, (GLfloat*)_values);
592 GLint location = glGetUniformLocation(this->m_programId, _name);
593 checkGLError2(_name);
594 glUniform3fv(location, _count, (GLfloat*)_values);
606 GLint location = glGetUniformLocation(this->m_programId, _name);
607 checkGLError2(_name);
608 glUniform4fv(location, _count, (GLfloat*)_values);
620 snprintf(varName, 1024,
"%s[%d]", _name, _index);
632 snprintf(varName, 1024,
"%s[%d]", _name, _index);
644 snprintf(varName, 1024,
"%s[%d]", _name, _index);
657 GLint location = glGetUniformLocation(this->m_programId, _name);
658 checkGLError2(_name);
659 glUniformMatrix4fv(location, 1, _transposed, _value.data());
671 GLint location = glGetUniformLocation(this->m_programId, _name);
672 checkGLError2(_name);
675 for (
int i = 0; i < 3; ++i)
676 for (
int k = 0; k < 3; ++k)
677 tmp[i*3+k] = _value.data()[i*4+k];
679 glUniformMatrix3fv(location, 1, _transposed, tmp);
689 glBindAttribLocation(this->m_programId, _index, _name);
690 checkGLError2(_name);
699 glBindFragDataLocationEXT(this->m_programId, _index, _name);
700 checkGLError2(_name);
709 int attributeLocation = glGetAttribLocation(this->m_programId, _name);
710 checkGLError2(_name);
711 return attributeLocation;
720 int attributeLocation = glGetUniformLocation(this->m_programId, _name);
721 checkGLError2(_name);
722 return attributeLocation;
731 int attributeLocation = glGetFragDataLocationEXT(this->m_programId, _name);
732 checkGLError2(_name);
733 return attributeLocation;
743 glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_INPUT_TYPE_EXT, _type);
753 glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_OUTPUT_TYPE_EXT, _type);
763 glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_VERTICES_OUT_EXT, _numVerticesOut);
774 #ifdef GL_ARB_uniform_buffer_object
775 GLuint idx = glGetUniformBlockIndex(m_programId, _name);
776 checkGLError2(_name);
790 #ifdef GL_ARB_uniform_buffer_object
791 glUniformBlockBinding(m_programId, _index, GLuint(_binding));
815 #ifdef GL_ARB_uniform_buffer_object
816 glGetActiveUniformBlockiv(m_programId, _index, GL_UNIFORM_BLOCK_DATA_SIZE, &bufsize);
841 #ifdef GL_ARB_uniform_buffer_object
842 GLuint* idx =
new GLuint[_numUniforms];
843 glGetUniformIndices(m_programId, _numUniforms, _names, idx);
845 glGetActiveUniformsiv(m_programId, _numUniforms, idx, GL_UNIFORM_OFFSET, _outOffsets);
861 void loadShaderRec(
const char *filename,
bool appendNewLineChar, std::map<QString, int>& includeMap, GLSL::StringList& shaderSource){
863 if (QDir(filename).isRelative()) {
864 path_file = qApp->applicationDirPath() + QString(
"/../shader/")
867 path_file = QString::fromLatin1(filename);
871 std::map<QString, int>::iterator includeIter = includeMap.find(path_file);
873 if (includeIter == includeMap.end()){
874 includeMap[path_file] = 1;
876 std::ifstream iShader(path_file.toLatin1());
878 std::cout <<
"ERROR: Could not open file " << path_file.toStdString() << std::endl;
882 while (!iShader.eof()) {
884 std::getline(iShader, strLine);
887 QString qstrLine = strLine.c_str();
888 if (qstrLine.trimmed().startsWith(
"#include")) {
891 QString strIncludeFile = qstrLine.remove(
"#include ").remove(
'\"').remove(
'<').remove(
'>').trimmed();
892 QFileInfo loadedShaderFile(path_file);
893 QString includePath = loadedShaderFile.absolutePath();
895 if (strIncludeFile.isEmpty())
896 std::cout <<
"wrong include syntax: " << strLine.c_str() << std::endl;
898 QString fullPathToIncludeFile = includePath + QDir::separator() + strIncludeFile;
900 loadShaderRec(fullPathToIncludeFile.toLatin1(), appendNewLineChar, includeMap, shaderSource);
904 if (appendNewLineChar)
906 shaderSource.push_back(strLine);
927 GLSL::StringList
loadShader(
const char *filename,
const GLSL::StringList *macros,
bool appendNewLineChar, GLSL::StringList* outIncludes) {
929 GLSL::StringList src;
931 std::map<QString, int> includeMap;
936 if (macros && !macros->empty() && !macros->front().empty())
938 bool foundVersionDirective =
false;
940 for (GLSL::StringList::iterator it = src.begin(); it != src.end(); ++it)
942 QString qstr = it->c_str();
943 if (qstr.trimmed().startsWith(
"#version "))
945 foundVersionDirective =
true;
949 for (GLSL::StringList::const_iterator itMacro = macros->begin(); itMacro != macros->end(); ++itMacro)
950 src.insert(it, *itMacro +
"\n");
956 if (!foundVersionDirective)
960 for (GLSL::StringList::const_reverse_iterator it = macros->rbegin(); it != macros->rend(); ++it)
961 src.push_front(*it +
"\n");
967 for (std::map<QString, int>::iterator it = includeMap.begin(); it != includeMap.end(); ++it)
968 outIncludes->push_back(it->first.toStdString());
977 StringList sourceVertex =
loadShader(name, macros);
979 if (!sourceVertex.empty() ) {
982 vertexShader->
compile(verbose);
991 StringList sourceVertex =
loadShader(name, macros);
993 if ( !sourceVertex.empty() ) {
996 if (!fragmentShader->
compile(verbose)) {
997 delete fragmentShader;
1001 return fragmentShader;
1008 StringList sourceVertex =
loadShader(name, macros);
1010 if (!sourceVertex.empty()) {
1012 geometryShader->
setSource(sourceVertex);
1013 if (!geometryShader->
compile(verbose)) {
1014 delete geometryShader;
1018 return geometryShader;
1026 #ifdef GL_ARB_tessellation_shader
1030 shader =
new GLSL::TessControlShader();
1032 if (!shader->
compile(verbose)) {
1037 #endif // GL_ARB_tessellation_shader
1045 #ifdef GL_ARB_tessellation_shader
1049 shader =
new GLSL::TessEvaluationShader();
1051 if (!shader->
compile(verbose)) {
1056 #endif // GL_ARB_tessellation_shader
1065 #ifdef GL_ARB_compute_shader
1071 if (!shader->
compile(verbose)) {
1076 #endif // GL_ARB_compute_shader
1083 const char *tessControlShaderFile,
1084 const char *tessEvaluationShaderFile,
1085 const char *geometryShaderFile,
1086 const char *fragmentShaderFile,
1087 const GLSL::StringList *macros,
1092 const int numShaders = 5;
1093 const char* ShaderFiles[numShaders] = {vertexShaderFile, tessControlShaderFile, tessEvaluationShaderFile, geometryShaderFile, fragmentShaderFile};
1096 for (
int i = 0; i < numShaders; ++i) {
1098 QString inputFile = ShaderFiles[i];
1099 if (ShaderFiles[i] && !inputFile.isEmpty()) {
1100 QDir inputFileDir = inputFile;
1103 QString shaderFile = inputFile;
1104 if (inputFileDir.isRelative())
1109 else if (i == 1 && tessControlShaderFile)
1111 else if (i == 2 && tessEvaluationShaderFile)
1113 else if (i == 3 && geometryShaderFile)
1118 if (!tempShaders[i] && ShaderFiles[i]) {
1120 std::cerr << ShaderFiles[i] <<
" could not be loaded and compiled" << std::endl;
1123 for (
int k = 0; k < numShaders; ++k)
1124 delete tempShaders[k];
1134 for (
int i = 0; i < numShaders; ++i)
1136 result->
attach(tempShaders[i]);
1139 for (
int i = 0; i < numShaders; ++i)
1140 delete tempShaders[i];
1149 GLSL::PtrProgram loadProgram(
const char *vertexShaderFile,
const char *geometryShaderFile,
const char *fragmentShaderFile,
const GLSL::StringList *macros,
bool verbose){
1151 return loadProgram(vertexShaderFile, 0, 0, geometryShaderFile, fragmentShaderFile, macros, verbose);
1156 return loadProgram(vertexShaderFile, 0, fragmentShaderFile, macros, verbose);
1163 QString inputFile = computeShaderFile;
1164 if (computeShaderFile && !inputFile.isEmpty()) {
1165 QDir inputFileDir = inputFile;
1168 QString shaderFile = inputFile;
1169 if (inputFileDir.isRelative())
1176 std::cerr << computeShaderFile <<
" could not be loaded and compiled" << std::endl;
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
void setSource(const StringList &source)
Upload the source of the shader.
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
void setGeometryInputType(GLint _type)
Set Type of Geometry.
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Program()
Creates a new GLSL program object.
void setGeometryOutputType(GLint _type)
Set output type of geometry.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
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 detach(PtrConstShader _shader)
Detaches a shader object from the program object.
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
bool openGLVersion(const int _major, const int _minor)
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
void use()
Enables the program object for using.
A generic shader base class.
GLuint getProgramId()
Returns opengl id.
virtual ~Shader()
Deletes the shader object.
bool isLinked()
Returns if the program object has been succesfully linked.
bool compile(bool verbose=true)
Compile the shader object.
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
bool isActive()
Returns if the program object is currently active.
void link()
Links the shader objects to the program.
This namespace contains all the classes and functions for handling GLSL shader and program objects...
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
void loadShaderRec(const char *filename, bool appendNewLineChar, std::map< QString, int > &includeMap, GLSL::StringList &shaderSource)
Loads the shader source and all recursive includes.
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
void disable()
Resets to standard rendering pipeline.
Shader(GLenum shaderType)
Creates a new shader.
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
int getUniformLocation(const char *_name)
Get location of the specified uniform.
static QString getShaderDir()
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.