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

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