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 228 bool ComputeShader::capsInitialized_ =
false;
230 ComputeShader::ComputeShader() :
Shader(
231 #ifdef GL_ARB_compute_shader
237 ComputeShader::~ComputeShader() {}
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;
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
void setSource(const StringList &source)
Upload the source of the shader.
bool compile(bool verbose=true)
Compile the shader object.
bool isLinked()
Returns if the program object has been succesfully linked.
A generic shader base class.
void link()
Links the shader objects to the program.
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
virtual ~Shader()
Deletes the shader object.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
void use()
Enables the program object for using.
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Shader(GLenum shaderType)
Creates a new shader.
static QString getShaderDir()
bool openGLVersion(const int _major, const int _minor)
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
void setGeometryInputType(GLint _type)
Set Type of Geometry.
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.
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
void loadShaderRec(const char *filename, bool appendNewLineChar, std::map< QString, int > &includeMap, GLSL::StringList &shaderSource)
Loads the shader source and all recursive includes.
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
Program()
Creates a new GLSL program object.
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
void setGeometryOutputType(GLint _type)
Set output type of geometry.
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
int getUniformLocation(const char *_name)
Get location of the specified uniform.
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
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...
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
void disable()
Resets to standard rendering pipeline.
GLuint getProgramId()
Returns opengl id.
Scalar * data()
access to Scalar array