Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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://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, ¤t_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 //-----------------------------------------------------------------------------