Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
GLSL.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlGraphics/GLSL.hpp>
33 #include <vlGraphics/OpenGL.hpp>
36 #include <vlCore/VirtualFile.hpp>
37 #include <vlCore/Log.hpp>
38 #include <vlCore/Say.hpp>
39 
40 using namespace vl;
41 
42 //-----------------------------------------------------------------------------
43 // GLSLShader
44 //-----------------------------------------------------------------------------
46 {
47  VL_DEBUG_SET_OBJECT_NAME()
49  mHandle = 0;
50  mCompiled = false;
51 }
52 //-----------------------------------------------------------------------------
54 {
55  VL_DEBUG_SET_OBJECT_NAME()
56  mType = type;
57  mHandle = 0;
58  mCompiled = false;
59  setSource(source);
60 }
61 //-----------------------------------------------------------------------------
63 {
64  deleteShader();
65 }
66 //-----------------------------------------------------------------------------
67 std::string GLSLShader::getShaderSource() const
68 {
69  if (handle())
70  {
71  GLint len = 0;
72  glGetShaderiv(handle(), GL_SHADER_SOURCE_LENGTH, &len);
73  if (len)
74  {
75  std::vector<char> src;
76  src.resize(len);
77  GLint len_written = 0;
78  glGetShaderSource(handle(), len, &len_written, &src[0]);
79  return &src[0];
80  }
81  }
82 
83  return "";
84 }
85 //-----------------------------------------------------------------------------
86 String GLSLShader::processSource( const String& source ) {
87  String new_source;
88  std::vector<String> lines;
89  source.splitLines( lines );
90  for( size_t i=0; i<lines.size(); ++i ) {
91  if ( lines[i].startsWith( "#pragma VL include" ) ) {
92  String file_path = lines[i].substring( 18 /*strlen("#pragma VL include")*/ ).trim();
93  String include = processSource( vl::String::loadText( file_path ) );
94  new_source += String::printf( "#line %d 1", 0) + '\n';
95  new_source += include + '\n';
96  new_source += String::printf( "#line %d 0", i + 1) + '\n';
97  } else {
98  new_source += lines[i] + '\n';
99  }
100  }
101 
102  return new_source;
103 }
104 //-----------------------------------------------------------------------------
106  if ( ! mPath.empty() ) {
107  // we need to make a copy of mPath as it gets reset inside setSource
108  setSource( String( path() ) );
109  return compile();
110  }
111 
112  return false;
113 }
114 //-----------------------------------------------------------------------------
115 void GLSLShader::setSource( const String& source_or_path )
116 {
117  // make sure `source_or_path` is not `mPath` since we clear it at the beginning.
118  VL_CHECK( &source_or_path != &mPath );
119 
120  std::string new_src = "ERROR";
121  mSource.clear();
122  mPath.clear();
123 
124  if ( source_or_path.empty() )
125  {
126  return;
127  }
128  else
129  if ( vl::locateFile( source_or_path ) )
130  {
131  new_src = processSource( vl::String::loadText( source_or_path ) ).toStdString();
132  setPath( source_or_path );
133  setObjectName( source_or_path.toStdString().c_str() );
134  }
135  else
136  {
137  int cn = source_or_path.count('\n');
138  int cr = source_or_path.count('\r');
139  int cf = source_or_path.count('\f');
140  int line_count = vl::max( vl::max( cn, cr ), cf );
141  if(line_count == 0)
142  {
143  Log::error("GLSLShader::setSource('" + source_or_path + "') error: file not found!\n");
144  mSource = "";
145  // VL_TRAP();
146  }
147  else
148  new_src = source_or_path.toStdString();
149  }
150 
151  // update only if the source is actually different
152  if (new_src != "ERROR" && new_src != mSource)
153  {
154  mSource = new_src;
155  mCompiled = false;
156  }
157 }
158 //-----------------------------------------------------------------------------
160 {
161  VL_CHECK_OGL();
162  VL_CHECK( Has_GLSL );
163 
164  if( ! Has_GLSL ) {
165  return false;
166  }
167 
168  if (mSource.empty())
169  {
170  Log::error("GLSLShader::compile() failed: shader source is empty!\n");
171  // VL_TRAP();
172  return false;
173  }
174 
175  // compile the shader
176 
177  if ( ! mCompiled )
178  {
179  // make sure shader object exists
180 
181  createShader();
182 
183  // assign sources
184 
185  const char* source[] = { mSource.c_str() };
186  glShaderSource(handle(), 1, source, NULL);
187 
188  // compile the shader
189 
190  glCompileShader( handle() );
191 
192  if ( compileStatus() )
193  {
194  mCompiled = true;
195  #ifndef NDEBUG
196  String log = infoLog();
197  if (!log.empty())
198  Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
199  #endif
200  }
201  else
202  {
203  Log::bug( Say("\nGLSLShader::compile() failed! '%s':\n\n") << objectName().c_str() );
204  // Log::bug( Say("Source:\n%s\n\n") << mSource.c_str() );
205  Log::bug( Say("Info log:\n%s\n\n") << infoLog() );
206  // VL_TRAP()
207  }
208  }
209 
210  VL_CHECK_OGL();
211  return mCompiled;
212 }
213 //-----------------------------------------------------------------------------
215 {
216  VL_CHECK_OGL();
217  VL_CHECK( Has_GLSL )
218  if( !Has_GLSL )
219  return false;
220  VL_CHECK(handle())
221 
222  int status = 0;
223  glGetShaderiv(handle(), GL_COMPILE_STATUS, &status); VL_CHECK_OGL();
224  return status == GL_TRUE;
225 }
226 //-----------------------------------------------------------------------------
228 {
229  VL_CHECK_OGL();
230  VL_CHECK( Has_GLSL )
231  if( !Has_GLSL )
232  return "OpenGL Shading Language not supported.\n";
233  VL_CHECK(handle())
234 
235  int max_length = 0;
236  glGetShaderiv(handle(), GL_INFO_LOG_LENGTH, &max_length); VL_CHECK_OGL();
237  if (max_length != 0)
238  {
239  std::vector<char> log_buffer;
240  log_buffer.resize(max_length);
241  glGetShaderInfoLog(handle(), max_length, NULL, &log_buffer[0]); VL_CHECK_OGL();
242  VL_CHECK_OGL();
243  return &log_buffer[0];
244  }
245  else
246  return String();
247 }
248 //-----------------------------------------------------------------------------
250 {
251  VL_CHECK_OGL();
252  VL_CHECK( Has_GLSL )
253  if( !Has_GLSL )
254  return;
255  if (!handle())
256  {
257  mHandle = glCreateShader(mType);
258  mCompiled = false;
259  }
260  VL_CHECK(handle());
261  VL_CHECK_OGL();
262 }
263 //------------------------------------------------------------------------------
265 {
266  // VL_CHECK_OGL();
267  VL_CHECK( Has_GLSL )
268  if( !Has_GLSL )
269  return;
270  if (handle())
271  {
272  glDeleteShader(handle()); // VL_CHECK_OGL();
273  mHandle = 0;
274  mCompiled = false;
275  }
276 }
277 //------------------------------------------------------------------------------
278 // GLSLProgram
279 //------------------------------------------------------------------------------
281 {
282  VL_DEBUG_SET_OBJECT_NAME()
283  mScheduleLink = true;
284  mHandle = 0;
285  mProgramBinaryRetrievableHint = false;
286  mProgramSeparable = false;
287 
288  resetBindingLocations();
289 }
290 //-----------------------------------------------------------------------------
292 {
293  if (handle())
294  deleteProgram();
295 }
296 //-----------------------------------------------------------------------------
297 void GLSLProgram::resetBindingLocations()
298 {
299  // standard uniform binding
300  m_vl_ModelViewMatrix = -1;
301  m_vl_ProjectionMatrix = -1;
302  m_vl_ModelViewProjectionMatrix = -1;
303  m_vl_NormalMatrix = -1;
304 
305  // vertex attrib binding
306  m_vl_VertexPosition = -1;
307  m_vl_VertexNormal = -1;
308  m_vl_VertexColor = -1;
309  m_vl_VertexSecondaryColor = -1;
310  m_vl_VertexFogCoord = -1;
311  m_vl_VertexTexCoord0 = -1;
312  m_vl_VertexTexCoord1 = -1;
313  m_vl_VertexTexCoord2 = -1;
314  m_vl_VertexTexCoord3 = -1;
315  m_vl_VertexTexCoord4 = -1;
316  m_vl_VertexTexCoord5 = -1;
317  m_vl_VertexTexCoord6 = -1;
318  m_vl_VertexTexCoord7 = -1;
319  m_vl_VertexTexCoord8 = -1;
320  m_vl_VertexTexCoord9 = -1;
321  m_vl_VertexTexCoord10 = -1;
322 }
323 //-----------------------------------------------------------------------------
325 {
326  VL_CHECK_OGL();
327  VL_CHECK( Has_GLSL )
328  if( !Has_GLSL )
329  return;
330 
331  if ( handle() == 0 )
332  {
333  scheduleRelinking();
334  mHandle = glCreateProgram(); VL_CHECK_OGL();
335  VL_CHECK(handle())
336  }
337 }
338 //-----------------------------------------------------------------------------
340 {
341  // VL_CHECK_OGL();
342  VL_CHECK( Has_GLSL )
343  if( !Has_GLSL )
344  return;
345  if(handle())
346  {
347  glDeleteProgram(handle()); // VL_CHECK_OGL();
348  mHandle = 0;
349  }
350  resetBindingLocations();
351  scheduleRelinking();
352 }
353 //-----------------------------------------------------------------------------
355 {
356  VL_CHECK_OGL();
357  VL_CHECK( Has_GLSL );
358 
359  if( ! Has_GLSL ) {
360  return false;
361  }
362 
363  createProgram();
364 
365  scheduleRelinking();
366 
367  #if 0
368  if(std::find(mShaders.begin(), mShaders.end(), shader) != mShaders.end())
369  {
370  if ( shader->handle() )
371  glDetachShader( handle(), shader->handle() ); VL_CHECK_OGL();
372  }
373  else
374  mShaders.push_back(shader);
375  #else
376  detachShader(shader);
377  mShaders.push_back(shader);
378  #endif
379 
380  shader->createShader();
381  glAttachShader( handle(), shader->handle() ); VL_CHECK_OGL();
382 
383  return shader->compile();
384 }
385 //-----------------------------------------------------------------------------
387 {
388  VL_CHECK_OGL();
389  for(size_t i=mShaders.size(); i--;)
390  detachShader(mShaders[i].get());
391 }
392 //-----------------------------------------------------------------------------
393 // detaching a shader that has not been attached is allowed, and is a No-Op
395 {
396  VL_CHECK_OGL();
397 
398  VL_CHECK( Has_GLSL )
399  if( !Has_GLSL )
400  return false;
401 
402  if (!handle() || !shader->handle())
403  return false;
404 
405  // if it fails the shader has never been attached to any GLSL program
406  for(int i=0; i<(int)mShaders.size(); ++i)
407  {
408  if (mShaders[i] == shader)
409  {
410  if ( shader->handle() )
411  glDetachShader( handle(), shader->handle() ); VL_CHECK_OGL();
412  mShaders.erase(mShaders.begin() + i);
413  break;
414  }
415  }
416 
417  return true;
418 }
419 //-----------------------------------------------------------------------------
421 {
422  VL_CHECK_OGL();
423  VL_CHECK( Has_GLSL );
424 
425  if( ! Has_GLSL ) {
426  return;
427  }
428 
429  if ( ! handle() ) {
430  return;
431  }
432 
433  for( size_t i = 0; i < mShaders.size(); ++i )
434  {
435  if ( mShaders[i]->handle() )
436  {
437  glDetachShader( handle(), mShaders[i]->handle() ); VL_CHECK_OGL();
438  mShaders[i]->deleteShader(); VL_CHECK_OGL();
439  }
440  }
441 
442  mShaders.clear();
443  mScheduleLink = true;
444 }
445 //-----------------------------------------------------------------------------
446 bool GLSLProgram::linkProgram(bool force_relink)
447 {
448  VL_CHECK_OGL();
449  VL_CHECK( Has_GLSL )
450  if( ! Has_GLSL ) {
451  return false;
452  }
453 
454  if ( linked() && ! force_relink ) {
455  return true;
456  }
457 
458  resetBindingLocations();
459 
460  if (shaderCount() == 0) {
461  Log::bug("GLSLProgram::linkProgram() called on a GLSLProgram with no shaders! (" + String(objectName()) + ")\n");
462  VL_TRAP()
463  return false;
464  }
465 
466  createProgram();
467 
468  // pre-link operations
469  preLink();
470 
471  // link the program
472 
473  glLinkProgram(handle()); VL_CHECK_OGL();
474 
475  mScheduleLink = ! linkStatus();
476 
477  // check link error
478  if( ! linked() ) {
479  Log::bug("GLSLProgram::linkProgram() failed! (" + String(objectName()) + ")\n");
480  Log::bug( infoLog() );
481  return false;
482  }
483 
484  // post-link operations
485  postLink();
486 
487  #ifndef NDEBUG
488  String log = infoLog();
489  if ( ! log.empty() ) {
490  Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
491  }
492  #endif
493 
494  return true;
495 }
496 //-----------------------------------------------------------------------------
497 void GLSLProgram::preLink()
498 {
499  VL_CHECK_OGL();
500  // fragment shader color number binding
501 
502  if ( Has_GL_EXT_gpu_shader4 || Has_GL_Version_3_0 || Has_GL_Version_4_0 )
503  {
504  std::map<std::string, int>::iterator it = mFragDataLocation.begin();
505  while(it != mFragDataLocation.end())
506  {
507  VL_glBindFragDataLocation( handle(), it->second, it->first.c_str() ); VL_CHECK_OGL();
508  ++it;
509  }
510  }
511 
512  // OpenGL 4 program parameters
513 
514  if( Has_GL_ARB_get_program_binary )
515  {
516  VL_glProgramParameteri(handle(), GL_PROGRAM_BINARY_RETRIEVABLE_HINT, programBinaryRetrievableHint()?GL_TRUE:GL_FALSE); VL_CHECK_OGL();
517  }
518 
519  if ( Has_GL_ARB_separate_shader_objects )
520  {
521  VL_glProgramParameteri(handle(), GL_PROGRAM_SEPARABLE, programSeparable()?GL_TRUE:GL_FALSE); VL_CHECK_OGL();
522  }
523 
524  // Automatically binds the specified attributes to the desired values
525 
526  glBindAttribLocation( handle(), vl::VA_Position, "vl_VertexPosition" ); VL_CHECK_OGL();
527  glBindAttribLocation( handle(), vl::VA_Normal, "vl_VertexNormal" ); VL_CHECK_OGL();
528  glBindAttribLocation( handle(), vl::VA_Color, "vl_VertexColor" ); VL_CHECK_OGL();
529  glBindAttribLocation( handle(), vl::VA_SecondaryColor, "vl_VertexSecondaryColor" ); VL_CHECK_OGL();
530  glBindAttribLocation( handle(), vl::VA_FogCoord, "vl_VertexFogCoord" ); VL_CHECK_OGL();
531  glBindAttribLocation( handle(), vl::VA_TexCoord0, "vl_VertexTexCoord0" ); VL_CHECK_OGL();
532  glBindAttribLocation( handle(), vl::VA_TexCoord1, "vl_VertexTexCoord1" ); VL_CHECK_OGL();
533  glBindAttribLocation( handle(), vl::VA_TexCoord2, "vl_VertexTexCoord2" ); VL_CHECK_OGL();
534  glBindAttribLocation( handle(), vl::VA_TexCoord3, "vl_VertexTexCoord3" ); VL_CHECK_OGL();
535  glBindAttribLocation( handle(), vl::VA_TexCoord4, "vl_VertexTexCoord4" ); VL_CHECK_OGL();
536  glBindAttribLocation( handle(), vl::VA_TexCoord5, "vl_VertexTexCoord5" ); VL_CHECK_OGL();
537  glBindAttribLocation( handle(), vl::VA_TexCoord6, "vl_VertexTexCoord6" ); VL_CHECK_OGL();
538  glBindAttribLocation( handle(), vl::VA_TexCoord7, "vl_VertexTexCoord7" ); VL_CHECK_OGL();
539  glBindAttribLocation( handle(), vl::VA_TexCoord8, "vl_VertexTexCoord8" ); VL_CHECK_OGL();
540  glBindAttribLocation( handle(), vl::VA_TexCoord9, "vl_VertexTexCoord9" ); VL_CHECK_OGL();
541  glBindAttribLocation( handle(), vl::VA_TexCoord10, "vl_VertexTexCoord10" ); VL_CHECK_OGL();
542 }
543 //-----------------------------------------------------------------------------
544 void GLSLProgram::postLink()
545 {
546  VL_CHECK_OGL();
547 
548  // track standard vl uniforms
549 
550  m_vl_WorldMatrix = glGetUniformLocation(handle(), "vl_WorldMatrix");
551  m_vl_ModelViewMatrix = glGetUniformLocation(handle(), "vl_ModelViewMatrix");
552  m_vl_ProjectionMatrix = glGetUniformLocation(handle(), "vl_ProjectionMatrix");
553  m_vl_ModelViewProjectionMatrix = glGetUniformLocation(handle(), "vl_ModelViewProjectionMatrix");
554  m_vl_NormalMatrix = glGetUniformLocation(handle(), "vl_NormalMatrix");
555 
556  // track vertex attribute bindings
557 
558  m_vl_VertexPosition = glGetAttribLocation( handle(), "vl_VertexPosition" );
559  m_vl_VertexNormal = glGetAttribLocation( handle(), "vl_VertexNormal" );
560  m_vl_VertexColor = glGetAttribLocation( handle(), "vl_VertexColor" );
561  m_vl_VertexSecondaryColor = glGetAttribLocation( handle(), "vl_VertexSecondaryColor" );
562  m_vl_VertexFogCoord = glGetAttribLocation( handle(), "vl_VertexFogCoord" );
563  m_vl_VertexTexCoord0 = glGetAttribLocation( handle(), "vl_VertexTexCoord0" );
564  m_vl_VertexTexCoord1 = glGetAttribLocation( handle(), "vl_VertexTexCoord1" );
565  m_vl_VertexTexCoord2 = glGetAttribLocation( handle(), "vl_VertexTexCoord2" );
566  m_vl_VertexTexCoord3 = glGetAttribLocation( handle(), "vl_VertexTexCoord3" );
567  m_vl_VertexTexCoord4 = glGetAttribLocation( handle(), "vl_VertexTexCoord4" );
568  m_vl_VertexTexCoord5 = glGetAttribLocation( handle(), "vl_VertexTexCoord5" );
569  m_vl_VertexTexCoord6 = glGetAttribLocation( handle(), "vl_VertexTexCoord6" );
570  m_vl_VertexTexCoord7 = glGetAttribLocation( handle(), "vl_VertexTexCoord7" );
571  m_vl_VertexTexCoord8 = glGetAttribLocation( handle(), "vl_VertexTexCoord8" );
572  m_vl_VertexTexCoord9 = glGetAttribLocation( handle(), "vl_VertexTexCoord9" );
573  m_vl_VertexTexCoord10 = glGetAttribLocation( handle(), "vl_VertexTexCoord10" );
574 }
575 //-----------------------------------------------------------------------------
577 {
578  VL_CHECK_OGL();
579  VL_CHECK( Has_GLSL )
580  if( !Has_GLSL )
581  return false;
582 
583  VL_CHECK(handle())
584 
585  if (handle() == 0)
586  return false;
587 
588  int status = 0;
589  glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
590  return status == GL_TRUE;
591 }
592 //-----------------------------------------------------------------------------
594 {
595  VL_CHECK_OGL();
596  VL_CHECK( Has_GLSL )
597  if( ! Has_GLSL ) {
598  return "OpenGL Shading Language not supported!\n";
599  }
600 
601  VL_CHECK( handle() )
602 
603  if (handle() == 0) {
604  return "GLSLProgram::infoLog(): error! GLSL program object not yet created! (" + String(objectName()) + ")\n";
605  }
606 
607  int max_length = 0;
608  glGetProgramiv(handle(), GL_INFO_LOG_LENGTH, &max_length); VL_CHECK_OGL();
609  std::vector<char> log_buffer;
610  log_buffer.resize( max_length + 1 );
611  glGetProgramInfoLog( handle(), max_length, NULL, &log_buffer[0] ); VL_CHECK_OGL();
612  return &log_buffer[0];
613 }
614 //-----------------------------------------------------------------------------
616 {
617  VL_CHECK_OGL();
618  VL_CHECK( Has_GLSL )
619  if( !Has_GLSL )
620  return false;
621 
622  VL_CHECK(handle())
623 
624  if (handle() == 0)
625  return false;
626 
627  GLint status = 0;
628  glValidateProgram( handle() );
629  glGetProgramiv( handle(), GL_VALIDATE_STATUS, &status ); VL_CHECK_OGL();
630  return status == GL_TRUE;
631 }
632 //-----------------------------------------------------------------------------
633 void GLSLProgram::bindAttribLocation(unsigned int index, const char* name)
634 {
635  VL_CHECK_OGL();
636  VL_CHECK( Has_GLSL )
637 
638  createProgram();
639  scheduleRelinking();
640  glBindAttribLocation(handle(), index, name); VL_CHECK_OGL()
641 }
642 //-----------------------------------------------------------------------------
643 void GLSLProgram::apply(int /*index*/, const Camera*, OpenGLContext* ctx) const
644 {
645  VL_CHECK_OGL();
646  if(Has_GLSL)
647  {
648  ctx->useGLSLProgram(this);
649  }
650 }
651 //-----------------------------------------------------------------------------
652 bool GLSLProgram::applyUniformSet(const UniformSet* uniforms) const
653 {
654  uniforms = uniforms ? uniforms : getUniformSet();
655 
656  VL_CHECK_OGL();
657  VL_CHECK( Has_GLSL )
658  if( !Has_GLSL )
659  return false;
660 
661  if(!uniforms)
662  return false;
663 
664  if (!linked())
665  return false;
666 
667  if (!handle())
668  return false;
669 
670 #ifndef NDEBUG
671  int current_glsl_program = -1;
672  glGetIntegerv(GL_CURRENT_PROGRAM, &current_glsl_program); VL_CHECK_OGL();
673  VL_CHECK(current_glsl_program == (int)handle())
674 #endif
675 
676  for(size_t i=0, count=uniforms->uniforms().size(); i<count; ++i)
677  {
678  const Uniform* uniform = uniforms->uniforms()[i].get();
679 
680  #if 0
681  const UniformInfo* uinfo = activeUniformInfo(uniform->name().c_str());
682  int location = uinfo ? uinfo->Location : -1;
683 
684  #ifndef NDEBUG
685  if (location == -1)
686  {
687  std::map<std::string, ref<UniformInfo> >::const_iterator it = activeUniforms().begin();
688  Log::warning("\nActive uniforms:\n");
689  for( ; it != activeUniforms().end(); ++it )
690  Log::warning( Say("\t%s\n") << it->first.c_str() );
691 
692  // Check the following:
693  // (1) Is the uniform variable declared but not used in your GLSL program?
694  // (2) Double-check the spelling of the uniform variable name.
696  "warning:\n"
697  "GLSLProgram::applyUniformSet(): uniform '%s' not found!\n"
698  "Is the uniform variable declared but not used in your GLSL program?\n"
699  "Also double-check the spelling of the uniform variable name.\n") << uniform->name() );
700  continue;
701  }
702  #endif
703  #else
704  int location = glGetUniformLocation(handle(), uniform->name().c_str());
705  if (location == -1) {
706  continue;
707  }
708  #endif
709 
710  // finally transmits the uniform
711  // note: we don't perform delta binding per-uniform variable at the moment!
712 
713  VL_CHECK_OGL();
714  switch(uniform->mType)
715  {
716  case UT_INT: glUniform1iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
717  case UT_INT_VEC2: glUniform2iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
718  case UT_INT_VEC3: glUniform3iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
719  case UT_INT_VEC4: glUniform4iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
720 
721  case UT_UNSIGNED_INT: VL_glUniform1uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
722  case UT_UNSIGNED_INT_VEC2: VL_glUniform2uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
723  case UT_UNSIGNED_INT_VEC3: VL_glUniform3uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
724  case UT_UNSIGNED_INT_VEC4: VL_glUniform4uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
725 
726  case UT_FLOAT: glUniform1fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
727  case UT_FLOAT_VEC2: glUniform2fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
728  case UT_FLOAT_VEC3: glUniform3fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
729  case UT_FLOAT_VEC4: glUniform4fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
730 
731  case UT_FLOAT_MAT2: glUniformMatrix2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
732  case UT_FLOAT_MAT3: glUniformMatrix3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
733  case UT_FLOAT_MAT4: glUniformMatrix4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
734 
735  case UT_FLOAT_MAT2x3: glUniformMatrix2x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
736  case UT_FLOAT_MAT3x2: glUniformMatrix3x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
737  case UT_FLOAT_MAT2x4: glUniformMatrix2x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
738  case UT_FLOAT_MAT4x2: glUniformMatrix4x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
739  case UT_FLOAT_MAT3x4: glUniformMatrix3x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
740  case UT_FLOAT_MAT4x3: glUniformMatrix4x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
741 
742  case UT_DOUBLE: glUniform1dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
743  case UT_DOUBLE_VEC2: glUniform2dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
744  case UT_DOUBLE_VEC3: glUniform3dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
745  case UT_DOUBLE_VEC4: glUniform4dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
746 
747  case UT_DOUBLE_MAT2: glUniformMatrix2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
748  case UT_DOUBLE_MAT3: glUniformMatrix3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
749  case UT_DOUBLE_MAT4: glUniformMatrix4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
750 
751  case UT_DOUBLE_MAT2x3: glUniformMatrix2x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
752  case UT_DOUBLE_MAT3x2: glUniformMatrix3x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
753  case UT_DOUBLE_MAT2x4: glUniformMatrix2x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
754  case UT_DOUBLE_MAT4x2: glUniformMatrix4x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
755  case UT_DOUBLE_MAT3x4: glUniformMatrix3x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
756  case UT_DOUBLE_MAT4x3: glUniformMatrix4x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
757 
758  case UT_NONE:
759  // Probably you added a uniform to a Shader or Actor but you forgot to assign a valueto it.
760  vl::Log::bug( vl::Say("GLSLProgram::applyUniformSet(): uniform '%s' does not contain any data! Did you forget to assign a value to it?\n") << uniform->name() );
761  VL_TRAP();
762  break;
763 
764  default:
765  vl::Log::bug( vl::Say("GLSLProgram::applyUniformSet(): wrong uniform type for '%s'!\n") << uniform->name() );
766  VL_TRAP();
767  break;
768  }
769  }
770 
771  VL_CHECK_OGL();
772  return true;
773 }
774 //-----------------------------------------------------------------------------
775 void GLSLProgram::bindFragDataLocation(int color_number, const char* name)
776 {
777  scheduleRelinking();
778  mFragDataLocation[name] = color_number;
779 }
780 //-----------------------------------------------------------------------------
782 {
783  scheduleRelinking();
784  mFragDataLocation.erase(name);
785 }
786 //-----------------------------------------------------------------------------
787 int GLSLProgram::fragDataLocation(const char* name) const
788 {
789  std::map<std::string, int>::const_iterator it = mFragDataLocation.find(name);
790  if (it != mFragDataLocation.end())
791  return it->second;
792  else
793  return -1;
794 }
795 //-----------------------------------------------------------------------------
796 bool GLSLProgram::getProgramBinary(GLenum& binary_format, std::vector<unsigned char>& binary) const
797 {
798  VL_CHECK_OGL();
799  VL_CHECK(Has_GL_ARB_get_program_binary)
800  if (!Has_GL_ARB_get_program_binary)
801  return false;
802 
803  binary.clear();
804  binary_format = (GLenum)-1;
805 
806  if (handle())
807  {
808  int status = 0;
809  glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
810  if (status == GL_FALSE)
811  return false;
812  GLint length = 0;
813  glGetProgramiv(handle(), GL_PROGRAM_BINARY_LENGTH, &length); VL_CHECK_OGL();
814  if (length)
815  {
816  binary.resize(length);
817  VL_glGetProgramBinary(handle(), length, NULL, &binary_format, &binary[0]); VL_CHECK_OGL();
818  }
819  return true;
820  }
821  else
822  {
823  VL_TRAP();
824  return false;
825  }
826 }
827 //-----------------------------------------------------------------------------
828 bool GLSLProgram::programBinary(GLenum binary_format, const void* binary, int length)
829 {
830  VL_CHECK_OGL();
831  VL_CHECK(Has_GL_ARB_get_program_binary)
832  if (!Has_GL_ARB_get_program_binary)
833  return false;
834 
835  createProgram();
836 
837  if (handle())
838  {
839  // pre-link operations
840  preLink();
841 
842  // load glsl program and link
843  VL_glProgramBinary(handle(), binary_format, binary, length); VL_CHECK_OGL();
844  mScheduleLink = !linkStatus();
845 
846  // log error
847  if(linked())
848  {
849  // post-link operations
850  postLink();
851 
852  #ifndef NDEBUG
853  String log = infoLog();
854  if (!log.empty())
855  Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
856  #endif
857  }
858  else
859  {
860  Log::bug("GLSLProgram::programBinary() failed! (" + String(objectName()) + ")\n");
861  Log::bug( Say("Info log:\n%s\n") << infoLog() );
862  VL_TRAP();
863  }
864 
865  return linked();
866  }
867  else
868  {
869  VL_TRAP();
870  return false;
871  }
872 }
873 //-----------------------------------------------------------------------------
875  bool ok = true;
876  for( size_t i = 0; i < mShaders.size(); ++i ) {
877  ok &= mShaders[i]->reload();
878  }
879  return ok && linkProgram( true );
880 }
881 //-----------------------------------------------------------------------------
bool reload()
Reloads the shader source and recompiles it. Returns true on success.
Definition: GLSL.cpp:105
const float * floatData() const
Definition: Uniform.hpp:327
Wraps an OpenGL Shading Language uniform to be associated to a GLSLProgram (see vl::GLSLProgram docum...
Definition: Uniform.hpp:59
A shader that is intended to run on the programmable vertex processor.
bool getProgramBinary(GLenum &binary_format, std::vector< unsigned char > &binary) const
glGetProgramBinary wrapper: returns a binary representation of a program object&#39;s compiled and linked...
Definition: GLSL.cpp:796
A simple String formatting class.
Definition: Say.hpp:124
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
static void warning(const String &message)
Use this function to provide information about situations that might lead to errors or loss of data...
Definition: Log.cpp:155
bool detachShader(GLSLShader *shader)
Detaches a GLSLShader from the GLSLShader (note: it does NOT schedule a relink of the program)...
Definition: GLSL.cpp:394
EShaderType mType
Definition: GLSL.hpp:107
unsigned int handle() const
The handle of this OpenGL shader object as returned by glCreateShader()
Definition: GLSL.hpp:104
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
void detachAllShaders()
Removes all the previously linked shaders and schedules a relinking.
Definition: GLSL.cpp:386
Represents an OpenGL context, possibly a widget or a pbuffer, which can also respond to keyboard...
unsigned int mHandle
Definition: GLSL.hpp:110
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void bindAttribLocation(unsigned int index, const char *name)
Equivalent to glBindAttribLocation(handle(), index, name.c_str()) with the difference that this funct...
Definition: GLSL.cpp:633
void splitLines(std::vector< String > &lines) const
Splits a String into a set of Strings each of which contains a line.
Definition: String.cpp:420
bool validateProgram() const
Returns true if the validation of this GLSL program is succesful, see also http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml for more information.
Definition: GLSL.cpp:615
int count(wchar_t ch, int start=0) const
Returns the number of occurrences of the given character after position &#39;start&#39;.
Definition: String.cpp:666
bool Has_GL_Version_4_0
Definition: OpenGL.cpp:60
const std::string & source() const
Returns the sources for this shader.
Definition: GLSL.hpp:72
bool applyUniformSet(const UniformSet *uniforms=NULL) const
Applies a set of uniforms to the currently bound GLSL program.
Definition: GLSL.cpp:652
String mPath
Definition: GLSL.hpp:109
const double * doubleData() const
Definition: Uniform.hpp:326
const std::vector< ref< Uniform > > & uniforms() const
Definition: UniformSet.hpp:68
bool compileStatus() const
Returns true if the shader has been succesfully compiled.
Definition: GLSL.cpp:214
bool Has_GL_Version_3_0
Definition: OpenGL.cpp:56
bool reload()
Reloads all the shaders source and recompiles them and relinks. Returns true on success.
Definition: GLSL.cpp:874
~GLSLProgram()
Destructor. Calls deleteProgram().
Definition: GLSL.cpp:291
T log(T a)
Definition: glsl_math.hpp:486
Visualization Library main namespace.
bool linkStatus() const
Definition: GLSL.cpp:576
bool Has_GLSL
Definition: OpenGL.cpp:73
const unsigned int * uintData() const
Definition: Uniform.hpp:329
EUniformType mType
Definition: Uniform.hpp:331
void discardAllShaders()
Detaches all the shaders and deletes them (note that the GLSL Program remains still valid)...
Definition: GLSL.cpp:420
int count() const
Definition: Uniform.hpp:261
bool linkProgram(bool force_relink=false)
Links the GLSLProgram calling glLinkProgram(handle()) only if the program needs to be linked...
Definition: GLSL.cpp:446
void setPath(const String &path)
The path from which the shader was loaded.
Definition: GLSL.hpp:75
static void bug(const String &message)
Use this function to provide information about programming errors: wrong parameter initialization...
Definition: Log.cpp:175
#define VL_TRAP()
Definition: checks.hpp:70
void useGLSLProgram(const GLSLProgram *glsl)
Activates the given GLSLProgram or unbinds the current one if glsl is NULL.
int fragDataLocation(const char *name) const
Definition: GLSL.cpp:787
For internal use only.
Definition: GLSL.hpp:50
const std::string & name() const
Returns the name of the uniform variable.
Definition: Uniform.hpp:86
float max(float a, float b)
Definition: Vector2.hpp:311
const int * intData() const
Definition: Uniform.hpp:328
void setSource(const String &source_or_path)
Sets the sources for this shader and schedules a recompilation for it. If the string passed is a file...
Definition: GLSL.cpp:115
void createProgram()
Calls glCreateProgram() in order to acquire a GLSL program handle, see also http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml for more information.
Definition: GLSL.cpp:324
void createShader()
Creates the shader using the OpenGL function glCreateShader(), see also http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml for more information.
Definition: GLSL.cpp:249
bool empty() const
Returns true if length() == 0.
Definition: String.hpp:136
void deleteShader()
Deletes the shader using the OpenGL function glDeleteShader(), see also http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml for more information.
Definition: GLSL.cpp:264
bool mCompiled
Definition: GLSL.hpp:111
static String loadText(const String &path, EStringEncoding encoding=VL_PLATFORM_DEFAULT_ENCODING)
Loads a String from the specified path.
Definition: String.cpp:86
bool programBinary(GLenum binary_format, const std::vector< unsigned char > &binary)
glProgramBinary wrapper: loads a program object with a program binary, see also http://www.opengl.org/sdk/docs/man4/xhtml/glProgramBinary.xml
Definition: GLSL.hpp:387
String infoLog() const
Returns the info log of this GLSL program using the OpenGL function glGetProgramInfoLog(), see also http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml for more information.
Definition: GLSL.cpp:593
#define NULL
Definition: OpenGLDefs.hpp:81
void unbindFragDataLocation(const char *name)
Definition: GLSL.cpp:781
#define VL_CHECK_OGL()
Definition: OpenGL.hpp:156
const std::string & objectName() const
The name of the object, by default set to the object&#39;s class name.
Definition: Object.hpp:217
VLCORE_EXPORT ref< VirtualFile > locateFile(const String &path)
Utility function, equivalent to vl::defFileSystem()->locateFile(path)
Definition: VirtualFile.cpp:41
bool compile()
Compiles the shader, see also http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml for more information.
Definition: GLSL.cpp:159
EShaderType type() const
Definition: GLSL.hpp:66
std::string mSource
Definition: GLSL.hpp:108
const String & path() const
The path from which the shader was loaded.
Definition: GLSL.hpp:78
void bindFragDataLocation(int color_number, const char *name)
Definition: GLSL.cpp:775
GLSLProgram()
Constructor.
Definition: GLSL.cpp:280
A set of Uniform objects managed by a Shader.
Definition: UniformSet.hpp:50
std::string getShaderSource() const
Retrieves the shader source using glGetShaderSource()
Definition: GLSL.cpp:67
T length(T v)
Definition: glsl_math.hpp:1084
Represents a virtual camera defining, among other things, the point of view from which scenes can be ...
Definition: Camera.hpp:50
static String printf(const char *fmt,...)
Returns a formatted string using the legacy printf syntax. The resulting string can be maximum 1024 +...
Definition: String.cpp:1510
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
bool attachShader(GLSLShader *shader)
Attaches the GLSLShader to this GLSLProgram.
Definition: GLSL.cpp:354
void deleteProgram()
Deletes the GLSL program calling glDeleteProgram(handle()), see also http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml for more information.
Definition: GLSL.cpp:339
#define VL_CHECK(expr)
Definition: checks.hpp:73
String & clear()
Clears the string.
Definition: String.hpp:142
String infoLog() const
Returns a String object containing this shader&#39;s info log as returned by glGetShaderInfoLog(), see also http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml for more information.
Definition: GLSL.cpp:227
void apply(int index, const Camera *, OpenGLContext *ctx) const
Calls OpenGLContext::useGLSLProgram()
Definition: GLSL.cpp:643