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 <vlCore/GlobalSettings.hpp> 00033 #include <vlGraphics/Renderer.hpp> 00034 #include <vlGraphics/OpenGLContext.hpp> 00035 #include <vlGraphics/GLSL.hpp> 00036 #include <vlGraphics/RenderQueue.hpp> 00037 #include <vlCore/Log.hpp> 00038 00039 using namespace vl; 00040 00041 //------------------------------------------------------------------------------ 00042 // Renderer 00043 //------------------------------------------------------------------------------ 00044 Renderer::Renderer() 00045 { 00046 VL_DEBUG_SET_OBJECT_NAME() 00047 00048 mProjViewTransfCallback = new ProjViewTransfCallback; 00049 00050 mDummyEnables = new EnableSet; 00051 mDummyStateSet = new RenderStateSet; 00052 } 00053 //------------------------------------------------------------------------------ 00054 namespace 00055 { 00056 struct GLSLProgState 00057 { 00058 public: 00059 GLSLProgState(): mCamera(NULL), mTransform(NULL), mGLSLProgUniformSet(NULL), mShaderUniformSet(NULL), mActorUniformSet(NULL) {} 00060 00061 bool operator<(const GLSLProgState& other) const 00062 { 00063 if ( mCamera != other.mCamera ) 00064 return mCamera < other.mCamera; 00065 else 00066 if ( mTransform != other.mTransform ) 00067 return mTransform < other.mTransform; 00068 else 00069 if ( mGLSLProgUniformSet != other.mGLSLProgUniformSet ) 00070 return mGLSLProgUniformSet < other.mGLSLProgUniformSet; 00071 else 00072 if ( mShaderUniformSet != other.mShaderUniformSet ) 00073 return mShaderUniformSet < other.mShaderUniformSet; 00074 else 00075 return mActorUniformSet < other.mActorUniformSet; 00076 } 00077 00078 const Camera* mCamera; 00079 const Transform* mTransform; 00080 const UniformSet* mGLSLProgUniformSet; 00081 const UniformSet* mShaderUniformSet; 00082 const UniformSet* mActorUniformSet; 00083 }; 00084 } 00085 //------------------------------------------------------------------------------ 00086 const RenderQueue* Renderer::render(const RenderQueue* render_queue, Camera* camera, real frame_clock) 00087 { 00088 VL_CHECK_OGL() 00089 00090 // skip if renderer is disabled 00091 00092 if (enableMask() == 0) 00093 return render_queue; 00094 00095 // enter/exit behavior contract 00096 00097 class InOutContract 00098 { 00099 Renderer* mRenderer; 00100 std::vector<RenderStateSlot> mOriginalDefaultRS; 00101 public: 00102 InOutContract(Renderer* renderer, Camera* camera): mRenderer(renderer) 00103 { 00104 // increment the render tick. 00105 mRenderer->mRenderTick++; 00106 00107 // render-target activation. 00108 // note: an OpenGL context can have multiple rendering targets! 00109 mRenderer->framebuffer()->activate(); 00110 00111 // viewport setup. 00112 camera->viewport()->setClearFlags( mRenderer->clearFlags() ); 00113 camera->viewport()->activate(); 00114 00115 OpenGLContext* gl_context = renderer->framebuffer()->openglContext(); 00116 00117 // default render states override 00118 for(size_t i=0; i<renderer->overriddenDefaultRenderStates().size(); ++i) 00119 { 00120 // save overridden default render state to be restored later 00121 ERenderState type = renderer->overriddenDefaultRenderStates()[i].type(); 00122 mOriginalDefaultRS.push_back(gl_context->defaultRenderState(type)); 00123 // set new default render state 00124 gl_context->setDefaultRenderState(renderer->overriddenDefaultRenderStates()[i]); 00125 } 00126 00127 // dispatch the renderer-started event. 00128 mRenderer->dispatchOnRendererStarted(); 00129 00130 // check user-generated errors. 00131 VL_CHECK_OGL() 00132 } 00133 00134 ~InOutContract() 00135 { 00136 // dispatch the renderer-finished event 00137 mRenderer->dispatchOnRendererFinished(); 00138 00139 OpenGLContext* gl_context = mRenderer->framebuffer()->openglContext(); 00140 00141 // restore default render states 00142 for(size_t i=0; i<mOriginalDefaultRS.size(); ++i) 00143 { 00144 gl_context->setDefaultRenderState(mOriginalDefaultRS[i]); 00145 } 00146 00147 VL_CHECK( !globalSettings()->checkOpenGLStates() || mRenderer->framebuffer()->openglContext()->isCleanState(true) ); 00148 00149 // check user-generated errors. 00150 VL_CHECK_OGL() 00151 00152 // note: we don't reset the render target here 00153 } 00154 } contract(this, camera); 00155 00156 // --------------- rendering --------------- 00157 00158 std::map<const GLSLProgram*, GLSLProgState> glslprogram_map; 00159 00160 OpenGLContext* opengl_context = framebuffer()->openglContext(); 00161 00162 // --------------- default scissor --------------- 00163 00164 // non GLSLProgram state sets 00165 const RenderStateSet* cur_render_state_set = NULL; 00166 const EnableSet* cur_enable_set = NULL; 00167 const Scissor* cur_scissor = NULL; 00168 00169 // scissor the viewport by default: needed for points and lines since they are not clipped against the viewport 00170 // this is already setup by the Viewport 00171 /* 00172 glEnable(GL_SCISSOR_TEST); 00173 glScissor(camera->viewport()->x(), camera->viewport()->y(), camera->viewport()->width(), camera->viewport()->height()); 00174 */ 00175 00176 // --------------- rendering --------------- 00177 00178 for(int itok=0; itok < render_queue->size(); ++itok) 00179 { 00180 const RenderToken* tok = render_queue->at(itok); VL_CHECK(tok); 00181 Actor* actor = tok->mActor; VL_CHECK(actor); 00182 00183 if ( !isEnabled(actor->enableMask()) ) 00184 continue; 00185 00186 // --------------- Actor's scissor --------------- 00187 00188 // mic fixme:this kind of scissor management is not particularly elegant. 00189 // It is required mainly for convenience for the vector graphics that allow the specification of a clipping rectangular area at any point in the rendering. 00190 // We must also find a good general solution to support indexed scissoring and viewport. 00191 00192 const Scissor* scissor = actor->scissor() ? actor->scissor() : tok->mShader->scissor(); 00193 if (cur_scissor != scissor) 00194 { 00195 cur_scissor = scissor; 00196 if (cur_scissor) 00197 { 00198 cur_scissor->enable(camera->viewport()); 00199 } 00200 else 00201 { 00202 // scissor the viewport by default: needed for points and lines with size > 1.0 as they are not clipped against the viewport. 00203 VL_CHECK(glIsEnabled(GL_SCISSOR_TEST)) 00204 glScissor(camera->viewport()->x(), camera->viewport()->y(), camera->viewport()->width(), camera->viewport()->height()); 00205 } 00206 } 00207 00208 // multipassing 00209 for( int ipass=0; tok != NULL; tok = tok->mNextPass, ++ipass ) 00210 { 00211 VL_CHECK_OGL() 00212 00213 // --------------- shader setup --------------- 00214 00215 const Shader* shader = tok->mShader; 00216 00217 // shader override: select the first that matches 00218 00219 for( std::map< unsigned int, ref<Shader> >::const_iterator eom_it = mShaderOverrideMask.begin(); 00220 eom_it != mShaderOverrideMask.end(); 00221 ++eom_it ) 00222 { 00223 if ( eom_it->first & actor->enableMask() ) 00224 { 00225 shader = eom_it->second.get(); 00226 break; 00227 } 00228 } 00229 00230 // shader's render states 00231 00232 if ( cur_render_state_set != shader->getRenderStateSet() ) 00233 { 00234 opengl_context->applyRenderStates( shader->getRenderStateSet(), camera ); 00235 cur_render_state_set = shader->getRenderStateSet(); 00236 } 00237 00238 VL_CHECK_OGL() 00239 00240 // shader's enables 00241 00242 if ( cur_enable_set != shader->getEnableSet() ) 00243 { 00244 opengl_context->applyEnables( shader->getEnableSet() ); 00245 cur_enable_set = shader->getEnableSet(); 00246 } 00247 00248 #ifndef NDEBUG 00249 if (glGetError() != GL_NO_ERROR) 00250 { 00251 Log::error("An unsupported OpenGL glEnable/glDisable capability has been enabled!\n"); 00252 VL_TRAP() 00253 } 00254 #endif 00255 00256 // --------------- Actor pre-render callback --------------- 00257 00258 // here the user has still the possibility to modify the Actor's uniforms 00259 00260 actor->dispatchOnActorRenderStarted( frame_clock, camera, tok->mRenderable, shader, ipass ); 00261 00262 VL_CHECK_OGL() 00263 00264 // --------------- GLSLProgram setup --------------- 00265 00266 VL_CHECK( !shader->glslProgram() || shader->glslProgram()->linked() ); 00267 00268 VL_CHECK_OGL() 00269 00270 // current transform 00271 const Transform* cur_transform = actor->transform(); 00272 const GLSLProgram* cur_glsl_program = NULL; // NULL == fixed function pipeline 00273 const UniformSet* cur_glsl_prog_uniform_set = NULL; 00274 const UniformSet* cur_shader_uniform_set = NULL; 00275 const UniformSet* cur_actor_uniform_set = NULL; 00276 00277 // make sure we update these things only if there is a valid GLSLProgram 00278 if (shader->glslProgram() && shader->glslProgram()->handle()) 00279 { 00280 cur_glsl_program = shader->glslProgram(); 00281 00282 // consider them NULL if they are empty 00283 if (cur_glsl_program->getUniformSet() && !cur_glsl_program->getUniformSet()->uniforms().empty()) 00284 cur_glsl_prog_uniform_set = cur_glsl_program->getUniformSet(); 00285 00286 if (shader->getUniformSet() && !shader->getUniformSet()->uniforms().empty()) 00287 cur_shader_uniform_set = shader->getUniformSet(); 00288 00289 if (actor->getUniformSet() && !actor->getUniformSet()->uniforms().empty()) 00290 cur_actor_uniform_set = actor->getUniformSet(); 00291 } 00292 00293 bool update_cm = false; // update camera 00294 bool update_tr = false; // update transform 00295 bool update_pu = false; // update glsl-program uniforms 00296 bool update_su = false; // update shader uniforms 00297 bool update_au = false; // update actor uniforms 00298 GLSLProgState* glsl_state = NULL; 00299 00300 // retrieve the state of this GLSLProgram (including the NULL one) 00301 std::map<const GLSLProgram*, GLSLProgState>::iterator glsl_state_it = glslprogram_map.find(cur_glsl_program); 00302 00303 if ( glsl_state_it == glslprogram_map.end() ) 00304 { 00305 // 00306 // this is the first time we see this GLSL program so we update everything we can 00307 // 00308 00309 // create a new glsl-state entry 00310 glsl_state = &glslprogram_map[cur_glsl_program]; 00311 update_cm = true; 00312 update_tr = true; 00313 update_pu = cur_glsl_prog_uniform_set != NULL; 00314 update_su = cur_shader_uniform_set != NULL; 00315 update_au = cur_actor_uniform_set != NULL; 00316 } 00317 else 00318 { 00319 // 00320 // we already know this GLSLProgram so we update only what has changed since last time 00321 // 00322 00323 glsl_state = &glsl_state_it->second; 00324 // check for differences 00325 update_cm = glsl_state->mCamera != camera; 00326 update_tr = glsl_state->mTransform != cur_transform; 00327 update_pu = glsl_state->mGLSLProgUniformSet != cur_glsl_prog_uniform_set && cur_glsl_prog_uniform_set != NULL; 00328 update_su = glsl_state->mShaderUniformSet != cur_shader_uniform_set && cur_shader_uniform_set != NULL; 00329 update_au = glsl_state->mActorUniformSet != cur_actor_uniform_set && cur_actor_uniform_set != NULL; 00330 } 00331 00332 // update glsl-state structure 00333 glsl_state->mCamera = camera; 00334 glsl_state->mTransform = cur_transform; 00335 glsl_state->mGLSLProgUniformSet = cur_glsl_prog_uniform_set; 00336 glsl_state->mShaderUniformSet = cur_shader_uniform_set; 00337 glsl_state->mActorUniformSet = cur_actor_uniform_set; 00338 00339 // --- update proj, view and transform matrices --- 00340 00341 VL_CHECK_OGL() 00342 00343 if (update_cm || update_tr) 00344 projViewTransfCallback()->updateMatrices( update_cm, update_tr, cur_glsl_program, camera, cur_transform ); 00345 00346 VL_CHECK_OGL() 00347 00348 // --- uniforms --- 00349 00350 // note: the user must not make the glslprogram's, shader's and actor's uniforms collide! 00351 VL_CHECK( !opengl_context->areUniformsColliding(cur_shader_uniform_set, cur_actor_uniform_set) ); 00352 VL_CHECK( !opengl_context->areUniformsColliding(cur_shader_uniform_set, cur_glsl_prog_uniform_set ) ); 00353 VL_CHECK( !opengl_context->areUniformsColliding(cur_actor_uniform_set, cur_glsl_prog_uniform_set ) ); 00354 00355 VL_CHECK_OGL() 00356 00357 // glsl program uniform set 00358 if ( update_pu ) 00359 { 00360 VL_CHECK( cur_glsl_prog_uniform_set && cur_glsl_prog_uniform_set->uniforms().size() ); 00361 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() ) 00362 cur_glsl_program->applyUniformSet( cur_glsl_prog_uniform_set ); 00363 } 00364 00365 VL_CHECK_OGL() 00366 00367 // shader uniform set 00368 if ( update_su ) 00369 { 00370 VL_CHECK( cur_shader_uniform_set && cur_shader_uniform_set->uniforms().size() ); 00371 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() ) 00372 cur_glsl_program->applyUniformSet( cur_shader_uniform_set ); 00373 } 00374 00375 VL_CHECK_OGL() 00376 00377 // actor uniform set 00378 if ( update_au ) 00379 { 00380 VL_CHECK( cur_actor_uniform_set && cur_actor_uniform_set->uniforms().size() ); 00381 VL_CHECK( shader->getRenderStateSet()->glslProgram() && shader->getRenderStateSet()->glslProgram()->handle() ) 00382 cur_glsl_program->applyUniformSet( cur_actor_uniform_set ); 00383 } 00384 00385 VL_CHECK_OGL() 00386 00387 // --------------- Actor rendering --------------- 00388 00389 // also compiles display lists and updates BufferObjects if necessary 00390 tok->mRenderable->render( actor, shader, camera, opengl_context ); 00391 00392 VL_CHECK_OGL() 00393 00394 // if shader is overridden it does not make sense to perform multipassing so we break the loop here. 00395 if (shader != tok->mShader) 00396 break; 00397 } 00398 } 00399 00400 // clear enables 00401 opengl_context->applyEnables( mDummyEnables.get() ); VL_CHECK_OGL(); 00402 00403 // clear render states 00404 opengl_context->applyRenderStates( mDummyStateSet.get(), NULL ); VL_CHECK_OGL(); 00405 00406 // enabled texture unit #0 00407 VL_glActiveTexture( GL_TEXTURE0 ); VL_CHECK_OGL(); 00408 if (Has_Fixed_Function_Pipeline) 00409 VL_glClientActiveTexture( GL_TEXTURE0 ); VL_CHECK_OGL(); 00410 00411 // disable scissor test 00412 glDisable(GL_SCISSOR_TEST); VL_CHECK_OGL(); 00413 00414 // disable all vertex arrays, note this also calls "glBindBuffer(GL_ARRAY_BUFFER, 0)" 00415 opengl_context->bindVAS(NULL, false, false); VL_CHECK_OGL(); 00416 00417 return render_queue; 00418 } 00419 //-----------------------------------------------------------------------------