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 #include <ACG/GL/acg_glew.hh>
45 
46 #include <QApplication>
47 #include <QDir>
48 
49 #include <iostream>
50 #include <fstream>
51 
52 #include <ACG/GL/gl.hh>
53 #include <ACG/GL/GLState.hh>
54 #include <ACG/GL/GLError.hh>
55 
56 #include "GLSLShader.hh"
57 #include <ACG/GL/ShaderGenerator.hh>
58 
59 #ifdef WIN32
60  #ifndef __MINGW32__
61  #define snprintf sprintf_s
62  #endif
63 #endif
64 
65 //==============================================================================
66 
67 namespace GLSL {
68 
69  //--------------------------------------------------------------------------
70  // Generic shader
71  //--------------------------------------------------------------------------
72 
77  Shader::Shader(GLenum shaderType)
78  : m_shaderId(0)
79  {
80 
81  if ( !ACG::openGLVersion(2,0) ) {
82  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
83  return;
84  }
85 
86  this->m_shaderId = glCreateShader(shaderType);
87  if ( this->m_shaderId == 0 ) {
88  std::cerr << "could not create shader" << std::endl;
89  }
90 
91  }
92 
96  if (this->m_shaderId) {
97  glDeleteShader(m_shaderId);
98  }
99  }
100 
103  void Shader::setSource(const StringList& source) {
104 
105  if ( this->m_shaderId == 0 ) {
106  std::cerr << "shader not initialized" << std::endl;
107  return;
108  }
109 
110  const char **stringArray = new const char*[source.size()];
111 
112  int index = 0;
113  for (StringList::const_iterator it = source.begin();it != source.end();++it) {
114  stringArray[index] = (*it).c_str();
115  ++index;
116  }
117 
118  glShaderSource(this->m_shaderId, int(source.size()), stringArray, 0);
119 
120  delete[] stringArray;
121  }
122 
123 
126  void Shader::setSource(const QStringList& source) {
127 
128  if ( this->m_shaderId == 0 ) {
129  std::cerr << "shader not initialized" << std::endl;
130  return;
131  }
132 
133  StringList strlist;
134 
135  for (QStringList::const_iterator it = source.begin();it != source.end();++it)
136  strlist.push_back(std::string((const char*)it->toLatin1()) + '\n');
137 
138  setSource(strlist);
139  }
140 
146  bool Shader::compile(bool verbose) {
147  if ( this->m_shaderId == 0 ) {
148  std::cerr << "shader not initialized" << std::endl;
149  return false;
150  }
151 
152  glCompileShader(m_shaderId);
153 
154  GLint compileStatus;
155  glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &compileStatus);
156  if (compileStatus == GL_FALSE) {
157 
158  if (verbose) {
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;
167 
168  delete[] shaderSource;
169  delete[] errorLog;
170  }
171 
172  return false;
173  }
174  return true;
175  }
176 
177  //--------------------------------------------------------------------------
178  // Vertex shader
179  //--------------------------------------------------------------------------
180 
181  VertexShader::VertexShader() : Shader(GL_VERTEX_SHADER) {}
182  VertexShader::~VertexShader() {}
183 
184  //--------------------------------------------------------------------------
185  // Fragment shader
186  //--------------------------------------------------------------------------
187 
188  FragmentShader::FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
189  FragmentShader::~FragmentShader() {}
190 
191  //--------------------------------------------------------------------------
192  // Geometry shader
193  //--------------------------------------------------------------------------
194 
195  GeometryShader::GeometryShader() : Shader(GL_GEOMETRY_SHADER_EXT) {}
196  GeometryShader::~GeometryShader() {}
197 
198  //--------------------------------------------------------------------------
199  // Tessellation-Control shader
200  //--------------------------------------------------------------------------
201 
202 #ifdef GL_ARB_tessellation_shader
203 
204  TessControlShader::TessControlShader() : Shader(GL_TESS_CONTROL_SHADER) {}
205  TessControlShader::~TessControlShader() {}
206 
207  //--------------------------------------------------------------------------
208  // Tessellation-Evaluation shader
209  //--------------------------------------------------------------------------
210 
211  TessEvaluationShader::TessEvaluationShader() : Shader(GL_TESS_EVALUATION_SHADER) {}
212  TessEvaluationShader::~TessEvaluationShader() {}
213 
214 #endif // GL_ARB_tessellation_shader
215 
216  //--------------------------------------------------------------------------
217  // Compute shader
218  //--------------------------------------------------------------------------
219 
220 
221  ComputeShader::Caps ComputeShader::caps_;
222  bool ComputeShader::capsInitialized_ = false;
223 
224  ComputeShader::ComputeShader() : Shader(
225 #ifdef GL_ARB_compute_shader
226  GL_COMPUTE_SHADER
227 #else
228  0
229 #endif
230  ) {}
231  ComputeShader::~ComputeShader() {}
232 
233  const ComputeShader::Caps& ComputeShader::caps() {
234  if (!capsInitialized_) {
235  capsInitialized_ = true;
236 
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_);
247 
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);
251  }
252 #else
253  memset(&caps_, 0, sizeof(caps_));
254 #endif
255  }
256  return caps_;
257  }
258 
259  //--------------------------------------------------------------------------
260  // Shader program object
261  //--------------------------------------------------------------------------
262 
265  Program::Program() : m_programId(0), m_linkStatus(GL_FALSE) {
266  if ( !ACG::openGLVersion(2,0) ) {
267  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
268  return;
269  }
270 
271  this->m_programId = glCreateProgram();
272 
273  if ( this->m_programId == 0 ) {
274  std::cerr << "could not create GLSL program" << std::endl;
275  return;
276  }
277 
278  }
279 
283  if (this->m_programId) {
284  glDeleteProgram(this->m_programId);
285  }
286  // free linked shaders
287  this->m_linkedShaders.clear();
288  }
289 
293  if ( this->m_programId == 0 ) {
294  std::cerr << "attach invalid program" << std::endl;
295  return;
296  }
297 
298  if ( _shader->m_shaderId == 0 ) {
299  std::cerr << "attach invalid shader" << std::endl;
300  return;
301  }
302 
303  glAttachShader(this->m_programId, _shader->m_shaderId);
304  m_linkedShaders.push_back(_shader);
305  }
306 
310  if ( this->m_programId == 0 ) {
311  std::cerr << "detach invalid program" << std::endl;
312  return;
313  }
314 
315  if ( _shader->m_shaderId == 0 ) {
316  std::cerr << "detach invalid shader" << std::endl;
317  return;
318  }
319 
320  glDetachShader(this->m_programId, _shader->m_shaderId);
321  m_linkedShaders.remove(_shader);
322  }
323 
326  void Program::link() {
327  glLinkProgram(this->m_programId);
328  checkGLError2("link program failed");
329 
330  GLint status = GL_FALSE;
331  glGetProgramiv(this->m_programId, GL_LINK_STATUS, &status);
332  if ( !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;
338  }
339 
340  m_linkStatus = status;
341  }
342 
345  void Program::use() {
346  if (m_linkStatus)
347  {
348  ACG::GLState::useProgram(this->m_programId);
349  checkGLError2("use program failed");
350  }
351  }
352 
357  checkGLError2("shader disable failed");
358  }
359 
363  GLint programId;
364  glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
365  return programId == this->m_programId;
366  }
367 
371  return m_linkStatus != GL_FALSE;
372  }
373 
377  return (GLuint)m_programId;
378  }
379 
385  void Program::setUniform(const char *_name, GLint _value) {
386  checkGLError();
387  GLint location = glGetUniformLocation(this->m_programId, _name);
388  checkGLError2(_name);
389  glUniform1i(location, _value);
390  checkGLError2(_name);
391  }
392 
398  void Program::setUniform(const char *_name, const ACG::Vec2i &_value) {
399  checkGLError();
400  GLint location = glGetUniformLocation(this->m_programId, _name);
401  checkGLError2(_name);
402  glUniform2iv(location, 1, _value.data());
403  checkGLError();
404  }
405 
411  void Program::setUniform(const char *_name, const ACG::Vec3i &_value) {
412  checkGLError();
413  GLint location = glGetUniformLocation(this->m_programId, _name);
414  checkGLError2(_name);
415  glUniform3iv(location, 1, _value.data());
416  checkGLError();
417  }
418 
424  void Program::setUniform(const char *_name, const ACG::Vec4i &_value) {
425  checkGLError();
426  GLint location = glGetUniformLocation(this->m_programId, _name);
427  checkGLError2(_name);
428  glUniform4iv(location, 1, _value.data());
429  checkGLError();
430  }
431 
437  void Program::setUniform(const char *_name, GLuint _value) {
438  checkGLError();
439  GLint location = glGetUniformLocation(this->m_programId, _name);
440  checkGLError2(_name);
441  glUniform1ui(location, _value);
442  checkGLError2(_name);
443  }
444 
450  void Program::setUniform(const char *_name, const ACG::Vec2ui &_value) {
451  checkGLError();
452  GLint location = glGetUniformLocation(this->m_programId, _name);
453  checkGLError2(_name);
454  glUniform2uiv(location, 1, _value.data());
455  checkGLError();
456  }
457 
463  void Program::setUniform(const char *_name, const ACG::Vec3ui &_value) {
464  checkGLError();
465  GLint location = glGetUniformLocation(this->m_programId, _name);
466  checkGLError2(_name);
467  glUniform3uiv(location, 1, _value.data());
468  checkGLError();
469  }
470 
476  void Program::setUniform(const char *_name, const ACG::Vec4ui &_value) {
477  checkGLError();
478  GLint location = glGetUniformLocation(this->m_programId, _name);
479  checkGLError2(_name);
480  glUniform4uiv(location, 1, _value.data());
481  checkGLError();
482  }
483 
489  void Program::setUniform(const char *_name, GLfloat _value) {
490  checkGLError2("prev opengl error");
491  GLint location = glGetUniformLocation(this->m_programId, _name);
492  checkGLError2(_name);
493  glUniform1f(location, _value);
494  checkGLError2(_name);
495  }
496 
502  void Program::setUniform(const char *_name, const ACG::Vec2f &_value) {
503  checkGLError();
504  GLint location = glGetUniformLocation(this->m_programId, _name);
505  checkGLError2(_name);
506  glUniform2fv(location, 1, _value.data());
507  checkGLError();
508  }
509 
515  void Program::setUniform(const char *_name, const ACG::Vec3f &_value) {
516  checkGLError();
517  GLint location = glGetUniformLocation(this->m_programId, _name);
518  checkGLError2(_name);
519  glUniform3fv(location, 1, _value.data());
520  checkGLError();
521  }
522 
528  void Program::setUniform(const char *_name, const ACG::Vec4f &_value) {
529  checkGLError();
530  GLint location = glGetUniformLocation(this->m_programId, _name);
531  checkGLError2(_name);
532  glUniform4fv(location, 1, _value.data());
533  checkGLError();
534  }
535 
542  void Program::setUniform(const char *_name, const GLint *_values, int _count) {
543  checkGLError();
544  GLint location = glGetUniformLocation(this->m_programId, _name);
545  checkGLError2(_name);
546  glUniform1iv(location, _count, _values);
547  checkGLError();
548  }
549 
556  void Program::setUniform(const char *_name, const GLfloat *_values, int _count) {
557  checkGLError();
558  GLint location = glGetUniformLocation(this->m_programId, _name);
559  checkGLError2(_name);
560  glUniform1fv(location, _count, _values);
561  checkGLError();
562  }
563 
570  void Program::setUniform(const char *_name, const ACG::Vec2f* _values, int _count) {
571  checkGLError();
572  GLint location = glGetUniformLocation(this->m_programId, _name);
573  checkGLError2(_name);
574  glUniform2fv(location, _count, (GLfloat*)_values);
575  checkGLError();
576  }
577 
584  void Program::setUniform(const char *_name, const ACG::Vec3f* _values, int _count) {
585  checkGLError();
586  GLint location = glGetUniformLocation(this->m_programId, _name);
587  checkGLError2(_name);
588  glUniform3fv(location, _count, (GLfloat*)_values);
589  checkGLError();
590  }
591 
598  void Program::setUniform(const char *_name, const ACG::Vec4f* _values, int _count) {
599  checkGLError();
600  GLint location = glGetUniformLocation(this->m_programId, _name);
601  checkGLError2(_name);
602  glUniform4fv(location, _count, (GLfloat*)_values);
603  checkGLError();
604  }
605 
612  void Program::setUniform(const char *_name, int _index, bool _value) {
613  char varName[1024];
614  snprintf(varName, 1024, "%s[%d]", _name, _index);
615  setUniform(varName, (GLint) _value);
616  }
617 
624  void Program::setUniform(const char *_name, int _index, int _value) {
625  char varName[1024];
626  snprintf(varName, 1024, "%s[%d]", _name, _index);
627  setUniform(varName, (GLint) _value);
628  }
629 
636  void Program::setUniform(const char *_name, int _index, float _value) {
637  char varName[1024];
638  snprintf(varName, 1024, "%s[%d]", _name, _index);
639  setUniform(varName, _value);
640  }
641 
642 
649  void Program::setUniform( const char *_name, const ACG::GLMatrixf &_value, bool _transposed){
650  checkGLError();
651  GLint location = glGetUniformLocation(this->m_programId, _name);
652  checkGLError2(_name);
653  glUniformMatrix4fv(location, 1, _transposed, _value.data());
654  checkGLError();
655  }
656 
663  void Program::setUniformMat3( const char *_name, const ACG::GLMatrixf &_value, bool _transposed){
664  checkGLError();
665  GLint location = glGetUniformLocation(this->m_programId, _name);
666  checkGLError2(_name);
667 
668  float tmp[9];
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];
672 
673  glUniformMatrix3fv(location, 1, _transposed, tmp);
674  checkGLError();
675  }
676 
682  void Program::bindAttributeLocation(unsigned int _index, const char *_name) {
683  glBindAttribLocation(this->m_programId, _index, _name);
684  checkGLError2(_name);
685  }
686 
692  void Program::bindFragDataLocation(unsigned int _index, const char *_name) {
693  glBindFragDataLocation(this->m_programId, _index, _name);
694  checkGLError2(_name);
695  }
696 
702  int Program::getAttributeLocation(const char *_name) {
703  int attributeLocation = glGetAttribLocation(this->m_programId, _name);
704  checkGLError2(_name);
705  return attributeLocation;
706  }
707 
713  int Program::getUniformLocation(const char *_name) {
714  int attributeLocation = glGetUniformLocation(this->m_programId, _name);
715  checkGLError2(_name);
716  return attributeLocation;
717  }
718 
724  int Program::getFragDataLocation(const char *_name) {
725  int attributeLocation = glGetFragDataLocation(this->m_programId, _name);
726  checkGLError2(_name);
727  return attributeLocation;
728  }
729 
736  void Program::setGeometryInputType(GLint _type) {
737  glProgramParameteri(this->m_programId, GL_GEOMETRY_INPUT_TYPE_EXT, _type);
738  }
739 
746  void Program::setGeometryOutputType(GLint _type) {
747  glProgramParameteri(this->m_programId, GL_GEOMETRY_OUTPUT_TYPE_EXT, _type);
748  }
749 
756  void Program::setGeometryVertexCount(GLint _numVerticesOut){
757  glProgramParameteri(this->m_programId, GL_GEOMETRY_VERTICES_OUT_EXT, _numVerticesOut);
758  }
759 
760 
767  GLuint Program::getUniformBlockIndex( const char *_name ) {
768 #ifdef GL_ARB_uniform_buffer_object
769  GLuint idx = glGetUniformBlockIndex(m_programId, _name);
770  checkGLError2(_name);
771  return idx;
772 #else
773  return 0xFFFFFFFF;
774 #endif
775  }
776 
783  void Program::setUniformBlockBinding( GLuint _index, int _binding ) {
784 #ifdef GL_ARB_uniform_buffer_object
785  glUniformBlockBinding(m_programId, _index, GLuint(_binding));
786  checkGLError();
787 #endif
788  }
789 
796  void Program::setUniformBlockBinding( const char* _name, int _binding ) {
797  GLuint idx = getUniformBlockIndex(_name);
798  setUniformBlockBinding(idx, _binding);
799  }
800 
807  int Program::getUniformBlockSize( GLuint _index ) {
808  GLint bufsize = 0;
809 #ifdef GL_ARB_uniform_buffer_object
810  glGetActiveUniformBlockiv(m_programId, _index, GL_UNIFORM_BLOCK_DATA_SIZE, &bufsize);
811  checkGLError();
812 #endif
813  return bufsize;
814  }
815 
822  int Program::getUniformBlockSize( const char* _name ) {
823  GLuint idx = getUniformBlockIndex(_name);
824  return getUniformBlockSize(idx);
825  }
826 
834  void Program::getUniformBlockOffsets( int _numUniforms, const char **_names, int *_outOffsets ) {
835 #ifdef GL_ARB_uniform_buffer_object
836  GLuint* idx = new GLuint[_numUniforms];
837  glGetUniformIndices(m_programId, _numUniforms, _names, idx);
838  checkGLError();
839  glGetActiveUniformsiv(m_programId, _numUniforms, idx, GL_UNIFORM_OFFSET, _outOffsets);
840  checkGLError();
841  delete [] idx;
842 #endif
843  }
844 
845 
855  void loadShaderRec(const char *filename, bool appendNewLineChar, std::map<QString, int>& includeMap, GLSL::StringList& shaderSource){
856  QString path_file;
857  if (QDir(filename).isRelative()) {
858  path_file = qApp->applicationDirPath() + QString("/../shader/")
859  + QString(filename);
860  } else {
861  path_file = QString::fromLatin1(filename);
862  }
863 
864  // avoid include loop
865  std::map<QString, int>::iterator includeIter = includeMap.find(path_file);
866 
867  if (includeIter == includeMap.end()){
868  includeMap[path_file] = 1;
869 
870  std::ifstream iShader(path_file.toLatin1());
871  if (!iShader) {
872  std::cout << "ERROR: Could not open file " << path_file.toStdString() << std::endl;
873  return;
874  }
875 
876  while (!iShader.eof()) {
877  std::string strLine;
878  std::getline(iShader, strLine);
879 
880  // check for includes
881  QString qstrLine = strLine.c_str();
882  if (qstrLine.trimmed().startsWith("#include")) {
883 
884  // try to load included file
885  QString strIncludeFile = qstrLine.remove("#include ").remove('\"').remove('<').remove('>').trimmed();
886  QFileInfo loadedShaderFile(path_file);
887  QString includePath = loadedShaderFile.absolutePath();
888 
889  if (strIncludeFile.isEmpty())
890  std::cout << "wrong include syntax: " << strLine.c_str() << std::endl;
891  else {
892  QString fullPathToIncludeFile = includePath + QDir::separator() + strIncludeFile;
893 
894  loadShaderRec(fullPathToIncludeFile.toLatin1(), appendNewLineChar, includeMap, shaderSource);
895  }
896  }
897  else {
898  if (appendNewLineChar)
899  strLine += "\n";
900  shaderSource.push_back(strLine);
901  }
902  }
903  iShader.close();
904  }
905  }
906 
921  GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList* outIncludes) {
922 
923  GLSL::StringList src;
924 
925  std::map<QString, int> includeMap;
926  loadShaderRec(filename, appendNewLineChar, includeMap, src);
927 
928 
929  // add preprocesor macros
930  if (macros && !macros->empty() && !macros->front().empty())
931  {
932  bool foundVersionDirective = false;
933 
934  for (GLSL::StringList::iterator it = src.begin(); it != src.end(); ++it)
935  {
936  QString qstr = it->c_str();
937  if (qstr.trimmed().startsWith("#version "))
938  {
939  foundVersionDirective = true;
940 
941  // insert preprocessor macros in the next line
942  ++it;
943  for (GLSL::StringList::const_iterator itMacro = macros->begin(); itMacro != macros->end(); ++itMacro)
944  src.insert(it, *itMacro + "\n");
945 
946  break;
947  }
948  }
949 
950  if (!foundVersionDirective)
951  {
952  // shader did not contain a #version directive
953  // add preprocessor macros to beginning of shader
954  for (GLSL::StringList::const_reverse_iterator it = macros->rbegin(); it != macros->rend(); ++it)
955  src.push_front(*it + "\n");
956  }
957  }
958 
959  if (outIncludes)
960  {
961  for (std::map<QString, int>::iterator it = includeMap.begin(); it != includeMap.end(); ++it)
962  outIncludes->push_back(it->first.toStdString());
963  }
964  return src;
965  }
966 
969  GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose) {
970  PtrVertexShader vertexShader = 0;
971  StringList sourceVertex = loadShader(name, macros);
972 
973  if (!sourceVertex.empty() ) {
974  vertexShader = new GLSL::VertexShader();
975  vertexShader->setSource(sourceVertex);
976  vertexShader->compile(verbose);
977  }
978  return vertexShader;
979  }
980 
983  GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose) {
984  PtrFragmentShader fragmentShader = 0;
985  StringList sourceVertex = loadShader(name, macros);
986 
987  if ( !sourceVertex.empty() ) {
988  fragmentShader = new GLSL::FragmentShader();
989  fragmentShader->setSource(sourceVertex);
990  if (!fragmentShader->compile(verbose)) {
991  delete fragmentShader;
992  fragmentShader = 0;
993  }
994  }
995  return fragmentShader;
996  }
997 
1000  GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1001  PtrGeometryShader geometryShader = 0;
1002  StringList sourceVertex = loadShader(name, macros);
1003 
1004  if (!sourceVertex.empty()) {
1005  geometryShader = new GLSL::GeometryShader();
1006  geometryShader->setSource(sourceVertex);
1007  if (!geometryShader->compile(verbose)) {
1008  delete geometryShader;
1009  geometryShader = 0;
1010  }
1011  }
1012  return geometryShader;
1013  }
1014 
1015 
1018  GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1019  GLSL::PtrShader shader = 0;
1020 #ifdef GL_ARB_tessellation_shader
1021  StringList src = loadShader(name, macros);
1022 
1023  if (!src.empty()) {
1024  shader = new GLSL::TessControlShader();
1025  shader->setSource(src);
1026  if (!shader->compile(verbose)) {
1027  delete shader;
1028  shader = 0;
1029  }
1030  }
1031 #endif // GL_ARB_tessellation_shader
1032  return shader;
1033  }
1034 
1037  GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1038  GLSL::PtrShader shader = 0;
1039 #ifdef GL_ARB_tessellation_shader
1040  StringList src = loadShader(name, macros);
1041 
1042  if (!src.empty()) {
1043  shader = new GLSL::TessEvaluationShader();
1044  shader->setSource(src);
1045  if (!shader->compile(verbose)) {
1046  delete shader;
1047  shader = 0;
1048  }
1049  }
1050 #endif // GL_ARB_tessellation_shader
1051  return shader;
1052  }
1053 
1054 
1057  GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose) {
1058  GLSL::PtrComputeShader shader = 0;
1059 #ifdef GL_ARB_compute_shader
1060  StringList src = loadShader(name, macros);
1061 
1062  if (!src.empty()) {
1063  shader = new GLSL::ComputeShader();
1064  shader->setSource(src);
1065  if (!shader->compile(verbose)) {
1066  delete shader;
1067  shader = 0;
1068  }
1069  }
1070 #endif // GL_ARB_compute_shader
1071  return shader;
1072  }
1073 
1074 
1075 
1076  GLSL::PtrProgram loadProgram(const char *vertexShaderFile,
1077  const char *tessControlShaderFile,
1078  const char *tessEvaluationShaderFile,
1079  const char *geometryShaderFile,
1080  const char *fragmentShaderFile,
1081  const GLSL::StringList *macros,
1082  bool verbose){
1083 
1084  GLSL::Program* result = 0;
1085 
1086  const int numShaders = 5;
1087  const char* ShaderFiles[numShaders] = {vertexShaderFile, tessControlShaderFile, tessEvaluationShaderFile, geometryShaderFile, fragmentShaderFile};
1088  GLSL::Shader* tempShaders[numShaders] = {0};
1089 
1090  for (int i = 0; i < numShaders; ++i) {
1091 
1092  QString inputFile = ShaderFiles[i];
1093  if (ShaderFiles[i] && !inputFile.isEmpty()) {
1094  QDir inputFileDir = inputFile;
1095 
1096  // eventually add shader dir to relative filepath
1097  QString shaderFile = inputFile;
1098  if (inputFileDir.isRelative())
1099  shaderFile = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + inputFile;
1100 
1101  if (i == 0) // vertex shader
1102  tempShaders[i] = GLSL::loadVertexShader(shaderFile.toUtf8(), macros, verbose);
1103  else if (i == 1 && tessControlShaderFile) // tesscontrol shader
1104  tempShaders[i] = GLSL::loadTessControlShader(shaderFile.toUtf8(), macros, verbose);
1105  else if (i == 2 && tessEvaluationShaderFile) // tesseval shader
1106  tempShaders[i] = GLSL::loadTessEvaluationShader(shaderFile.toUtf8(), macros, verbose);
1107  else if (i == 3 && geometryShaderFile) // geometry shader
1108  tempShaders[i] = GLSL::loadGeometryShader(shaderFile.toUtf8(), macros, verbose);
1109  else if (i == 4) // fragment shader
1110  tempShaders[i] = GLSL::loadFragmentShader(shaderFile.toUtf8(), macros, verbose);
1111 
1112  if (!tempShaders[i] && ShaderFiles[i]) {
1113  if (verbose)
1114  std::cerr << ShaderFiles[i] << " could not be loaded and compiled" << std::endl;
1115 
1116  // avoid memleak
1117  for (int k = 0; k < numShaders; ++k)
1118  delete tempShaders[k];
1119 
1120  return 0;
1121  }
1122  }
1123  }
1124 
1125  // create program
1126 
1127  result = new GLSL::Program();
1128  for (int i = 0; i < numShaders; ++i)
1129  if (tempShaders[i])
1130  result->attach(tempShaders[i]);
1131  result->link();
1132 
1133  for (int i = 0; i < numShaders; ++i)
1134  delete tempShaders[i];
1135 
1136  if (verbose)
1138 
1139 
1140  return result;
1141  }
1142 
1143  GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose){
1144 
1145  return loadProgram(vertexShaderFile, 0, 0, geometryShaderFile, fragmentShaderFile, macros, verbose);
1146  }
1147 
1148 
1149  GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose){
1150  return loadProgram(vertexShaderFile, 0, fragmentShaderFile, macros, verbose);
1151  }
1152 
1153 
1154  GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros /* = 0 */, bool verbose /* = true */) {
1155  GLSL::PtrProgram result = 0;
1156 
1157  QString inputFile = computeShaderFile;
1158  if (computeShaderFile && !inputFile.isEmpty()) {
1159  QDir inputFileDir = inputFile;
1160 
1161  // eventually add shader dir to relative filepath
1162  QString shaderFile = inputFile;
1163  if (inputFileDir.isRelative())
1164  shaderFile = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + inputFile;
1165 
1166  GLSL::PtrShader sh = GLSL::loadComputeShader(computeShaderFile, macros, verbose);
1167 
1168  if (!sh) {
1169  if (verbose)
1170  std::cerr << computeShaderFile << " could not be loaded and compiled" << std::endl;
1171 
1172  // avoid memleak
1173  delete sh;
1174 
1175  return 0;
1176  }
1177 
1178 
1179  // create program
1180  result = new GLSL::Program();
1181  result->attach(sh);
1182  result->link();
1183 
1184  delete sh;
1185 
1186  if (verbose)
1188  }
1189 
1190  return result;
1191  }
1192 
1193 
1194 }
1195 
1196 
1197 //==============================================================================
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:969
This namespace contains all the classes and functions for handling GLSL shader and program objects...
Definition: AntiAliasing.hh:66
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:1000
virtual ~Shader()
Deletes the shader object.
Definition: GLSLShader.cc:95
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
Definition: GLSLShader.cc:1057
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
Definition: GLSLShader.cc:783
bool isActive()
Returns if the program object is currently active.
Definition: GLSLShader.cc:362
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:807
void setGeometryInputType(GLint _type)
Set Type of Geometry.
Definition: GLSLShader.cc:736
Program()
Creates a new GLSL program object.
Definition: GLSLShader.cc:265
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:692
GLSL vertex shader.
Definition: GLSLShader.hh:95
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:376
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:355
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:195
Shader(GLenum shaderType)
Creates a new shader.
Definition: GLSLShader.cc:77
GLSL program class.
Definition: GLSLShader.hh:211
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
Definition: GLSLShader.cc:756
GLSL geometry shader.
Definition: GLSLShader.hh:124
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
Definition: GLSLShader.cc:1037
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:724
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:292
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
Definition: GLState.cc:2157
A generic shader base class.
Definition: GLSLShader.hh:71
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:326
int getUniformLocation(const char *_name)
Get location of the specified uniform.
Definition: GLSLShader.cc:713
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
Definition: GLSLShader.cc:309
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Definition: GLSLShader.cc:921
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:663
static QString getShaderDir()
GLSL fragment shader.
Definition: GLSLShader.hh:110
void glCheckErrors()
Definition: GLError.hh:96
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
Definition: GLSLShader.cc:282
void setGeometryOutputType(GLint _type)
Set output type of geometry.
Definition: GLSLShader.cc:746
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:767
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
Definition: GLSLShader.cc:702
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:1076
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1154
GLSL compute shader.
Definition: GLSLShader.hh:170
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:146
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:834
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:983
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
Definition: GLSLShader.cc:682
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:370
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:855
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:103
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
Definition: GLSLShader.cc:1018
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129