Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/GLSL.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2011, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlGraphics/GLSL.hpp>
00033 #include <vlGraphics/OpenGL.hpp>
00034 #include <vlCore/GlobalSettings.hpp>
00035 #include <vlCore/VirtualFile.hpp>
00036 #include <vlCore/Log.hpp>
00037 #include <vlCore/Say.hpp>
00038 
00039 using namespace vl;
00040 
00041 //-----------------------------------------------------------------------------
00042 // GLSLShader
00043 //-----------------------------------------------------------------------------
00044 GLSLShader::GLSLShader()
00045 {
00046   VL_DEBUG_SET_OBJECT_NAME()
00047   mType = ST_VERTEX_SHADER;
00048   mHandle = 0;
00049   mCompiled = false;
00050 }
00051 //-----------------------------------------------------------------------------
00052 GLSLShader::GLSLShader(EShaderType type, const String& source)
00053 {
00054   VL_DEBUG_SET_OBJECT_NAME()
00055   mType = type;
00056   mHandle = 0;
00057   mCompiled = false;
00058   setSource(source);
00059 }
00060 //-----------------------------------------------------------------------------
00061 GLSLShader::~GLSLShader()
00062 {
00063   deleteShader();
00064 }
00065 //-----------------------------------------------------------------------------
00066 std::string GLSLShader::getShaderSource() const
00067 {
00068   if (handle())
00069   {
00070     GLint len = 0;
00071     glGetShaderiv(handle(), GL_SHADER_SOURCE_LENGTH, &len);
00072     if (len)
00073     {
00074       std::vector<char> src;
00075       src.resize(len);
00076       GLint len_written = 0;
00077       glGetShaderSource(handle(), len, &len_written, &src[0]);
00078       return &src[0];
00079     }
00080   }
00081 
00082   return "";
00083 }
00084 //-----------------------------------------------------------------------------
00085 void GLSLShader::setSource( const String& source_or_path )
00086 {
00087   std::string new_src = "ERROR";
00088 
00089   if (source_or_path.empty())
00090   {
00091     mSource.clear();
00092     return;
00093   }
00094   else
00095   if (vl::locateFile(source_or_path))
00096   {
00097     new_src = vl::String::loadText(source_or_path).toStdString();
00098     setObjectName( source_or_path.toStdString().c_str() );
00099     setPath( source_or_path.toStdString().c_str() );
00100   }
00101   else
00102   {
00103     int cn = source_or_path.count('\n');
00104     int cr = source_or_path.count('\r');
00105     int cf = source_or_path.count('\f');
00106     int line_count = vl::max( vl::max( cn, cr ), cf );
00107     if(line_count == 0)
00108     {
00109       Log::error("GLSLShader::setSource('" + source_or_path + "') error: file not found!\n");
00110       mSource = "";
00111       // VL_TRAP();
00112     }
00113     else
00114       new_src = source_or_path.toStdString();
00115   }
00116 
00117   // update only if the source is actually different
00118   if (new_src != "ERROR" && new_src != mSource)
00119   {
00120     mSource = new_src;
00121     mCompiled = false;
00122   }
00123 }
00124 //-----------------------------------------------------------------------------
00125 bool GLSLShader::compile()
00126 {
00127   VL_CHECK_OGL();
00128   VL_CHECK( Has_GLSL )
00129   if( !Has_GLSL )
00130     return false;
00131 
00132   if (mSource.empty())
00133   {
00134     Log::error("GLSLShader::compile() failed: shader source is empty!\n");
00135     VL_TRAP();
00136     return false;
00137   }
00138 
00139   if (!mCompiled)
00140   {
00141     // compile the shader
00142 
00143     if (!handle())
00144     {
00145       // createShader();
00146       mHandle = glCreateShader(mType);
00147     }
00148 
00149     // assign sources
00150 
00151     const char* source[] = { mSource.c_str() };
00152     glShaderSource(handle(), 1, source, NULL);
00153 
00154     // compile the shader
00155 
00156     glCompileShader(handle());
00157 
00158     if ( compileStatus() )
00159     {
00160       mCompiled = true;
00161       #ifndef NDEBUG
00162         String log = infoLog();
00163         if (!log.empty())
00164           Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
00165       #endif
00166     }
00167     else
00168     {
00169       Log::bug( Say("\nGLSLShader::compile() failed! '%s':\n\n") << objectName().c_str() );
00170       // Log::bug( Say("Source:\n%s\n\n") << mSource.c_str() );
00171       Log::bug( Say("Info log:\n%s\n\n") << infoLog() );
00172       // VL_TRAP()
00173     }
00174   }
00175 
00176   VL_CHECK_OGL();
00177   return mCompiled;
00178 }
00179 //-----------------------------------------------------------------------------
00180 bool GLSLShader::compileStatus() const
00181 {
00182   VL_CHECK_OGL();
00183   VL_CHECK( Has_GLSL )
00184   if( !Has_GLSL )
00185     return false;
00186   VL_CHECK(handle())
00187 
00188   int status = 0;
00189   glGetShaderiv(handle(), GL_COMPILE_STATUS, &status); VL_CHECK_OGL();
00190   return status == GL_TRUE;
00191 }
00192 //-----------------------------------------------------------------------------
00193 String GLSLShader::infoLog() const
00194 {
00195   VL_CHECK_OGL();
00196   VL_CHECK( Has_GLSL )
00197   if( !Has_GLSL )
00198     return "OpenGL Shading Language not supported.\n";
00199   VL_CHECK(handle())
00200 
00201   int max_length = 0;
00202   glGetShaderiv(handle(), GL_INFO_LOG_LENGTH, &max_length); VL_CHECK_OGL();
00203   if (max_length != 0)
00204   {
00205     std::vector<char> log_buffer;
00206     log_buffer.resize(max_length);
00207     glGetShaderInfoLog(handle(), max_length, NULL, &log_buffer[0]); VL_CHECK_OGL();
00208     VL_CHECK_OGL();
00209     return &log_buffer[0];
00210   }
00211   else
00212     return String();
00213 }
00214 //-----------------------------------------------------------------------------
00215 void GLSLShader::createShader()
00216 {
00217   VL_CHECK_OGL();
00218   VL_CHECK( Has_GLSL )
00219   if( !Has_GLSL )
00220     return;
00221   if (!handle())
00222   {
00223     mHandle = glCreateShader(mType);
00224     mCompiled = false;
00225   }
00226   VL_CHECK(handle());
00227   VL_CHECK_OGL();
00228 }
00229 //------------------------------------------------------------------------------
00230 void GLSLShader::deleteShader()
00231 {
00232   // VL_CHECK_OGL();
00233   VL_CHECK( Has_GLSL )
00234   if( !Has_GLSL )
00235     return;
00236   if (handle())
00237   {
00238     glDeleteShader(handle()); // VL_CHECK_OGL();
00239     mHandle = 0;
00240     mCompiled = false;
00241   }
00242 }
00243 //------------------------------------------------------------------------------
00244 // GLSLProgram
00245 //------------------------------------------------------------------------------
00246 GLSLProgram::GLSLProgram()
00247 {
00248   VL_DEBUG_SET_OBJECT_NAME()
00249   mScheduleLink = true;
00250   mHandle = 0;
00251   mGeometryVerticesOut = 0;
00252   mGeometryInputType   = GIT_TRIANGLES;
00253   mGeometryOutputType  = GOT_TRIANGLE_STRIP;
00254   mProgramBinaryRetrievableHint = false;
00255   mProgramSeparable = false;
00256   m_vl_ModelViewMatrix = -1;
00257   m_vl_ProjectionMatrix = -1;
00258   m_vl_ModelViewProjectionMatrix = -1;
00259   m_vl_NormalMatrix = -1;
00260 }
00261 //-----------------------------------------------------------------------------
00262 GLSLProgram::~GLSLProgram()
00263 {
00264   if (handle())
00265     deleteProgram();
00266 }
00267 //-----------------------------------------------------------------------------
00268 GLSLProgram& GLSLProgram::operator=(const GLSLProgram& other)
00269 {
00270   super::operator=(other);
00271 
00272   // unsigned int mHandle;
00273   // bool mScheduleLink;
00274   deleteProgram();
00275 
00276   // attach shader
00277   mShaders.clear();
00278   for(size_t i=0; i<other.mShaders.size(); ++i)
00279     attachShader( other.mShaders[i].get_writable() );
00280 
00281   mFragDataLocation = other.mFragDataLocation;
00282   mActiveUniforms.clear();
00283   mActiveAttribs.clear();
00284   mAutoAttribLocation = other.mAutoAttribLocation;
00285   if (other.mUniformSet)
00286   {
00287     if (mUniformSet.get() == NULL)
00288       mUniformSet = new UniformSet;
00289     *mUniformSet = *other.mUniformSet;
00290   }
00291   else
00292     mUniformSet = NULL;
00293 
00294   // glProgramParameter
00295   mGeometryVerticesOut = other.mGeometryVerticesOut;
00296   mGeometryInputType = other.mGeometryInputType;
00297   mGeometryOutputType = other.mGeometryOutputType;
00298   mProgramBinaryRetrievableHint = other.mProgramBinaryRetrievableHint;
00299   mProgramSeparable = other.mProgramSeparable;
00300 
00301   m_vl_ModelViewMatrix = -1;
00302   m_vl_ProjectionMatrix = -1;
00303   m_vl_ModelViewProjectionMatrix = -1;
00304   m_vl_NormalMatrix = -1;
00305 
00306   return *this;
00307 }
00308 void GLSLProgram::createProgram()
00309 {
00310   VL_CHECK_OGL();
00311   VL_CHECK( Has_GLSL )
00312   if( !Has_GLSL )
00313     return;
00314 
00315   if (handle() == 0)
00316   {
00317     scheduleRelinking();
00318     mHandle = glCreateProgram(); VL_CHECK_OGL();
00319     VL_CHECK(handle())
00320   }
00321 }
00322 //-----------------------------------------------------------------------------
00323 void GLSLProgram::deleteProgram()
00324 {
00325   // VL_CHECK_OGL();
00326   VL_CHECK( Has_GLSL )
00327   if( !Has_GLSL )
00328     return;
00329   if(handle())
00330   {
00331     glDeleteProgram(handle()); // VL_CHECK_OGL();
00332     mHandle = 0;
00333   }
00334   scheduleRelinking();
00335 }
00336 //-----------------------------------------------------------------------------
00337 bool GLSLProgram::attachShader(GLSLShader* shader)
00338 {
00339   VL_CHECK_OGL();
00340   VL_CHECK( Has_GLSL )
00341   if( !Has_GLSL )
00342     return false;
00343 
00344   scheduleRelinking();
00345 
00346   #if 0
00347     if(std::find(mShaders.begin(), mShaders.end(), shader) != mShaders.end())
00348     {
00349       if ( shader->handle() )
00350         glDetachShader( handle(), shader->handle() ); VL_CHECK_OGL();
00351     }
00352     else
00353       mShaders.push_back(shader);
00354   #else
00355     detachShader(shader);
00356     mShaders.push_back(shader);
00357   #endif
00358 
00359   if ( shader->compile() )
00360   {
00361     createProgram();
00362     glAttachShader( handle(), shader->handle() ); VL_CHECK_OGL();
00363     return true;
00364   }
00365 
00366   VL_CHECK_OGL();
00367   return false;
00368 
00369 }
00370 //-----------------------------------------------------------------------------
00371 void GLSLProgram::detachAllShaders()
00372 {
00373   VL_CHECK_OGL();
00374   for(size_t i=mShaders.size(); i--;)
00375     detachShader(mShaders[i].get());
00376 }
00377 //-----------------------------------------------------------------------------
00378 // detaching a shader that has not been attached is allowed, and is a No-Op
00379 bool GLSLProgram::detachShader(GLSLShader* shader)
00380 {
00381   VL_CHECK_OGL();
00382 
00383   VL_CHECK( Has_GLSL )
00384   if( !Has_GLSL )
00385     return false;
00386 
00387   if (!handle() || !shader->handle())
00388     return false;
00389 
00390   // if it fails the shader has never been attached to any GLSL program
00391   for(int i=0; i<(int)mShaders.size(); ++i)
00392   {
00393     if (mShaders[i] == shader)
00394     {
00395       if ( shader->handle() )
00396         glDetachShader( handle(), shader->handle() ); VL_CHECK_OGL();
00397       mShaders.erase(mShaders.begin() + i);
00398       break;
00399     }
00400   }
00401 
00402   return true;
00403 }
00404 //-----------------------------------------------------------------------------
00405 void GLSLProgram::discardAllShaders()
00406 {
00407   VL_CHECK_OGL();
00408   VL_CHECK( Has_GLSL )
00409   if( !Has_GLSL )
00410     return;
00411 
00412   if (!handle())
00413     return;
00414 
00415   for(int i=0; i<(int)mShaders.size(); ++i)
00416   {
00417     if (mShaders[i]->handle())
00418     {
00419       glDetachShader( handle(), mShaders[i]->handle() ); VL_CHECK_OGL();
00420       mShaders[i]->deleteShader();
00421     }
00422   }
00423 
00424   mShaders.clear();
00425 }
00426 //-----------------------------------------------------------------------------
00427 bool GLSLProgram::linkProgram(bool force_relink)
00428 {
00429   VL_CHECK_OGL();
00430   VL_CHECK( Has_GLSL )
00431   if( !Has_GLSL )
00432     return false;
00433 
00434   if (!linked() || force_relink)
00435   {
00436     if (shaderCount() == 0)
00437     {
00438       Log::bug("GLSLProgram::linkProgram() called on a GLSLProgram with no shaders! (" + String(objectName().c_str()) + ")\n");
00439       VL_TRAP()
00440       return false;
00441     }
00442 
00443     createProgram();
00444 
00445     // pre-link operations
00446     preLink();
00447 
00448     // link the program
00449 
00450     glLinkProgram(handle()); VL_CHECK_OGL();
00451     mScheduleLink = !linkStatus();
00452 
00453     // check link error
00454     if(linked())
00455     {
00456       // post-link operations
00457       postLink();
00458 
00459       #ifndef NDEBUG
00460         String log = infoLog();
00461         if (!log.empty())
00462           Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
00463       #endif
00464     }
00465     else
00466     {
00467       Log::bug("GLSLProgram::linkProgram() failed! (" + String(objectName().c_str()) + ")\n");
00468       Log::bug( Say("Info log:\n%s\n") << infoLog() );
00469       VL_TRAP()
00470       return false;
00471     }
00472   }
00473 
00474   return true;
00475 }
00476 //-----------------------------------------------------------------------------
00477 void GLSLProgram::preLink()
00478 {
00479   VL_CHECK_OGL();
00480   // fragment shader color number binding
00481 
00482   if (Has_GL_EXT_gpu_shader4||Has_GL_Version_3_0||Has_GL_Version_4_0)
00483   {
00484     std::map<std::string, int>::iterator it = mFragDataLocation.begin();
00485     while(it != mFragDataLocation.end())
00486     {
00487       VL_glBindFragDataLocation( handle(), it->second, it->first.c_str() ); VL_CHECK_OGL();
00488       ++it;
00489     }
00490   }
00491 
00492   // Note that OpenGL 3.2 and 4 do not use glProgramParameter to define the layout of the
00493   // input/output geometry but something like this in the geometry shader:
00494   //
00495   // layout(triangles) in;
00496   // layout(triangle_strip, max_vertices = 3) out;
00497 
00498   if (Has_Geometry_Shader && geometryVerticesOut() )
00499   {
00500     // if there is at least one geometry shader applies the geometry shader parameters
00501     for(unsigned i=0; i<mShaders.size(); ++i)
00502     {
00503       if (mShaders[i]->type() == ST_GEOMETRY_SHADER)
00504       {
00505         VL_glProgramParameteri(handle(), GL_GEOMETRY_INPUT_TYPE_EXT,   geometryInputType()); VL_CHECK_OGL();
00506         VL_glProgramParameteri(handle(), GL_GEOMETRY_OUTPUT_TYPE_EXT,  geometryOutputType()); VL_CHECK_OGL();
00507         VL_glProgramParameteri(handle(), GL_GEOMETRY_VERTICES_OUT_EXT, geometryVerticesOut()); VL_CHECK_OGL();
00508         break;
00509       }
00510     }
00511   }
00512 
00513   // OpenGL 4 program parameters
00514 
00515   if(Has_GL_ARB_get_program_binary)
00516   {
00517     VL_glProgramParameteri(handle(), GL_PROGRAM_BINARY_RETRIEVABLE_HINT, programBinaryRetrievableHint()?GL_TRUE:GL_FALSE); VL_CHECK_OGL();
00518   }
00519 
00520   if (Has_GL_ARB_separate_shader_objects)
00521   {
00522     VL_glProgramParameteri(handle(), GL_PROGRAM_SEPARABLE, programSeparable()?GL_TRUE:GL_FALSE); VL_CHECK_OGL();
00523   }
00524 
00525   // automatically binds the specified attributes to the desired values
00526 
00527   for( std::map<std::string, int>::iterator it = mAutoAttribLocation.begin(); it != mAutoAttribLocation.end(); ++it)
00528   {
00529     glBindAttribLocation(handle(),it->second,it->first.c_str()); VL_CHECK_OGL();
00530   }
00531 }
00532 //-----------------------------------------------------------------------------
00533 void GLSLProgram::postLink()
00534 {
00535   VL_CHECK_OGL();
00536 
00537   // populate uniform binding map
00538 
00539   mActiveUniforms.clear();
00540 
00541   int uniform_len = 0;
00542   glGetProgramiv(handle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_len); VL_CHECK_OGL();
00543   if (uniform_len)
00544   {
00545     std::vector<char> tmp_buf;
00546     tmp_buf.resize(uniform_len+1); // +1: just for safety in case of buggy drivers.
00547     char* name = &tmp_buf[0];
00548 
00549     int uniform_count = 0;
00550     glGetProgramiv(handle(), GL_ACTIVE_UNIFORMS, &uniform_count); VL_CHECK_OGL();
00551     for(int i=0; i<uniform_count; ++i)
00552     {
00553       GLenum type;
00554       int size;
00555       std::fill(tmp_buf.begin(), tmp_buf.end(), 0); // reset string to all zeros: just for safety in case of buggy drivers.
00556       int length = 0;
00557       glGetActiveUniform(handle(), i, (GLsizei)tmp_buf.size(), &length, &size, &type, name); VL_CHECK_OGL();
00558 
00559       // workaround for NVIDIA drivers bug: remove the trailing [] after the uniform name.
00560       // See also: http://www.visualizationlibrary.org/forum/viewtopic.php?f=3&t=307
00561       if (name[length-1] == ']')
00562       {
00563         char* bracket = strrchr(name, '[');
00564         if (bracket)
00565         {
00566           Log::warning( Say("Driver bug: glGetActiveUniform() returned a uniform name '%s' containing square brackets!\n"
00567                           "VL will continue trimming them from the uniform's name.\n"
00568                           "Please update your drivers and report the issue to your driver vendor.\n"
00569                           "Driver info: vendor: %s, renderer: %s, OpenGL version: %s\n"
00570                           ) << name << glGetString(GL_VENDOR) << glGetString(GL_RENDERER) << glGetString(GL_VERSION) );
00571           *bracket = 0;
00572         }
00573       }
00574 
00575       ref<UniformInfo> uinfo = new UniformInfo(name, (EUniformType)type, size, glGetUniformLocation(handle(), name));
00576       mActiveUniforms[name] = uinfo;
00577     }
00578   }
00579 
00580   // populate attribute binding map
00581 
00582   mActiveAttribs.clear();
00583 
00584   int attrib_len = 0;
00585   glGetProgramiv(handle(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_len); VL_CHECK_OGL();
00586   if (attrib_len)
00587   {
00588     std::vector<char> tmp_buf;
00589     tmp_buf.resize(attrib_len);
00590     char* name = &tmp_buf[0];
00591 
00592     int attrib_count = 0;
00593     glGetProgramiv(handle(), GL_ACTIVE_ATTRIBUTES, &attrib_count); VL_CHECK_OGL();
00594     for(int i=0; i<attrib_count; ++i)
00595     {
00596       GLenum type;
00597       int size;
00598       glGetActiveAttrib(handle(), i, attrib_len, NULL, &size, &type, name); VL_CHECK_OGL();
00599       ref<AttribInfo> uinfo = new AttribInfo(name, (EAttributeType)type, size, glGetAttribLocation(handle(), name));
00600       mActiveAttribs[name] = uinfo;
00601     }
00602   }
00603 
00604   // check for the predefined glsl uniform variables
00605 
00606   m_vl_ModelViewMatrix           = glGetUniformLocation(handle(), "vl_ModelViewMatrix");
00607   m_vl_ProjectionMatrix          = glGetUniformLocation(handle(), "vl_ProjectionMatrix");
00608   m_vl_ModelViewProjectionMatrix = glGetUniformLocation(handle(), "vl_ModelViewProjectionMatrix");
00609   m_vl_NormalMatrix              = glGetUniformLocation(handle(), "vl_NormalMatrix");
00610 }
00611 //-----------------------------------------------------------------------------
00612 bool GLSLProgram::linkStatus() const
00613 {
00614   VL_CHECK_OGL();
00615   VL_CHECK( Has_GLSL )
00616   if( !Has_GLSL )
00617     return false;
00618 
00619   VL_CHECK(handle())
00620 
00621   if (handle() == 0)
00622     return false;
00623 
00624   int status = 0;
00625   glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
00626   return status == GL_TRUE;
00627 }
00628 //-----------------------------------------------------------------------------
00629 String GLSLProgram::infoLog() const
00630 {
00631   VL_CHECK_OGL();
00632   VL_CHECK( Has_GLSL )
00633   if( !Has_GLSL )
00634     return "OpenGL Shading Language not supported!\n";
00635 
00636   VL_CHECK(handle())
00637 
00638   if (handle() == 0)
00639     return "GLSLProgram::infoLog(): error! GLSL program object not yet created! (" + String(objectName().c_str()) + ")\n";
00640 
00641   int max_length = 0;
00642   glGetProgramiv(handle(), GL_INFO_LOG_LENGTH, &max_length); VL_CHECK_OGL();
00643   std::vector<char> log_buffer;
00644   log_buffer.resize(max_length+1);
00645   glGetProgramInfoLog(handle(), max_length, NULL, &log_buffer[0]); VL_CHECK_OGL();
00646   return &log_buffer[0];
00647 }
00648 //-----------------------------------------------------------------------------
00649 bool GLSLProgram::validateProgram() const
00650 {
00651   VL_CHECK_OGL();
00652   VL_CHECK( Has_GLSL )
00653   if( !Has_GLSL )
00654     return false;
00655 
00656   VL_CHECK(handle())
00657 
00658   if (handle() == 0)
00659     return false;
00660 
00661   glValidateProgram(handle());
00662   int status = 0;
00663   glGetProgramiv(handle(), GL_VALIDATE_STATUS, &status); VL_CHECK_OGL();
00664   return status == GL_TRUE;
00665 }
00666 //-----------------------------------------------------------------------------
00667 void GLSLProgram::bindAttribLocation(unsigned int index, const char* name)
00668 {
00669   VL_CHECK_OGL();
00670   VL_CHECK( Has_GLSL )
00671 
00672   createProgram();
00673   scheduleRelinking();
00674   glBindAttribLocation(handle(), index, name); VL_CHECK_OGL()
00675 }
00676 //-----------------------------------------------------------------------------
00677 bool GLSLProgram::useProgram() const
00678 {
00679   VL_CHECK_OGL()
00680   VL_CHECK( Has_GLSL )
00681   if( !Has_GLSL )
00682     return false;
00683 
00684   if (!handle())
00685   {
00686     Log::bug("GLSLProgram::useProgram() failed! GLSL program handle is null! (" + String(objectName().c_str()) + ")\n");
00687     VL_TRAP()
00688     return false;
00689   }
00690 
00691   if (!linked())
00692   {
00693     Log::bug("GLSLProgram::useProgram() failed! GLSL program not linked! (" + String(objectName().c_str()) + ")\n");
00694     VL_TRAP()
00695     return false;
00696   }
00697 
00698 // The program validation should be done only after all the uniforms have been applied, just before rendering an object.
00699 //#ifndef NDEBUG
00700 //  if (!validateProgram())
00701 //  {
00702 //    Log::bug("GLSLProgram::useProgram() failed validation! (" + String(objectName().c_str()) + ")\n");
00703 //    Log::bug( Say("Info log:\n%s\n") << infoLog() );
00704 //    VL_TRAP();
00705 //    return false;
00706 //  }
00707 //#endif
00708 
00709   // bind the GLSL program
00710   glUseProgram(handle()); VL_CHECK_OGL()
00711 
00712   return true;
00713 }
00714 //-----------------------------------------------------------------------------
00715 void GLSLProgram::apply(int /*index*/, const Camera*, OpenGLContext*) const
00716 {
00717   VL_CHECK_OGL();
00718   if(Has_GLSL)
00719   {
00720     if ( handle() )
00721       useProgram();
00722     else
00723       glUseProgram(0); VL_CHECK_OGL();
00724   }
00725 }
00726 //-----------------------------------------------------------------------------
00727 bool GLSLProgram::applyUniformSet(const UniformSet* uniforms) const
00728 {
00729   VL_CHECK_OGL();
00730   VL_CHECK( Has_GLSL )
00731   if( !Has_GLSL )
00732     return false;
00733 
00734   if(!uniforms)
00735     return false;
00736 
00737   if (!linked())
00738     return false;
00739 
00740   if (!handle())
00741     return false;
00742 
00743 #ifndef NDEBUG
00744   int current_glsl_program = -1;
00745   glGetIntegerv(GL_CURRENT_PROGRAM, &current_glsl_program); VL_CHECK_OGL();
00746   VL_CHECK(current_glsl_program == (int)handle())
00747 #endif
00748 
00749   for(size_t i=0, count=uniforms->uniforms().size(); i<count; ++i)
00750   {
00751     const Uniform* uniform = uniforms->uniforms()[i].get();
00752 
00753     #if 1
00754       const UniformInfo* uinfo = activeUniformInfo(uniform->name().c_str());
00755       int location = uinfo ? uinfo->Location : -1;
00756 
00757       #ifndef NDEBUG
00758       if (location == -1)
00759       {
00760         std::map<std::string, ref<UniformInfo> >::const_iterator it = activeUniforms().begin();
00761         Log::warning("\nActive uniforms:\n");
00762         for( ; it != activeUniforms().end(); ++it )
00763           Log::warning( Say("\t%s\n") << it->first.c_str() );
00764       }
00765       #endif
00766 
00767     #else
00768       int location = glGetUniformLocation(handle(), uniform->name().c_str());
00769     #endif
00770 
00771     if (location == -1)
00772     {
00773       // Check the following:
00774       // (1) Is the uniform variable declared but not used in your GLSL program?
00775       // (2) Double-check the spelling of the uniform variable name.
00776       vl::Log::warning( vl::Say(
00777         "warning:\n"
00778         "GLSLProgram::applyUniformSet(): uniform '%s' not found!\n"
00779         "Is the uniform variable declared but not used in your GLSL program?\n"
00780         "Also double-check the spelling of the uniform variable name.\n") << uniform->name() );
00781       continue;
00782     }
00783 
00784     // finally transmits the uniform
00785     // note: we don't perform delta binding per-uniform variable at the moment!
00786 
00787     VL_CHECK_OGL();
00788     switch(uniform->mType)
00789     {
00790       case UT_INT:      glUniform1iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
00791       case UT_INT_VEC2: glUniform2iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
00792       case UT_INT_VEC3: glUniform3iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
00793       case UT_INT_VEC4: glUniform4iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
00794 
00795       case UT_UNSIGNED_INT:      VL_glUniform1uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
00796       case UT_UNSIGNED_INT_VEC2: VL_glUniform2uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
00797       case UT_UNSIGNED_INT_VEC3: VL_glUniform3uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
00798       case UT_UNSIGNED_INT_VEC4: VL_glUniform4uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
00799 
00800       case UT_FLOAT:      glUniform1fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
00801       case UT_FLOAT_VEC2: glUniform2fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
00802       case UT_FLOAT_VEC3: glUniform3fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
00803       case UT_FLOAT_VEC4: glUniform4fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
00804 
00805       case UT_FLOAT_MAT2: glUniformMatrix2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00806       case UT_FLOAT_MAT3: glUniformMatrix3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00807       case UT_FLOAT_MAT4: glUniformMatrix4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00808 
00809       case UT_FLOAT_MAT2x3: glUniformMatrix2x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00810       case UT_FLOAT_MAT3x2: glUniformMatrix3x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00811       case UT_FLOAT_MAT2x4: glUniformMatrix2x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00812       case UT_FLOAT_MAT4x2: glUniformMatrix4x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00813       case UT_FLOAT_MAT3x4: glUniformMatrix3x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00814       case UT_FLOAT_MAT4x3: glUniformMatrix4x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
00815 
00816       case UT_DOUBLE:      glUniform1dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
00817       case UT_DOUBLE_VEC2: glUniform2dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
00818       case UT_DOUBLE_VEC3: glUniform3dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
00819       case UT_DOUBLE_VEC4: glUniform4dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
00820 
00821       case UT_DOUBLE_MAT2: glUniformMatrix2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00822       case UT_DOUBLE_MAT3: glUniformMatrix3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00823       case UT_DOUBLE_MAT4: glUniformMatrix4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00824 
00825       case UT_DOUBLE_MAT2x3: glUniformMatrix2x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00826       case UT_DOUBLE_MAT3x2: glUniformMatrix3x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00827       case UT_DOUBLE_MAT2x4: glUniformMatrix2x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00828       case UT_DOUBLE_MAT4x2: glUniformMatrix4x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00829       case UT_DOUBLE_MAT3x4: glUniformMatrix3x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00830       case UT_DOUBLE_MAT4x3: glUniformMatrix4x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
00831 
00832       case UT_NONE:
00833         // Probably you added a uniform to a Shader or Actor but you forgot to assign a valueto it.
00834         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() );
00835         VL_TRAP();
00836         break;
00837 
00838       default:
00839         vl::Log::bug( vl::Say("GLSLProgram::applyUniformSet(): wrong uniform type for '%s'!\n") << uniform->name() );
00840         VL_TRAP();
00841         break;
00842     }
00843   }
00844 
00845   VL_CHECK_OGL();
00846   return true;
00847 }
00848 //-----------------------------------------------------------------------------
00849 void GLSLProgram::bindFragDataLocation(int color_number, const char* name)
00850 {
00851   scheduleRelinking();
00852   mFragDataLocation[name] = color_number;
00853 }
00854 //-----------------------------------------------------------------------------
00855 void GLSLProgram::unbindFragDataLocation(const char* name)
00856 {
00857   scheduleRelinking();
00858   mFragDataLocation.erase(name);
00859 }
00860 //-----------------------------------------------------------------------------
00861 int GLSLProgram::fragDataLocation(const char* name) const
00862 {
00863   std::map<std::string, int>::const_iterator it = mFragDataLocation.find(name);
00864   if (it != mFragDataLocation.end())
00865     return it->second;
00866   else
00867     return -1;
00868 }
00869 //-----------------------------------------------------------------------------
00870 bool GLSLProgram::getProgramBinary(GLenum& binary_format, std::vector<unsigned char>& binary) const
00871 {
00872   VL_CHECK_OGL();
00873   VL_CHECK(Has_GL_ARB_get_program_binary)
00874   if (!Has_GL_ARB_get_program_binary)
00875     return false;
00876 
00877   binary.clear();
00878   binary_format = (GLenum)-1;
00879 
00880   if (handle())
00881   {
00882     int status = 0;
00883     glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
00884     if (status == GL_FALSE)
00885       return false;
00886     GLint length = 0;
00887     glGetProgramiv(handle(), GL_PROGRAM_BINARY_LENGTH, &length); VL_CHECK_OGL();
00888     if (length)
00889     {
00890       binary.resize(length);
00891       VL_glGetProgramBinary(handle(), length, NULL, &binary_format, &binary[0]); VL_CHECK_OGL();
00892     }
00893     return true;
00894   }
00895   else
00896   {
00897     VL_TRAP();
00898     return false;
00899   }
00900 }
00901 //-----------------------------------------------------------------------------
00902 bool GLSLProgram::programBinary(GLenum binary_format, const void* binary, int length)
00903 {
00904   VL_CHECK_OGL();
00905   VL_CHECK(Has_GL_ARB_get_program_binary)
00906   if (!Has_GL_ARB_get_program_binary)
00907     return false;
00908 
00909   createProgram();
00910 
00911   if (handle())
00912   {
00913     // pre-link operations
00914     preLink();
00915 
00916     // load glsl program and link
00917     VL_glProgramBinary(handle(), binary_format, binary, length); VL_CHECK_OGL();
00918     mScheduleLink = !linkStatus();
00919 
00920     // log error
00921     if(linked())
00922     {
00923       // post-link operations
00924       postLink();
00925 
00926       #ifndef NDEBUG
00927         String log = infoLog();
00928         if (!log.empty())
00929           Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
00930       #endif
00931     }
00932     else
00933     {
00934       Log::bug("GLSLProgram::programBinary() failed! (" + String(objectName().c_str()) + ")\n");
00935       Log::bug( Say("Info log:\n%s\n") << infoLog() );
00936       VL_TRAP();
00937     }
00938 
00939     return linked();
00940   }
00941   else
00942   {
00943     VL_TRAP();
00944     return false;
00945   }
00946 }
00947 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:37.
Permission is granted to use this page to write and publish articles regarding Visualization Library.