# Visualization Library

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

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

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/Renderer.cpp

Go to the documentation of this file.

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

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:24.
Permission is granted to use this page to write and publish articles regarding Visualization Library.