Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
101 Shader::~Shader() {
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
288 Program::~Program() {
289 if (this->m_programId) {
290 glDeleteProgram(this->m_programId);
291 }
292 // free linked shaders
293 this->m_linkedShaders.clear();
294 }
295
298 void Program::attach(PtrConstShader _shader) {
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
315 void Program::detach(PtrConstShader _shader) {
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
361 void Program::disable() {
362 ACG::GLState::useProgram(0);
363 checkGLError2("shader disable failed");
364 }
365
368 bool Program::isActive() {
369 GLint programId;
370 glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
371 return programId == this->m_programId;
372 }
373
376 bool Program::isLinked() {
377 return m_linkStatus != GL_FALSE;
378 }
379
382 GLuint Program::getProgramId() {
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)
1143 ACG::glCheckErrors();
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)
1193 ACG::glCheckErrors();
1194 }
1195
1196 return result;
1197 }
1198
1199
1200 }
1201
1202
1203 //==============================================================================
GLSL::loadShader
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Definition: GLSLShader.cc:927
GLSL::loadComputeProgram
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1160
GLSL::Shader::setSource
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:109
GLSL::Program::getFragDataLocation
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:730
GLSL::Program::setGeometryInputType
void setGeometryInputType(GLint _type)
Set Type of Geometry.
Definition: GLSLShader.cc:742
GLSL::loadVertexShader
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:975
GLSL::Program::Program
Program()
Creates a new GLSL program object.
Definition: GLSLShader.cc:271
GLSL::GeometryShader
GLSL geometry shader.
Definition: GLSLShader.hh:130
GLSL::FragmentShader
GLSL fragment shader.
Definition: GLSLShader.hh:116
GLSL::Program::setGeometryOutputType
void setGeometryOutputType(GLint _type)
Set output type of geometry.
Definition: GLSLShader.cc:752
VectorT< signed int, 4 >
GLSL::Program::bindFragDataLocation
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:698
GLSL::loadProgram
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
GLSL::Program::detach
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
Definition: GLSLShader.cc:315
GLSL::Program::~Program
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
Definition: GLSLShader.cc:288
GLSL::Program::getAttributeLocation
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
Definition: GLSLShader.cc:708
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
GLSL::VertexShader
GLSL vertex shader.
Definition: GLSLShader.hh:101
GLSL::Program::getUniformBlockSize
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
Definition: GLSLShader.cc:813
GLSL::loadFragmentShader
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:989
GLSL::Program::getUniformBlockIndex
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
Definition: GLSLShader.cc:773
GLSL::Program::use
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
ACG::GLMatrixT< float >
GLSL::Shader
A generic shader base class.
Definition: GLSLShader.hh:77
GLSL::Program::getProgramId
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:382
GLSL::Shader::~Shader
virtual ~Shader()
Deletes the shader object.
Definition: GLSLShader.cc:101
GLSL::Program::isLinked
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:376
GLSL::Shader::compile
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:152
GLSL::Program::setGeometryVertexCount
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
Definition: GLSLShader.cc:762
OpenMesh::VectorT
Definition: Vector11T.hh:83
GLSL::Program::isActive
bool isActive()
Returns if the program object is currently active.
Definition: GLSLShader.cc:368
GLSL::Program::link
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
GLSL
This namespace contains all the classes and functions for handling GLSL shader and program objects...
Definition: AntiAliasing.hh:75
ACG::glCheckErrors
void glCheckErrors()
Definition: GLError.hh:105
ACG::GLState::useProgram
static void useProgram(GLuint _program)
replaces glUseProgram, supports locking
Definition: GLState.cc:2073
GLSL::loadGeometryShader
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:1006
GLSL::Program::setUniform
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:217
GLSL::loadTessControlShader
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
GLSL::Program::getUniformBlockOffsets
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
Definition: GLSLShader.cc:840
GLSL::loadShaderRec
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
GLSL::loadTessEvaluationShader
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::Program::bindAttributeLocation
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
Definition: GLSLShader.cc:688
GLSL::Program::disable
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
GLSL::Shader::Shader
Shader(GLenum shaderType)
Creates a new shader.
Definition: GLSLShader.cc:83
GLSL::Program::attach
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:298
GLSL::Program::getUniformLocation
int getUniformLocation(const char *_name)
Get location of the specified uniform.
Definition: GLSLShader.cc:719
ACG::ShaderProgGenerator::getShaderDir
static QString getShaderDir()
Definition: ShaderGenerator.cc:2406
GLSL::Program::setUniformBlockBinding
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
Definition: GLSLShader.cc:789
GLSL::loadComputeShader
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::Program::setUniformMat3
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:669
GLSL::ComputeShader
GLSL compute shader.
Definition: GLSLShader.hh:176