# Visualization Library

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

[Home] [Tutorials] [All Classes] [Grouped Classes]

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

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/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       glGetActiveUniform(handle(), i, (GLsizei)tmp_buf.size(), NULL, &size, &type, name); VL_CHECK_OGL();
    00557       // Log::print( Say("[%n] uniform = %s\n") << i << name);
    00558
    00559       // mic fixme: might go in debug only release later...
    00560       // >>> CHECK UNIFORM NAMES (only for non OpenGL built-in uniforms!)
    00561       if (strstr(name, "gl_") != name)
    00562       {
    00563         GLint location = glGetUniformLocation(handle(), name);
    00564         if(location == -1)
    00565           Log::bug( Say("OpenGL driver bug: uniform '%s' not found! Please update your drivers or report the issue to your driver vendor.\n") << name);
    00566       }
    00567       // <<<
    00568
    00569       ref<UniformInfo> uinfo = new UniformInfo(name, (EUniformType)type, size, glGetUniformLocation(handle(), name));
    00570       mActiveUniforms[name] = uinfo;
    00571     }
    00572   }
    00573
    00574   // populate attribute binding map
    00575
    00576   mActiveAttribs.clear();
    00577
    00578   int attrib_len = 0;
    00579   glGetProgramiv(handle(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_len); VL_CHECK_OGL();
    00580   if (attrib_len)
    00581   {
    00582     std::vector<char> tmp_buf;
    00583     tmp_buf.resize(attrib_len);
    00584     char* name = &tmp_buf[0];
    00585
    00586     int attrib_count = 0;
    00587     glGetProgramiv(handle(), GL_ACTIVE_ATTRIBUTES, &attrib_count); VL_CHECK_OGL();
    00588     for(int i=0; i<attrib_count; ++i)
    00589     {
    00590       GLenum type;
    00591       int size;
    00592       glGetActiveAttrib(handle(), i, attrib_len, NULL, &size, &type, name); VL_CHECK_OGL();
    00593       ref<AttribInfo> uinfo = new AttribInfo(name, (EAttributeType)type, size, glGetAttribLocation(handle(), name));
    00594       mActiveAttribs[name] = uinfo;
    00595     }
    00596   }
    00597
    00598   // check for the predefined glsl uniform variables
    00599
    00600   m_vl_ModelViewMatrix           = glGetUniformLocation(handle(), "vl_ModelViewMatrix");
    00601   m_vl_ProjectionMatrix          = glGetUniformLocation(handle(), "vl_ProjectionMatrix");
    00602   m_vl_ModelViewProjectionMatrix = glGetUniformLocation(handle(), "vl_ModelViewProjectionMatrix");
    00603   m_vl_NormalMatrix              = glGetUniformLocation(handle(), "vl_NormalMatrix");
    00604 }
    00605 //-----------------------------------------------------------------------------
    00606 bool GLSLProgram::linkStatus() const
    00607 {
    00608   VL_CHECK_OGL();
    00609   VL_CHECK( Has_GLSL )
    00610   if( !Has_GLSL )
    00611     return false;
    00612
    00613   VL_CHECK(handle())
    00614
    00615   if (handle() == 0)
    00616     return false;
    00617
    00618   int status = 0;
    00619   glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
    00620   return status == GL_TRUE;
    00621 }
    00622 //-----------------------------------------------------------------------------
    00623 String GLSLProgram::infoLog() const
    00624 {
    00625   VL_CHECK_OGL();
    00626   VL_CHECK( Has_GLSL )
    00627   if( !Has_GLSL )
    00628     return "OpenGL Shading Language not supported!\n";
    00629
    00630   VL_CHECK(handle())
    00631
    00632   if (handle() == 0)
    00633     return "GLSLProgram::infoLog(): error! GLSL program object not yet created! (" + String(objectName().c_str()) + ")\n";
    00634
    00635   int max_length = 0;
    00636   glGetProgramiv(handle(), GL_INFO_LOG_LENGTH, &max_length); VL_CHECK_OGL();
    00637   std::vector<char> log_buffer;
    00638   log_buffer.resize(max_length+1);
    00639   glGetProgramInfoLog(handle(), max_length, NULL, &log_buffer[0]); VL_CHECK_OGL();
    00640   return &log_buffer[0];
    00641 }
    00642 //-----------------------------------------------------------------------------
    00643 bool GLSLProgram::validateProgram() const
    00644 {
    00645   VL_CHECK_OGL();
    00646   VL_CHECK( Has_GLSL )
    00647   if( !Has_GLSL )
    00648     return false;
    00649
    00650   VL_CHECK(handle())
    00651
    00652   if (handle() == 0)
    00653     return false;
    00654
    00655   glValidateProgram(handle());
    00656   int status = 0;
    00657   glGetProgramiv(handle(), GL_VALIDATE_STATUS, &status); VL_CHECK_OGL();
    00658   return status == GL_TRUE;
    00659 }
    00660 //-----------------------------------------------------------------------------
    00661 void GLSLProgram::bindAttribLocation(unsigned int index, const char* name)
    00662 {
    00663   VL_CHECK_OGL();
    00664   VL_CHECK( Has_GLSL )
    00665
    00666   createProgram();
    00667   scheduleRelinking();
    00668   glBindAttribLocation(handle(), index, name); VL_CHECK_OGL()
    00669 }
    00670 //-----------------------------------------------------------------------------
    00671 bool GLSLProgram::useProgram() const
    00672 {
    00673   VL_CHECK_OGL()
    00674   VL_CHECK( Has_GLSL )
    00675   if( !Has_GLSL )
    00676     return false;
    00677
    00678   if (!handle())
    00679   {
    00680     Log::bug("GLSLProgram::useProgram() failed! GLSL program handle is null! (" + String(objectName().c_str()) + ")\n");
    00681     VL_TRAP()
    00682     return false;
    00683   }
    00684
    00685   if (!linked())
    00686   {
    00687     Log::bug("GLSLProgram::useProgram() failed! GLSL program not linked! (" + String(objectName().c_str()) + ")\n");
    00688     VL_TRAP()
    00689     return false;
    00690   }
    00691
    00692 // The program validation should be done only after all the uniforms have been applied, just before rendering an object.
    00693 //#ifndef NDEBUG
    00694 //  if (!validateProgram())
    00695 //  {
    00696 //    Log::bug("GLSLProgram::useProgram() failed validation! (" + String(objectName().c_str()) + ")\n");
    00697 //    Log::bug( Say("Info log:\n%s\n") << infoLog() );
    00698 //    VL_TRAP();
    00699 //    return false;
    00700 //  }
    00701 //#endif
    00702
    00703   // bind the GLSL program
    00704   glUseProgram(handle()); VL_CHECK_OGL()
    00705
    00706   return true;
    00707 }
    00708 //-----------------------------------------------------------------------------
    00709 void GLSLProgram::apply(int /*index*/, const Camera*, OpenGLContext*) const
    00710 {
    00711   VL_CHECK_OGL();
    00712   if(Has_GLSL)
    00713   {
    00714     if ( handle() )
    00715       useProgram();
    00716     else
    00717       glUseProgram(0); VL_CHECK_OGL();
    00718   }
    00719 }
    00720 //-----------------------------------------------------------------------------
    00721 bool GLSLProgram::applyUniformSet(const UniformSet* uniforms) const
    00722 {
    00723   VL_CHECK_OGL();
    00724   VL_CHECK( Has_GLSL )
    00725   if( !Has_GLSL )
    00726     return false;
    00727
    00728   if(!uniforms)
    00729     return false;
    00730
    00731   if (!linked())
    00732     return false;
    00733
    00734   if (!handle())
    00735     return false;
    00736
    00737 #ifndef NDEBUG
    00738   int current_glsl_program = -1;
    00739   glGetIntegerv(GL_CURRENT_PROGRAM, &current_glsl_program); VL_CHECK_OGL();
    00740   VL_CHECK(current_glsl_program == (int)handle())
    00741 #endif
    00742
    00743   for(size_t i=0, count=uniforms->uniforms().size(); i<count; ++i)
    00744   {
    00745     const Uniform* uniform = uniforms->uniforms()[i].get();
    00746
    00747     #if 1
    00748       const UniformInfo* uinfo = activeUniformInfo(uniform->name().c_str());
    00749       int location = uinfo ? uinfo->Location : -1;
    00750
    00751       #ifndef NDEBUG
    00752       if (location == -1)
    00753       {
    00754         std::map<std::string, ref<UniformInfo> >::const_iterator it = activeUniforms().begin();
    00755         Log::warning("\nActive uniforms:\n");
    00756         for( ; it != activeUniforms().end(); ++it )
    00757           Log::warning( Say("\t%s\n") << it->first.c_str() );
    00758       }
    00759       #endif
    00760
    00761     #else
    00762       int location = glGetUniformLocation(handle(), uniform->name().c_str());
    00763     #endif
    00764
    00765     if (location == -1)
    00766     {
    00767       // Check the following:
    00768       // (1) Is the uniform variable declared but not used in your GLSL program?
    00769       // (2) Double-check the spelling of the uniform variable name.
    00770       vl::Log::warning( vl::Say(
    00771         "warning:\n"
    00772         "GLSLProgram::applyUniformSet(): uniform '%s' not found!\n"
    00773         "Is the uniform variable declared but not used in your GLSL program?\n"
    00774         "Also double-check the spelling of the uniform variable name.\n") << uniform->name() );
    00775       continue;
    00776     }
    00777
    00778     // finally transmits the uniform
    00779     // note: we don't perform delta binding per-uniform variable at the moment!
    00780
    00781     VL_CHECK_OGL();
    00782     switch(uniform->mType)
    00783     {
    00784       case UT_INT:      glUniform1iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
    00785       case UT_INT_VEC2: glUniform2iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
    00786       case UT_INT_VEC3: glUniform3iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
    00787       case UT_INT_VEC4: glUniform4iv(location, uniform->count(), uniform->intData()); VL_CHECK_OGL(); break;
    00788
    00789       case UT_UNSIGNED_INT:      VL_glUniform1uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
    00790       case UT_UNSIGNED_INT_VEC2: VL_glUniform2uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
    00791       case UT_UNSIGNED_INT_VEC3: VL_glUniform3uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
    00792       case UT_UNSIGNED_INT_VEC4: VL_glUniform4uiv(location, uniform->count(), uniform->uintData()); VL_CHECK_OGL(); break;
    00793
    00794       case UT_FLOAT:      glUniform1fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
    00795       case UT_FLOAT_VEC2: glUniform2fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
    00796       case UT_FLOAT_VEC3: glUniform3fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
    00797       case UT_FLOAT_VEC4: glUniform4fv(location, uniform->count(), uniform->floatData()); VL_CHECK_OGL(); break;
    00798
    00799       case UT_FLOAT_MAT2: glUniformMatrix2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00800       case UT_FLOAT_MAT3: glUniformMatrix3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00801       case UT_FLOAT_MAT4: glUniformMatrix4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00802
    00803       case UT_FLOAT_MAT2x3: glUniformMatrix2x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00804       case UT_FLOAT_MAT3x2: glUniformMatrix3x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00805       case UT_FLOAT_MAT2x4: glUniformMatrix2x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00806       case UT_FLOAT_MAT4x2: glUniformMatrix4x2fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00807       case UT_FLOAT_MAT3x4: glUniformMatrix3x4fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00808       case UT_FLOAT_MAT4x3: glUniformMatrix4x3fv(location, uniform->count(), GL_FALSE, uniform->floatData()); VL_CHECK_OGL(); break;
    00809
    00810       case UT_DOUBLE:      glUniform1dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
    00811       case UT_DOUBLE_VEC2: glUniform2dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
    00812       case UT_DOUBLE_VEC3: glUniform3dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
    00813       case UT_DOUBLE_VEC4: glUniform4dv(location, uniform->count(), uniform->doubleData()); VL_CHECK_OGL(); break;
    00814
    00815       case UT_DOUBLE_MAT2: glUniformMatrix2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00816       case UT_DOUBLE_MAT3: glUniformMatrix3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00817       case UT_DOUBLE_MAT4: glUniformMatrix4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00818
    00819       case UT_DOUBLE_MAT2x3: glUniformMatrix2x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00820       case UT_DOUBLE_MAT3x2: glUniformMatrix3x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00821       case UT_DOUBLE_MAT2x4: glUniformMatrix2x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00822       case UT_DOUBLE_MAT4x2: glUniformMatrix4x2dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00823       case UT_DOUBLE_MAT3x4: glUniformMatrix3x4dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00824       case UT_DOUBLE_MAT4x3: glUniformMatrix4x3dv(location, uniform->count(), GL_FALSE, uniform->doubleData()); VL_CHECK_OGL(); break;
    00825
    00826       case UT_NONE:
    00827         // Probably you added a uniform to a Shader or Actor but you forgot to assign a valueto it.
    00828         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() );
    00829         VL_TRAP();
    00830         break;
    00831
    00832       default:
    00833         vl::Log::bug( vl::Say("GLSLProgram::applyUniformSet(): wrong uniform type for '%s'!\n") << uniform->name() );
    00834         VL_TRAP();
    00835         break;
    00836     }
    00837   }
    00838
    00839   VL_CHECK_OGL();
    00840   return true;
    00841 }
    00842 //-----------------------------------------------------------------------------
    00843 void GLSLProgram::bindFragDataLocation(int color_number, const char* name)
    00844 {
    00845   scheduleRelinking();
    00846   mFragDataLocation[name] = color_number;
    00847 }
    00848 //-----------------------------------------------------------------------------
    00849 void GLSLProgram::unbindFragDataLocation(const char* name)
    00850 {
    00851   scheduleRelinking();
    00852   mFragDataLocation.erase(name);
    00853 }
    00854 //-----------------------------------------------------------------------------
    00855 int GLSLProgram::fragDataLocation(const char* name) const
    00856 {
    00857   std::map<std::string, int>::const_iterator it = mFragDataLocation.find(name);
    00858   if (it != mFragDataLocation.end())
    00859     return it->second;
    00860   else
    00861     return -1;
    00862 }
    00863 //-----------------------------------------------------------------------------
    00864 bool GLSLProgram::getProgramBinary(GLenum& binary_format, std::vector<unsigned char>& binary) const
    00865 {
    00866   VL_CHECK_OGL();
    00867   VL_CHECK(Has_GL_ARB_get_program_binary)
    00868   if (!Has_GL_ARB_get_program_binary)
    00869     return false;
    00870
    00871   binary.clear();
    00872   binary_format = (GLenum)-1;
    00873
    00874   if (handle())
    00875   {
    00876     int status = 0;
    00877     glGetProgramiv(handle(), GL_LINK_STATUS, &status); VL_CHECK_OGL();
    00878     if (status == GL_FALSE)
    00879       return false;
    00880     GLint length = 0;
    00881     glGetProgramiv(handle(), GL_PROGRAM_BINARY_LENGTH, &length); VL_CHECK_OGL();
    00882     if (length)
    00883     {
    00884       binary.resize(length);
    00885       VL_glGetProgramBinary(handle(), length, NULL, &binary_format, &binary[0]); VL_CHECK_OGL();
    00886     }
    00887     return true;
    00888   }
    00889   else
    00890   {
    00891     VL_TRAP();
    00892     return false;
    00893   }
    00894 }
    00895 //-----------------------------------------------------------------------------
    00896 bool GLSLProgram::programBinary(GLenum binary_format, const void* binary, int length)
    00897 {
    00898   VL_CHECK_OGL();
    00899   VL_CHECK(Has_GL_ARB_get_program_binary)
    00900   if (!Has_GL_ARB_get_program_binary)
    00901     return false;
    00902
    00903   createProgram();
    00904
    00905   if (handle())
    00906   {
    00907     // pre-link operations
    00908     preLink();
    00909
    00910     // load glsl program and link
    00911     VL_glProgramBinary(handle(), binary_format, binary, length); VL_CHECK_OGL();
    00912     mScheduleLink = !linkStatus();
    00913
    00914     // log error
    00915     if(linked())
    00916     {
    00917       // post-link operations
    00918       postLink();
    00919
    00920       #ifndef NDEBUG
    00921         String log = infoLog();
    00922         if (!log.empty())
    00923           Log::warning( Say("%s\n%s\n\n") << objectName().c_str() << log );
    00924       #endif
    00925     }
    00926     else
    00927     {
    00928       Log::bug("GLSLProgram::programBinary() failed! (" + String(objectName().c_str()) + ")\n");
    00929       Log::bug( Say("Info log:\n%s\n") << infoLog() );
    00930       VL_TRAP();
    00931     }
    00932
    00933     return linked();
    00934   }
    00935   else
    00936   {
    00937     VL_TRAP();
    00938     return false;
    00939   }
    00940 }
    00941 //-----------------------------------------------------------------------------

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:39.
Permission is granted to use this page to write and publish articles regarding Visualization Library.