Developer Documentation
Loading...
Searching...
No Matches
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
GLSL compute shader.
GLSL fragment shader.
GLSL geometry shader.
GLSL program class.
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
void setUniformBlockBinding(GLuint _index, int _binding)
Set binding point of a uniform buffer.
void setGeometryOutputType(GLint _type)
Set output type of geometry.
bool isLinked()
Returns if the program object has been succesfully linked.
void bindAttributeLocation(unsigned int _index, const char *_name)
Bind attribute to name.
GLuint getProgramId()
Returns opengl id.
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
void getUniformBlockOffsets(int _numUniforms, const char **_names, int *_outOffsets)
Get offsets of uniforms in a uniform buffer.
int getUniformBlockSize(GLuint _index)
Get size in bytes of a uniform buffer.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
int getAttributeLocation(const char *_name)
Get location of the specified attribute.
void detach(PtrConstShader _shader)
Detaches a shader object from the program object.
GLuint getUniformBlockIndex(const char *_name)
Get location of the specified uniform buffer.
virtual ~Program()
Deletes the GLSL program object and frees the linked shader objects.
int getUniformLocation(const char *_name)
Get location of the specified uniform.
void disable()
Resets to standard rendering pipeline.
bool isActive()
Returns if the program object is currently active.
void link()
Links the shader objects to the program.
void use()
Enables the program object for using.
Program()
Creates a new GLSL program object.
void setGeometryInputType(GLint _type)
Set Type of Geometry.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
A generic shader base class.
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.
void setSource(const StringList &source)
Upload the source of the shader.
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.
GLSL::PtrComputeShader loadComputeShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new compute shader.
void loadShaderRec(const char *filename, bool appendNewLineChar, std::map< QString, int > &includeMap, GLSL::StringList &shaderSource)
Loads the shader source and all recursive includes.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
GLSL::PtrShader loadTessControlShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation control shader.
GLSL::PtrGeometryShader loadGeometryShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
GLSL::PtrShader loadTessEvaluationShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new tessellation evaluation shader.
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.