Developer Documentation
GLSLShader.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 #include <ACG/GL/acg_glew.hh>
51 
52 #include <QApplication>
53 #include <QDir>
54 
55 #include <iostream>
56 #include <fstream>
57 
58 #include <ACG/GL/gl.hh>
59 #include <ACG/GL/GLState.hh>
60 #include <ACG/GL/GLError.hh>
61 
62 #include "GLSLShader.hh"
63 #include <ACG/GL/ShaderGenerator.hh>
64 
65 #ifdef WIN32
66  #ifndef __MINGW32__
67  #define snprintf sprintf_s
68  #endif
69 #endif
70 
71 //==============================================================================
72 
73 namespace GLSL {
74 
75  //--------------------------------------------------------------------------
76  // Generic shader
77  //--------------------------------------------------------------------------
78 
83  Shader::Shader(GLenum shaderType)
84  : m_shaderId(0)
85  {
86 
87  if ( !ACG::openGLVersion(2,0) ) {
88  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
89  return;
90  }
91 
92  this->m_shaderId = glCreateShader(shaderType);
93  if ( this->m_shaderId == 0 ) {
94  std::cerr << "could not create shader" << std::endl;
95  }
96 
97  }
98 
102  if (this->m_shaderId) {
103  glDeleteShader(m_shaderId);
104  }
105  }
106 
109  void Shader::setSource(const StringList& source) {
110 
111  if ( this->m_shaderId == 0 ) {
112  std::cerr << "shader not initialized" << std::endl;
113  return;
114  }
115 
116  const char **stringArray = new const char*[source.size()];
117 
118  int index = 0;
119  for (StringList::const_iterator it = source.begin();it != source.end();++it) {
120  stringArray[index] = (*it).c_str();
121  ++index;
122  }
123 
124  glShaderSource(this->m_shaderId, int(source.size()), stringArray, 0);
125 
126  delete[] stringArray;
127  }
128 
129 
132  void Shader::setSource(const QStringList& source) {
133 
134  if ( this->m_shaderId == 0 ) {
135  std::cerr << "shader not initialized" << std::endl;
136  return;
137  }
138 
139  StringList strlist;
140 
141  for (QStringList::const_iterator it = source.begin();it != source.end();++it)
142  strlist.push_back(std::string((const char*)it->toLatin1()) + '\n');
143 
144  setSource(strlist);
145  }
146 
152  bool Shader::compile(bool verbose) {
153  if ( this->m_shaderId == 0 ) {
154  std::cerr << "shader not initialized" << std::endl;
155  return false;
156  }
157 
158  glCompileShader(m_shaderId);
159 
160  GLint compileStatus;
161  glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &compileStatus);
162  if (compileStatus == GL_FALSE) {
163 
164  if (verbose) {
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;
173 
174  delete[] shaderSource;
175  delete[] errorLog;
176  }
177 
178  return false;
179  }
180  return true;
181  }
182 
183  //--------------------------------------------------------------------------
184  // Vertex shader
185  //--------------------------------------------------------------------------
186 
187  VertexShader::VertexShader() : Shader(GL_VERTEX_SHADER) {}
188  VertexShader::~VertexShader() {}
189 
190  //--------------------------------------------------------------------------
191  // Fragment shader
192  //--------------------------------------------------------------------------
193 
194  FragmentShader::FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
195  FragmentShader::~FragmentShader() {}
196 
197  //--------------------------------------------------------------------------
198  // Geometry shader
199  //--------------------------------------------------------------------------
200 
201  GeometryShader::GeometryShader() : Shader(GL_GEOMETRY_SHADER_EXT) {}
202  GeometryShader::~GeometryShader() {}
203 
204  //--------------------------------------------------------------------------
205  // Tessellation-Control shader
206  //--------------------------------------------------------------------------
207 
208 #ifdef GL_ARB_tessellation_shader
209 
210  TessControlShader::TessControlShader() : Shader(GL_TESS_CONTROL_SHADER) {}
211  TessControlShader::~TessControlShader() {}
212 
213  //--------------------------------------------------------------------------
214  // Tessellation-Evaluation shader
215  //--------------------------------------------------------------------------
216 
217  TessEvaluationShader::TessEvaluationShader() : Shader(GL_TESS_EVALUATION_SHADER) {}
218  TessEvaluationShader::~TessEvaluationShader() {}
219 
220 #endif // GL_ARB_tessellation_shader
221 
222  //--------------------------------------------------------------------------
223  // Compute shader
224  //--------------------------------------------------------------------------
225 
226 
227  ComputeShader::Caps ComputeShader::caps_;
228  bool ComputeShader::capsInitialized_ = false;
229 
230  ComputeShader::ComputeShader() : Shader(
231 #ifdef GL_ARB_compute_shader
232  GL_COMPUTE_SHADER
233 #else
234  0
235 #endif
236  ) {}
237  ComputeShader::~ComputeShader() {}
238 
239  const ComputeShader::Caps& ComputeShader::caps() {
240  if (!capsInitialized_) {
241  capsInitialized_ = true;
242 
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_);
253 
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);
257  }
258 #else
259  memset(&caps_, 0, sizeof(caps_));
260 #endif
261  }
262  return caps_;
263  }
264 
265  //--------------------------------------------------------------------------
266  // Shader program object
267  //--------------------------------------------------------------------------
268 
271  Program::Program() : m_programId(0), m_linkStatus(GL_FALSE) {
272  if ( !ACG::openGLVersion(2,0) ) {
273  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
274  return;
275  }
276 
277  this->m_programId = glCreateProgram();
278 
279  if ( this->m_programId == 0 ) {
280  std::cerr << "could not create GLSL program" << std::endl;
281  return;
282  }
283 
284  }
285 
289  if (this->m_programId) {
290  glDeleteProgram(this->m_programId);
291  }
292  // free linked shaders
293  this->m_linkedShaders.clear();
294  }
295 
299  if ( this->m_programId == 0 ) {
300  std::cerr << "attach invalid program" << std::endl;
301  return;
302  }
303 
304  if ( _shader->m_shaderId == 0 ) {
305  std::cerr << "attach invalid shader" << std::endl;
306  return;
307  }
308 
309  glAttachShader(this->m_programId, _shader->m_shaderId);
310  m_linkedShaders.push_back(_shader);
311  }
312 
316  if ( this->m_programId == 0 ) {
317  std::cerr << "detach invalid program" << std::endl;
318  return;
319  }
320 
321  if ( _shader->m_shaderId == 0 ) {
322  std::cerr << "detach invalid shader" << std::endl;
323  return;
324  }
325 
326  glDetachShader(this->m_programId, _shader->m_shaderId);
327  m_linkedShaders.remove(_shader);
328  }
329 
332  void Program::link() {
333  glLinkProgram(this->m_programId);
334  checkGLError2("link program failed");
335 
336  GLint status = GL_FALSE;
337  glGetProgramiv(this->m_programId, GL_LINK_STATUS, &status);
338  if ( !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;
344  }
345 
346  m_linkStatus = status;
347  }
348 
351  void Program::use() {
352  if (m_linkStatus)
353  {
354  ACG::GLState::useProgram(this->m_programId);
355  checkGLError2("use program failed");
356  }
357  }
358 
363  checkGLError2("shader disable failed");
364  }
365 
369  GLint programId;
370  glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
371  return programId == this->m_programId;
372  }
373 
377  return m_linkStatus != GL_FALSE;
378  }
379 
383  return (GLuint)m_programId;
384  }
385 
391  void Program::setUniform(const char *_name, GLint _value) {
392  checkGLError();
393  GLint location = glGetUniformLocation(this->m_programId, _name);
394  checkGLError2(_name);
395  glUniform1i(location, _value);
396  checkGLError2(_name);
397  }
398 
404  void Program::setUniform(const char *_name, const ACG::Vec2i &_value) {
405  checkGLError();
406  GLint location = glGetUniformLocation(this->m_programId, _name);
407  checkGLError2(_name);
408  glUniform2iv(location, 1, _value.data());
409  checkGLError();
410  }
411 
417  void Program::setUniform(const char *_name, const ACG::Vec3i &_value) {
418  checkGLError();
419  GLint location = glGetUniformLocation(this->m_programId, _name);
420  checkGLError2(_name);
421  glUniform3iv(location, 1, _value.data());
422  checkGLError();
423  }
424 
430  void Program::setUniform(const char *_name, const ACG::Vec4i &_value) {
431  checkGLError();
432  GLint location = glGetUniformLocation(this->m_programId, _name);
433  checkGLError2(_name);
434  glUniform4iv(location, 1, _value.data());
435  checkGLError();
436  }
437 
443  void Program::setUniform(const char *_name, GLuint _value) {
444  checkGLError();
445  GLint location = glGetUniformLocation(this->m_programId, _name);
446  checkGLError2(_name);
447  glUniform1ui(location, _value);
448  checkGLError2(_name);
449  }
450 
456  void Program::setUniform(const char *_name, const ACG::Vec2ui &_value) {
457  checkGLError();
458  GLint location = glGetUniformLocation(this->m_programId, _name);
459  checkGLError2(_name);
460  glUniform2uiv(location, 1, _value.data());
461  checkGLError();
462  }
463 
469  void Program::setUniform(const char *_name, const ACG::Vec3ui &_value) {
470  checkGLError();
471  GLint location = glGetUniformLocation(this->m_programId, _name);
472  checkGLError2(_name);
473  glUniform3uiv(location, 1, _value.data());
474  checkGLError();
475  }
476 
482  void Program::setUniform(const char *_name, const ACG::Vec4ui &_value) {
483  checkGLError();
484  GLint location = glGetUniformLocation(this->m_programId, _name);
485  checkGLError2(_name);
486  glUniform4uiv(location, 1, _value.data());
487  checkGLError();
488  }
489 
495  void Program::setUniform(const char *_name, GLfloat _value) {
496  checkGLError2("prev opengl error");
497  GLint location = glGetUniformLocation(this->m_programId, _name);
498  checkGLError2(_name);
499  glUniform1f(location, _value);
500  checkGLError2(_name);
501  }
502 
508  void Program::setUniform(const char *_name, const ACG::Vec2f &_value) {
509  checkGLError();
510  GLint location = glGetUniformLocation(this->m_programId, _name);
511  checkGLError2(_name);
512  glUniform2fv(location, 1, _value.data());
513  checkGLError();
514  }
515 
521  void Program::setUniform(const char *_name, const ACG::Vec3f &_value) {
522  checkGLError();
523  GLint location = glGetUniformLocation(this->m_programId, _name);
524  checkGLError2(_name);
525  glUniform3fv(location, 1, _value.data());
526  checkGLError();
527  }
528 
534  void Program::setUniform(const char *_name, const ACG::Vec4f &_value) {
535  checkGLError();
536  GLint location = glGetUniformLocation(this->m_programId, _name);
537  checkGLError2(_name);
538  glUniform4fv(location, 1, _value.data());
539  checkGLError();
540  }
541 
548  void Program::setUniform(const char *_name, const GLint *_values, int _count) {
549  checkGLError();
550  GLint location = glGetUniformLocation(this->m_programId, _name);
551  checkGLError2(_name);
552  glUniform1iv(location, _count, _values);
553  checkGLError();
554  }
555 
562  void Program::setUniform(const char *_name, const GLfloat *_values, int _count) {
563  checkGLError();
564  GLint location = glGetUniformLocation(this->m_programId, _name);
565  checkGLError2(_name);
566  glUniform1fv(location, _count, _values);
567  checkGLError();
568  }
569 
576  void Program::setUniform(const char *_name, const ACG::Vec2f* _values, int _count) {
577  checkGLError();
578  GLint location = glGetUniformLocation(this->m_programId, _name);
579  checkGLError2(_name);
580  glUniform2fv(location, _count, (GLfloat*)_values);
581  checkGLError();
582  }
583 
590  void Program::setUniform(const char *_name, const ACG::Vec3f* _values, int _count) {
591  checkGLError();
592  GLint location = glGetUniformLocation(this->m_programId, _name);
593  checkGLError2(_name);
594  glUniform3fv(location, _count, (GLfloat*)_values);
595  checkGLError();
596  }
597 
604  void Program::setUniform(const char *_name, const ACG::Vec4f* _values, int _count) {
605  checkGLError();
606  GLint location = glGetUniformLocation(this->m_programId, _name);
607  checkGLError2(_name);
608  glUniform4fv(location, _count, (GLfloat*)_values);
609  checkGLError();
610  }
611 
618  void Program::setUniform(const char *_name, int _index, bool _value) {
619  char varName[1024];
620  snprintf(varName, 1024, "%s[%d]", _name, _index);
621  setUniform(varName, (GLint) _value);
622  }
623 
630  void Program::setUniform(const char *_name, int _index, int _value) {
631  char varName[1024];
632  snprintf(varName, 1024, "%s[%d]", _name, _index);
633  setUniform(varName, (GLint) _value);
634  }
635 
642  void Program::setUniform(const char *_name, int _index, float _value) {
643  char varName[1024];
644  snprintf(varName, 1024, "%s[%d]", _name, _index);
645  setUniform(varName, _value);
646  }
647 
648 
655  void Program::setUniform( const char *_name, const ACG::GLMatrixf &_value, bool _transposed){
656  checkGLError();
657  GLint location = glGetUniformLocation(this->m_programId, _name);
658  checkGLError2(_name);
659  glUniformMatrix4fv(location, 1, _transposed, _value.data());
660  checkGLError();
661  }
662 
669  void Program::setUniformMat3( const char *_name, const ACG::GLMatrixf &_value, bool _transposed){
670  checkGLError();
671  GLint location = glGetUniformLocation(this->m_programId, _name);
672  checkGLError2(_name);
673 
674  float tmp[9];
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];
678 
679  glUniformMatrix3fv(location, 1, _transposed, tmp);
680  checkGLError();
681  }
682 
688  void Program::bindAttributeLocation(unsigned int _index, const char *_name) {
689  glBindAttribLocation(this->m_programId, _index, _name);
690  checkGLError2(_name);
691  }
692 
698  void Program::bindFragDataLocation(unsigned int _index, const char *_name) {
699  glBindFragDataLocationEXT(this->m_programId, _index, _name);
700  checkGLError2(_name);
701  }
702 
708  int Program::getAttributeLocation(const char *_name) {
709  int attributeLocation = glGetAttribLocation(this->m_programId, _name);
710  checkGLError2(_name);
711  return attributeLocation;
712  }
713 
719  int Program::getUniformLocation(const char *_name) {
720  int attributeLocation = glGetUniformLocation(this->m_programId, _name);
721  checkGLError2(_name);
722  return attributeLocation;
723  }
724 
730  int Program::getFragDataLocation(const char *_name) {
731  int attributeLocation = glGetFragDataLocationEXT(this->m_programId, _name);
732  checkGLError2(_name);
733  return attributeLocation;
734  }
735 
742  void Program::setGeometryInputType(GLint _type) {
743  glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_INPUT_TYPE_EXT, _type);
744  }
745 
752  void Program::setGeometryOutputType(GLint _type) {
753  glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_OUTPUT_TYPE_EXT, _type);
754  }
755 
762  void Program::setGeometryVertexCount(GLint _numVerticesOut){
763  glProgramParameteriEXT(this->m_programId, GL_GEOMETRY_VERTICES_OUT_EXT, _numVerticesOut);
764  }
765 
766 
773  GLuint Program::getUniformBlockIndex( const char *_name ) {
774 #ifdef GL_ARB_uniform_buffer_object
775  GLuint idx = glGetUniformBlockIndex(m_programId, _name);
776  checkGLError2(_name);
777  return idx;
778 #else
779  return 0xFFFFFFFF;
780 #endif
781  }
782 
789  void Program::setUniformBlockBinding( GLuint _index, int _binding ) {
790 #ifdef GL_ARB_uniform_buffer_object
791  glUniformBlockBinding(m_programId, _index, GLuint(_binding));
792  checkGLError();
793 #endif
794  }
795 
802  void Program::setUniformBlockBinding( const char* _name, int _binding ) {
803  GLuint idx = getUniformBlockIndex(_name);
804  setUniformBlockBinding(idx, _binding);
805  }
806 
813  int Program::getUniformBlockSize( GLuint _index ) {
814  GLint bufsize = 0;
815 #ifdef GL_ARB_uniform_buffer_object
816  glGetActiveUniformBlockiv(m_programId, _index, GL_UNIFORM_BLOCK_DATA_SIZE, &bufsize);
817  checkGLError();
818 #endif
819  return bufsize;
820  }
821 
828  int Program::getUniformBlockSize( const char* _name ) {
829  GLuint idx = getUniformBlockIndex(_name);
830  return getUniformBlockSize(idx);
831  }
832 
840  void Program::getUniformBlockOffsets( int _numUniforms, const char **_names, int *_outOffsets ) {
841 #ifdef GL_ARB_uniform_buffer_object
842  GLuint* idx = new GLuint[_numUniforms];
843  glGetUniformIndices(m_programId, _numUniforms, _names, idx);
844  checkGLError();
845  glGetActiveUniformsiv(m_programId, _numUniforms, idx, GL_UNIFORM_OFFSET, _outOffsets);
846  checkGLError();
847  delete [] idx;
848 #endif
849  }
850 
851 
861  void loadShaderRec(const char *filename, bool appendNewLineChar, std::map<QString, int>& includeMap, GLSL::StringList& shaderSource){
862  QString path_file;
863  if (QDir(filename).isRelative()) {
864  path_file = qApp->applicationDirPath() + QString("/../shader/")
865  + QString(filename);
866  } else {
867  path_file = QString::fromLatin1(filename);
868  }
869 
870  // avoid include loop
871  std::map<QString, int>::iterator includeIter = includeMap.find(path_file);
872 
873  if (includeIter == includeMap.end()){
874  includeMap[path_file] = 1;
875 
876  std::ifstream iShader(path_file.toLatin1());
877  if (!iShader) {
878  std::cout << "ERROR: Could not open file " << path_file.toStdString() << std::endl;
879  return;
880  }
881 
882  while (!iShader.eof()) {
883  std::string strLine;
884  std::getline(iShader, strLine);
885 
886  // check for includes
887  QString qstrLine = strLine.c_str();
888  if (qstrLine.trimmed().startsWith("#include")) {
889 
890  // try to load included file
891  QString strIncludeFile = qstrLine.remove("#include ").remove('\"').remove('<').remove('>').trimmed();
892  QFileInfo loadedShaderFile(path_file);
893  QString includePath = loadedShaderFile.absolutePath();
894 
895  if (strIncludeFile.isEmpty())
896  std::cout << "wrong include syntax: " << strLine.c_str() << std::endl;
897  else {
898  QString fullPathToIncludeFile = includePath + QDir::separator() + strIncludeFile;
899 
900  loadShaderRec(fullPathToIncludeFile.toLatin1(), appendNewLineChar, includeMap, shaderSource);
901  }
902  }
903  else {
904  if (appendNewLineChar)
905  strLine += "\n";
906  shaderSource.push_back(strLine);
907  }
908  }
909  iShader.close();
910  }
911  }
912 
927  GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList* outIncludes) {
928 
929  GLSL::StringList src;
930 
931  std::map<QString, int> includeMap;
932  loadShaderRec(filename, appendNewLineChar, includeMap, src);
933 
934 
935  // add preprocesor macros
936  if (macros && !macros->empty() && !macros->front().empty())
937  {
938  bool foundVersionDirective = false;
939 
940  for (GLSL::StringList::iterator it = src.begin(); it != src.end(); ++it)
941  {
942  QString qstr = it->c_str();
943  if (qstr.trimmed().startsWith("#version "))
944  {
945  foundVersionDirective = true;
946 
947  // insert preprocessor macros in the next line
948  ++it;
949  for (GLSL::StringList::const_iterator itMacro = macros->begin(); itMacro != macros->end(); ++itMacro)
950  src.insert(it, *itMacro + "\n");
951 
952  break;
953  }
954  }
955 
956  if (!foundVersionDirective)
957  {
958  // shader did not contain a #version directive
959  // add preprocessor macros to beginning of shader
960  for (GLSL::StringList::const_reverse_iterator it = macros->rbegin(); it != macros->rend(); ++it)
961  src.push_front(*it + "\n");
962  }
963  }
964 
965  if (outIncludes)
966  {
967  for (std::map<QString, int>::iterator it = includeMap.begin(); it != includeMap.end(); ++it)
968  outIncludes->push_back(it->first.toStdString());
969  }
970  return src;
971  }
972 
975  GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose) {
976  PtrVertexShader vertexShader = 0;
977  StringList sourceVertex = loadShader(name, macros);
978 
979  if (!sourceVertex.empty() ) {
980  vertexShader = new GLSL::VertexShader();
981  vertexShader->setSource(sourceVertex);
982  vertexShader->compile(verbose);
983  }
984  return vertexShader;
985  }
986 
989  GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose) {
990  PtrFragmentShader fragmentShader = 0;
991  StringList sourceVertex = loadShader(name, macros);
992 
993  if ( !sourceVertex.empty() ) {
994  fragmentShader = new GLSL::FragmentShader();
995  fragmentShader->setSource(sourceVertex);
996  if (!fragmentShader->compile(verbose)) {
997  delete fragmentShader;
998  fragmentShader = 0;
999  }
1000  }
1001  return fragmentShader;
1002  }
1003 
1006  GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1007  PtrGeometryShader geometryShader = 0;
1008  StringList sourceVertex = loadShader(name, macros);
1009 
1010  if (!sourceVertex.empty()) {
1011  geometryShader = new GLSL::GeometryShader();
1012  geometryShader->setSource(sourceVertex);
1013  if (!geometryShader->compile(verbose)) {
1014  delete geometryShader;
1015  geometryShader = 0;
1016  }
1017  }
1018  return geometryShader;
1019  }
1020 
1021 
1024  GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1025  GLSL::PtrShader shader = 0;
1026 #ifdef GL_ARB_tessellation_shader
1027  StringList src = loadShader(name, macros);
1028 
1029  if (!src.empty()) {
1030  shader = new GLSL::TessControlShader();
1031  shader->setSource(src);
1032  if (!shader->compile(verbose)) {
1033  delete shader;
1034  shader = 0;
1035  }
1036  }
1037 #endif // GL_ARB_tessellation_shader
1038  return shader;
1039  }
1040 
1043  GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1044  GLSL::PtrShader shader = 0;
1045 #ifdef GL_ARB_tessellation_shader
1046  StringList src = loadShader(name, macros);
1047 
1048  if (!src.empty()) {
1049  shader = new GLSL::TessEvaluationShader();
1050  shader->setSource(src);
1051  if (!shader->compile(verbose)) {
1052  delete shader;
1053  shader = 0;
1054  }
1055  }
1056 #endif // GL_ARB_tessellation_shader
1057  return shader;
1058  }
1059 
1060 
1063  GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1064  GLSL::PtrComputeShader shader = 0;
1065 #ifdef GL_ARB_compute_shader
1066  StringList src = loadShader(name, macros);
1067 
1068  if (!src.empty()) {
1069  shader = new GLSL::ComputeShader();
1070  shader->setSource(src);
1071  if (!shader->compile(verbose)) {
1072  delete shader;
1073  shader = 0;
1074  }
1075  }
1076 #endif // GL_ARB_compute_shader
1077  return shader;
1078  }
1079 
1080 
1081 
1082  GLSL::PtrProgram loadProgram(const char *vertexShaderFile,
1083  const char *tessControlShaderFile,
1084  const char *tessEvaluationShaderFile,
1085  const char *geometryShaderFile,
1086  const char *fragmentShaderFile,
1087  const GLSL::StringList *macros,
1088  bool verbose){
1089 
1090  GLSL::Program* result = 0;
1091 
1092  const int numShaders = 5;
1093  const char* ShaderFiles[numShaders] = {vertexShaderFile, tessControlShaderFile, tessEvaluationShaderFile, geometryShaderFile, fragmentShaderFile};
1094  GLSL::Shader* tempShaders[numShaders] = {0};
1095 
1096  for (int i = 0; i < numShaders; ++i) {
1097 
1098  QString inputFile = ShaderFiles[i];
1099  if (ShaderFiles[i] && !inputFile.isEmpty()) {
1100  QDir inputFileDir = inputFile;
1101 
1102  // eventually add shader dir to relative filepath
1103  QString shaderFile = inputFile;
1104  if (inputFileDir.isRelative())
1105  shaderFile = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + inputFile;
1106 
1107  if (i == 0) // vertex shader
1108  tempShaders[i] = GLSL::loadVertexShader(shaderFile.toUtf8(), macros, verbose);
1109  else if (i == 1 && tessControlShaderFile) // tesscontrol shader
1110  tempShaders[i] = GLSL::loadTessControlShader(shaderFile.toUtf8(), macros, verbose);
1111  else if (i == 2 && tessEvaluationShaderFile) // tesseval shader
1112  tempShaders[i] = GLSL::loadTessEvaluationShader(shaderFile.toUtf8(), macros, verbose);
1113  else if (i == 3 && geometryShaderFile) // geometry shader
1114  tempShaders[i] = GLSL::loadGeometryShader(shaderFile.toUtf8(), macros, verbose);
1115  else if (i == 4) // fragment shader
1116  tempShaders[i] = GLSL::loadFragmentShader(shaderFile.toUtf8(), macros, verbose);
1117 
1118  if (!tempShaders[i] && ShaderFiles[i]) {
1119  if (verbose)
1120  std::cerr << ShaderFiles[i] << " could not be loaded and compiled" << std::endl;
1121 
1122  // avoid memleak
1123  for (int k = 0; k < numShaders; ++k)
1124  delete tempShaders[k];
1125 
1126  return 0;
1127  }
1128  }
1129  }
1130 
1131  // create program
1132 
1133  result = new GLSL::Program();
1134  for (int i = 0; i < numShaders; ++i)
1135  if (tempShaders[i])
1136  result->attach(tempShaders[i]);
1137  result->link();
1138 
1139  for (int i = 0; i < numShaders; ++i)
1140  delete tempShaders[i];
1141 
1142  if (verbose)
1144 
1145 
1146  return result;
1147  }
1148 
1149  GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose){
1150 
1151  return loadProgram(vertexShaderFile, 0, 0, geometryShaderFile, fragmentShaderFile, macros, verbose);
1152  }
1153 
1154 
1155  GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose){
1156  return loadProgram(vertexShaderFile, 0, fragmentShaderFile, macros, verbose);
1157  }
1158 
1159 
1160  GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros /* = 0 */, bool verbose /* = true */) {
1161  GLSL::PtrProgram result = 0;
1162 
1163  QString inputFile = computeShaderFile;
1164  if (computeShaderFile && !inputFile.isEmpty()) {
1165  QDir inputFileDir = inputFile;
1166 
1167  // eventually add shader dir to relative filepath
1168  QString shaderFile = inputFile;
1169  if (inputFileDir.isRelative())
1170  shaderFile = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + inputFile;
1171 
1172  GLSL::PtrShader sh = GLSL::loadComputeShader(computeShaderFile, macros, verbose);
1173 
1174  if (!sh) {
1175  if (verbose)
1176  std::cerr << computeShaderFile << " could not be loaded and compiled" << std::endl;
1177 
1178  // avoid memleak
1179  delete sh;
1180 
1181  return 0;
1182  }
1183 
1184 
1185  // create program
1186  result = new GLSL::Program();
1187  result->attach(sh);
1188  result->link();
1189 
1190  delete sh;
1191 
1192  if (verbose)
1194  }
1195 
1196  return result;
1197  }
1198 
1199 
1200 }
1201 
1202 
1203 //==============================================================================
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
Definition: GLSLShader.cc:789
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:698
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:298
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:989
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:109
GLSL compute shader.
Definition: GLSLShader.hh:176
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:152
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:376
A generic shader base class.
Definition: GLSLShader.hh:77
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1160
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:773
virtual ~Shader()
Deletes the shader object.
Definition: GLSLShader.cc:101
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:669
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1082
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
Definition: GLState.cc:2073
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
GLSL vertex shader.
Definition: GLSLShader.hh:101
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Definition: GLSLShader.cc:927
Shader(GLenum shaderType)
Creates a new shader.
Definition: GLSLShader.cc:83
static QString getShaderDir()
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
Definition: GLSLShader.cc:1043
GLSL geometry shader.
Definition: GLSLShader.hh:130
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:730
void setGeometryInputType(GLint _type)
Set Type of Geometry.
Definition: GLSLShader.cc:742
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:1006
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
Definition: GLSLShader.cc:288
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
Definition: GLSLShader.cc:1024
void loadShaderRec(const char *filename, bool appendNewLineChar, std::map< QString, int > &includeMap, GLSL::StringList &shaderSource)
Loads the shader source and all recursive includes.
Definition: GLSLShader.cc:861
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
Definition: GLSLShader.cc:708
Program()
Creates a new GLSL program object.
Definition: GLSLShader.cc:271
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:840
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
Definition: GLSLShader.cc:762
void setGeometryOutputType(GLint _type)
Set output type of geometry.
Definition: GLSLShader.cc:752
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:813
int getUniformLocation(const char *_name)
Get location of the specified uniform.
Definition: GLSLShader.cc:719
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
Definition: GLSLShader.cc:1063
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:975
bool isActive()
Returns if the program object is currently active.
Definition: GLSLShader.cc:368
This namespace contains all the classes and functions for handling GLSL shader and program objects...
Definition: AntiAliasing.hh:75
GLSL fragment shader.
Definition: GLSLShader.hh:116
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
Definition: GLSLShader.cc:315
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
Definition: GLSLShader.cc:688
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:382
GLSL program class.
Definition: GLSLShader.hh:217
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:193
void glCheckErrors()
Definition: GLError.hh:105