# 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/Rendering.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/Rendering.hpp>
    00033 #include <vlGraphics/OpenGLContext.hpp>
    00034 #include <vlGraphics/Renderer.hpp>
    00035 #include <vlGraphics/SceneManager.hpp>
    00036 #include <vlGraphics/RenderQueue.hpp>
    00037 #include <vlGraphics/GLSL.hpp>
    00038 #include <vlCore/Log.hpp>
    00039 #include <vlCore/Say.hpp>
    00040
    00041 using namespace vl;
    00042
    00043 //------------------------------------------------------------------------------
    00044 Rendering::Rendering():
    00045   mAutomaticResourceInit(true),
    00046   mCullingEnabled(true),
    00047   mEvaluateLOD(true),
    00048   mShaderAnimationEnabled(true),
    00049   mNearFarClippingPlanesOptimized(false)
    00050 {
    00051   VL_DEBUG_SET_OBJECT_NAME()
    00052   mRenderQueueSorter  = new RenderQueueSorterStandard;
    00053   mActorQueue         = new ActorCollection;
    00054   mRenderQueue        = new RenderQueue;
    00055   mSceneManagers      = new Collection<SceneManager>;
    00056   mCamera             = new Camera;
    00057   mTransform          = new Transform;
    00058   mRenderers.push_back( new Renderer );
    00059 }
    00060 //------------------------------------------------------------------------------
    00061 Rendering& Rendering::operator=(const Rendering& other)
    00062 {
    00063   RenderingAbstract::operator=(other);
    00064
    00065   mEnableMask               = other.mEnableMask;
    00066   mAutomaticResourceInit    = other.mAutomaticResourceInit;
    00067   mCullingEnabled    = other.mCullingEnabled;
    00068   mEvaluateLOD              = other.mEvaluateLOD;
    00069   mShaderAnimationEnabled   = other.mShaderAnimationEnabled;
    00070   mNearFarClippingPlanesOptimized = other.mNearFarClippingPlanesOptimized;
    00071
    00072   mRenderQueueSorter   = other.mRenderQueueSorter;
    00073   /*mActorQueue        = other.mActorQueue;*/
    00074   /*mRenderQueue       = other.mRenderQueue;*/
    00075   *mSceneManagers      = *other.mSceneManagers;
    00076   mRenderers           = other.mRenderers;
    00077   mCamera              = other.mCamera;
    00078   mTransform           = other.mTransform;
    00079
    00080   return *this;
    00081 }
    00082 //------------------------------------------------------------------------------
    00083 void Rendering::render()
    00084 {
    00085   VL_CHECK(camera());
    00086   VL_CHECK(camera()->viewport());
    00087
    00088   // if rendering is disabled skip all.
    00089
    00090   if ( enableMask() == 0 )
    00091     return;
    00092
    00093   // enter/exit behavior contract
    00094
    00095   class InOutContract
    00096   {
    00097     Rendering* mRendering;
    00098     OpenGLContext* mOpenGLContext;
    00099
    00100   public:
    00101     InOutContract(Rendering* rendering): mRendering(rendering)
    00102     {
    00103       VL_CHECK(mRendering->renderers().size());
    00104       VL_CHECK(mRendering->renderers()[0]->renderTarget());
    00105       VL_CHECK(mRendering->renderers()[0]->renderTarget()->openglContext());
    00106
    00107       // as stated in the documentation all the renderers must target the same OpenGLContext
    00108       mOpenGLContext = mRendering->renderers()[0]->renderTarget()->openglContext();
    00109
    00110       // activate OpenGL context
    00111       mOpenGLContext->makeCurrent();
    00112       VL_CHECK_OGL(); // the first check must be done when the context is active!
    00113
    00114       // render states ]shield[
    00115       mOpenGLContext->resetContextStates();
    00116
    00117       // pre rendering callback
    00118       mRendering->dispatchOnRenderingStarted();
    00119
    00120       // check user-generated errors.
    00121       VL_CHECK_OGL()
    00122     }
    00123
    00124     ~InOutContract()
    00125     {
    00126       // post rendering callback
    00127       mRendering->dispatchOnRenderingFinished();
    00128
    00129       // check user-generated errors.
    00130       VL_CHECK_OGL()
    00131
    00132       // render states ]shield[
    00133       mOpenGLContext->resetContextStates();
    00134     }
    00135   } contract(this);
    00136
    00137   // --------------- rendering ---------------
    00138
    00139   if (renderers().empty())
    00140   {
    00141     vl::Log::error("Rendering::render(): no Renderer specified for this Rendering!\n");
    00142     VL_TRAP();
    00143     return;
    00144   }
    00145
    00146   if (!renderers()[0]->renderTarget())
    00147   {
    00148     vl::Log::error("Rendering::render(): no RendererTarget specified for Renderer #0!\n");
    00149     VL_TRAP();
    00150     return;
    00151   }
    00152
    00153   if (!renderers()[0]->renderTarget()->openglContext())
    00154   {
    00155     vl::Log::error("Rendering::render(): invalid RenderTarget for Renderer #0, OpenGLContext is NULL!\n");
    00156     VL_TRAP();
    00157     return;
    00158   }
    00159
    00160   if (sceneManagers()->empty())
    00161     return;
    00162
    00163   if (!camera())
    00164     return;
    00165
    00166   if (!camera()->viewport())
    00167     return;
    00168
    00169   // transform
    00170
    00171   if (transform() != NULL)
    00172     transform()->computeWorldMatrixRecursive( camera() );
    00173
    00174   // camera transform update (can be redundant)
    00175
    00176   if (camera()->followedTransform())
    00177     camera()->setInverseViewMatrix( camera()->followedTransform()->worldMatrix() );
    00178
    00179   VL_CHECK_OGL()
    00180
    00181   // culling & actor queue filling
    00182
    00183   camera()->computeFrustumPlanes();
    00184
    00185   // if near/far clipping planes optimization is enabled don't perform far-culling
    00186   if (nearFarClippingPlanesOptimized())
    00187   {
    00188     // perform only near culling with plane at distance 0
    00189     camera()->frustum().planes().resize(5);
    00190     camera()->frustum().planes()[4] = Plane( camera()->inverseViewMatrix().getT(),
    00191                                              camera()->inverseViewMatrix().getZ());
    00192   }
    00193
    00194   actorQueue()->clear();
    00195   for(int i=0; i<sceneManagers()->size(); ++i)
    00196   {
    00197     if ( isEnabled(sceneManagers()->at(i)->enableMask()) )
    00198     {
    00199       if (cullingEnabled() && sceneManagers()->at(i)->cullingEnabled())
    00200       {
    00201         if (sceneManagers()->at(i)->boundsDirty())
    00202           sceneManagers()->at(i)->computeBounds();
    00203         // try to cull the scene with both bsphere and bbox
    00204         bool visible = !camera()->frustum().cull(sceneManagers()->at(i)->boundingSphere()) &&
    00205                        !camera()->frustum().cull(sceneManagers()->at(i)->boundingBox());
    00206         if ( visible )
    00207           sceneManagers()->at(i)->extractVisibleActors( *actorQueue(), camera() );
    00208       }
    00209       else
    00210         sceneManagers()->at(i)->extractActors( *actorQueue() );
    00211     }
    00212   }
    00213
    00214   // collect near/far clipping planes optimization information
    00215   if (nearFarClippingPlanesOptimized())
    00216   {
    00217     Sphere world_bounding_sphere;
    00218     for(int i=0; i<actorQueue()->size(); ++i)
    00219       world_bounding_sphere += actorQueue()->at(i)->boundingSphere();
    00220
    00221     // compute the optimized
    00222     camera()->computeNearFarOptimizedProjMatrix(world_bounding_sphere);
    00223
    00224     // recompute frustum planes to account for new near/far values
    00225     camera()->computeFrustumPlanes();
    00226   }
    00227
    00228   // render queue filling
    00229
    00230   renderQueue()->clear();
    00231
    00232   fillRenderQueue( actorQueue() );
    00233
    00234   // sort the rendering queue according to this renderer sorting algorithm
    00235
    00236   if (renderQueueSorter())
    00237     renderQueue()->sort( renderQueueSorter(), camera() );
    00238
    00239   // --- RENDER THE QUEUE: loop through the renderers, feeding the output of one as input for the next ---
    00240
    00241   const RenderQueue* render_queue = renderQueue();
    00242   for(size_t i=0; i<renderers().size(); ++i)
    00243   {
    00244     if (renderers()[i])
    00245     {
    00246       if (renderers()[i]->renderTarget() == NULL)
    00247       {
    00248         vl::Log::error( Say("Rendering::render(): no RendererTarget specified for Renderer #%n!\n") << i );
    00249         VL_TRAP();
    00250         continue;
    00251       }
    00252       if (renderers()[i]->renderTarget()->openglContext() == NULL)
    00253       {
    00254         vl::Log::error( Say("Rendering::render(): invalid RenderTarget for Renderer #%n, OpenGLContext is NULL!\n") << i );
    00255         VL_TRAP();
    00256         continue;
    00257       }
    00258       // loop the rendering
    00259       render_queue = renderers()[i]->render( render_queue, camera(), frameClock() );
    00260     }
    00261   }
    00262
    00263   VL_CHECK_OGL()
    00264 }
    00265 //------------------------------------------------------------------------------
    00266 void Rendering::fillRenderQueue( ActorCollection* actor_list )
    00267 {
    00268   if (actor_list == NULL)
    00269     return;
    00270
    00271   if (actor_list->empty())
    00272     return;
    00273
    00274   if (camera() == NULL)
    00275     return;
    00276
    00277   if (enableMask() == 0)
    00278     return;
    00279
    00280   RenderQueue* list = renderQueue();
    00281   std::set<Shader*> shader_set;
    00282
    00283   // iterate actor list
    00284
    00285   for(int iactor=0; iactor < actor_list->size(); iactor++)
    00286   {
    00287     Actor* actor = actor_list->at(iactor);
    00288
    00289     VL_CHECK(actor->lod(0))
    00290
    00291     if ( !isEnabled(actor->enableMask()) )
    00292       continue;
    00293
    00294     // update the Actor's bounds
    00295     actor->computeBounds();
    00296
    00297     Effect* effect = actor->effect();
    00298     VL_CHECK(effect)
    00299
    00300     // effect override
    00301
    00302     for( std::map< unsigned int, ref<Effect> >::const_iterator eom_it = mEffectOverrideMask.begin();
    00303          eom_it != mEffectOverrideMask.end();
    00304          ++eom_it )
    00305     {
    00306       if (eom_it->first & actor->enableMask())
    00307         effect = eom_it->second.get();
    00308     }
    00309
    00310     if ( !isEnabled(effect->enableMask()) )
    00311       continue;
    00312
    00313     // --------------- LOD evaluation ---------------
    00314
    00315     int effect_lod = effect->evaluateLOD( actor, camera() );
    00316
    00317     int geometry_lod = 0;
    00318     if ( evaluateLOD() )
    00319       geometry_lod = actor->evaluateLOD( camera() );
    00320
    00321     // --------------- M U L T I   P A S S I N G ---------------
    00322
    00323     RenderToken* prev_pass = NULL;
    00324     const int pass_count = effect->lod(effect_lod)->size();
    00325     for(int ipass=0; ipass<pass_count; ++ipass)
    00326     {
    00327       // setup the shader to be used for this pass
    00328
    00329       Shader* shader = effect->lod(effect_lod)->at(ipass);
    00330
    00331       // --------------- fill render token ---------------
    00332
    00333       // create a render token
    00334       RenderToken* tok = list->newToken(prev_pass != NULL);
    00335
    00336       // multipass chain: implemented as a linked list
    00337       if ( prev_pass != NULL )
    00338         prev_pass->mNextPass = tok;
    00339       prev_pass = tok;
    00340       tok->mNextPass = NULL;
    00341       // track the current state
    00342       tok->mActor = actor;
    00343       tok->mRenderable = actor->lod(geometry_lod).get();
    00344       // set the shader used (multipassing shader or effect->shader())
    00345       tok->mShader = shader;
    00346
    00347       if ( shaderAnimationEnabled() )
    00348       {
    00349         VL_CHECK(frameClock() >= 0)
    00350         if( frameClock() >= 0 )
    00351         {
    00352           // note that the condition is != as opposed to <
    00353           if ( shader->lastUpdateTime() != frameClock() && shader->shaderAnimator() && shader->shaderAnimator()->isEnabled() )
    00354           {
    00355             // update
    00356             shader->shaderAnimator()->updateShader( shader, camera(), frameClock() );
    00357
    00358             // note that we update this after
    00359             shader->setLastUpdateTime( frameClock() );
    00360           }
    00361         }
    00362       }
    00363
    00364       if ( automaticResourceInit() && shader_set.find(shader) == shader_set.end() )
    00365       {
    00366         shader_set.insert(shader);
    00367
    00368         // link GLSLProgram
    00369         if (shader->glslProgram())
    00370         {
    00371           shader->glslProgram()->linkProgram();
    00372           VL_CHECK( shader->glslProgram()->linked() );
    00373         }
    00374
    00375         // lazy texture creation
    00376         if ( shader->gocRenderStateSet() )
    00377         {
    00378           const std::vector< ref<RenderState> >& states = shader->gocRenderStateSet()->renderStates();
    00379           for( size_t i=0; i<states.size(); ++i )
    00380           {
    00381             if (states[i]->type() >= RS_TextureUnit0 && states[i]->type() < RS_TextureUnit0+VL_MAX_TEXTURE_UNITS)
    00382             {
    00383               TextureUnit* tex_unit = dynamic_cast<TextureUnit*>( states[i].get() );
    00384               VL_CHECK(tex_unit);
    00385               if (tex_unit)
    00386               {
    00387                 if (tex_unit->texture() && tex_unit->texture()->setupParams())
    00388                   tex_unit->texture()->createTexture();
    00389               }
    00390             }
    00391           }
    00392
    00393         }
    00394       }
    00395
    00396       tok->mEffectRenderRank = effect->renderRank();
    00397     }
    00398   }
    00399 }
    00400 //------------------------------------------------------------------------------

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.