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