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
67namespace 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
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
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
737 glProgramParameteri(this->m_programId, GL_GEOMETRY_INPUT_TYPE_EXT, _type);
738 }
739
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//==============================================================================
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
Definition: GLState.cc:2200
static QString getShaderDir()
GLSL compute shader.
Definition: GLSLShader.hh:170
GLSL fragment shader.
Definition: GLSLShader.hh:110
GLSL geometry shader.
Definition: GLSLShader.hh:124
GLSL program class.
Definition: GLSLShader.hh:211
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
Definition: GLSLShader.cc:756
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
Definition: GLSLShader.cc:783
void setGeometryOutputType(GLint _type)
Set output type of geometry.
Definition: GLSLShader.cc:746
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:370
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
Definition: GLSLShader.cc:682
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:376
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:724
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:834
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:807
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:663
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
Definition: GLSLShader.cc:702
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
Definition: GLSLShader.cc:309
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:767
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
Definition: GLSLShader.cc:282
int getUniformLocation(const char *_name)
Get location of the specified uniform.
Definition: GLSLShader.cc:713
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:355
bool isActive()
Returns if the program object is currently active.
Definition: GLSLShader.cc:362
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:326
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
Program()
Creates a new GLSL program object.
Definition: GLSLShader.cc:265
void setGeometryInputType(GLint _type)
Set Type of Geometry.
Definition: GLSLShader.cc:736
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:692
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:292
A generic shader base class.
Definition: GLSLShader.hh:71
virtual ~Shader()
Deletes the shader object.
Definition: GLSLShader.cc:95
Shader(GLenum shaderType)
Creates a new shader.
Definition: GLSLShader.cc:77
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:146
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:103
GLSL vertex shader.
Definition: GLSLShader.hh:95
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:201
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
void glCheckErrors()
Definition: GLError.hh:96
This namespace contains all the classes and functions for handling GLSL shader and program objects.
Definition: AntiAliasing.hh:66
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 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
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:983
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
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:1000
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
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::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Definition: GLSLShader.cc:921
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1154
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:969