# 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/Rendering.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.org                                               */
    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   super::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]->framebuffer());
    00105       VL_CHECK(mRendering->renderers()[0]->framebuffer()->openglContext());
    00106
    00107       // as stated in the documentation all the renderers must target the same OpenGLContext
    00108       mOpenGLContext = mRendering->renderers()[0]->framebuffer()->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(RCS_RenderingStarted);
    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       // release rendered Actors
    00130       mRendering->actorQueue()->resize(0);
    00131
    00132       // check user-generated errors.
    00133       VL_CHECK_OGL()
    00134
    00135       // render states ]shield[
    00136       mOpenGLContext->resetContextStates(RCS_RenderingFinished);
    00137     }
    00138   } contract(this);
    00139
    00140   // --------------- rendering ---------------
    00141
    00142   if (renderers().empty())
    00143   {
    00144     vl::Log::error("Rendering::render(): no Renderer specified for this Rendering!\n");
    00145     VL_TRAP();
    00146     return;
    00147   }
    00148
    00149   if (!renderers()[0]->framebuffer())
    00150   {
    00151     vl::Log::error("Rendering::render(): no RendererTarget specified for Renderer #0!\n");
    00152     VL_TRAP();
    00153     return;
    00154   }
    00155
    00156   if (!renderers()[0]->framebuffer()->openglContext())
    00157   {
    00158     vl::Log::error("Rendering::render(): invalid Framebuffer for Renderer #0, OpenGLContext is NULL!\n");
    00159     VL_TRAP();
    00160     return;
    00161   }
    00162
    00163   if (sceneManagers()->empty())
    00164     return;
    00165
    00166   if (!camera())
    00167     return;
    00168
    00169   if (!camera()->viewport())
    00170     return;
    00171
    00172   // transform
    00173
    00174   if (transform() != NULL)
    00175     transform()->computeWorldMatrixRecursive( camera() );
    00176
    00177   // camera transform update (can be redundant)
    00178
    00179   if (camera()->boundTransform())
    00180     camera()->setModelingMatrix( camera()->boundTransform()->worldMatrix() );
    00181
    00182   VL_CHECK_OGL()
    00183
    00184   // culling & actor queue filling
    00185
    00186   camera()->computeFrustumPlanes();
    00187
    00188   // if near/far clipping planes optimization is enabled don't perform far-culling
    00189   if (nearFarClippingPlanesOptimized())
    00190   {
    00191     // perform only near culling with plane at distance 0
    00192     camera()->frustum().planes().resize(5);
    00193     camera()->frustum().planes()[4] = Plane( camera()->modelingMatrix().getT(),
    00194                                              camera()->modelingMatrix().getZ());
    00195   }
    00196
    00197   actorQueue()->clear();
    00198   for(int i=0; i<sceneManagers()->size(); ++i)
    00199   {
    00200     if ( isEnabled(sceneManagers()->at(i)->enableMask()) )
    00201     {
    00202       if (cullingEnabled() && sceneManagers()->at(i)->cullingEnabled())
    00203       {
    00204         if (sceneManagers()->at(i)->boundsDirty())
    00205           sceneManagers()->at(i)->computeBounds();
    00206         // try to cull the scene with both bsphere and bbox
    00207         bool visible = !camera()->frustum().cull(sceneManagers()->at(i)->boundingSphere()) &&
    00208                        !camera()->frustum().cull(sceneManagers()->at(i)->boundingBox());
    00209         if ( visible )
    00210           sceneManagers()->at(i)->extractVisibleActors( *actorQueue(), camera() );
    00211       }
    00212       else
    00213         sceneManagers()->at(i)->extractActors( *actorQueue() );
    00214     }
    00215   }
    00216
    00217   // collect near/far clipping planes optimization information
    00218   if (nearFarClippingPlanesOptimized())
    00219   {
    00220     Sphere world_bounding_sphere;
    00221     for(int i=0; i<actorQueue()->size(); ++i)
    00222       world_bounding_sphere += actorQueue()->at(i)->boundingSphere();
    00223
    00224     // compute the optimized
    00225     camera()->computeNearFarOptimizedProjMatrix(world_bounding_sphere);
    00226
    00227     // recompute frustum planes to account for new near/far values
    00228     camera()->computeFrustumPlanes();
    00229   }
    00230
    00231   // render queue filling
    00232
    00233   renderQueue()->clear();
    00234   fillRenderQueue( actorQueue() );
    00235
    00236   // sort the rendering queue according to this renderer sorting algorithm
    00237
    00238   if (renderQueueSorter())
    00239     renderQueue()->sort( renderQueueSorter(), camera() );
    00240
    00241   // --- RENDER THE QUEUE: loop through the renderers, feeding the output of one as input for the next ---
    00242
    00243   const RenderQueue* render_queue = renderQueue();
    00244   for(size_t i=0; i<renderers().size(); ++i)
    00245   {
    00246     if (renderers()[i])
    00247     {
    00248       if (renderers()[i]->framebuffer() == NULL)
    00249       {
    00250         vl::Log::error( Say("Rendering::render(): no RendererTarget specified for Renderer #%n!\n") << i );
    00251         VL_TRAP();
    00252         continue;
    00253       }
    00254
    00255       if (renderers()[i]->framebuffer()->openglContext() == NULL)
    00256       {
    00257         vl::Log::error( Say("Rendering::render(): invalid Framebuffer for Renderer #%n, OpenGLContext is NULL!\n") << i );
    00258         VL_TRAP();
    00259         continue;
    00260       }
    00261
    00262       // loop the rendering
    00263       render_queue = renderers()[i]->render( render_queue, camera(), frameClock() );
    00264     }
    00265   }
    00266
    00267   VL_CHECK_OGL()
    00268 }
    00269 //------------------------------------------------------------------------------
    00270 void Rendering::fillRenderQueue( ActorCollection* actor_list )
    00271 {
    00272   if (actor_list == NULL)
    00273     return;
    00274
    00275   if (actor_list->empty())
    00276     return;
    00277
    00278   if (camera() == NULL)
    00279     return;
    00280
    00281   if (enableMask() == 0)
    00282     return;
    00283
    00284   RenderQueue* list = renderQueue();
    00285   std::set<Shader*> shader_set;
    00286
    00287   // iterate actor list
    00288
    00289   for(int iactor=0; iactor < actor_list->size(); iactor++)
    00290   {
    00291     Actor* actor = actor_list->at(iactor);
    00292
    00293     VL_CHECK(actor->lod(0))
    00294
    00295     if ( !isEnabled(actor->enableMask()) )
    00296       continue;
    00297
    00298     // update the Actor's bounds
    00299     actor->computeBounds();
    00300
    00301     Effect* effect = actor->effect();
    00302     VL_CHECK(effect)
    00303
    00304     // effect override
    00305
    00306     for( std::map< unsigned int, ref<Effect> >::iterator eom_it = mEffectOverrideMask.begin();
    00307          eom_it != mEffectOverrideMask.end();
    00308          ++eom_it )
    00309     {
    00310       if (eom_it->first & actor->enableMask())
    00311         effect = eom_it->second.get();
    00312     }
    00313
    00314     if ( !isEnabled(effect->enableMask()) )
    00315       continue;
    00316
    00317     // --------------- LOD evaluation ---------------
    00318
    00319     int effect_lod = effect->evaluateLOD( actor, camera() );
    00320
    00321     int geometry_lod = 0;
    00322     if ( evaluateLOD() )
    00323       geometry_lod = actor->evaluateLOD( camera() );
    00324
    00325     // --------------- M U L T I   P A S S I N G ---------------
    00326
    00327     RenderToken* prev_pass = NULL;
    00328     const int pass_count = effect->lod(effect_lod)->size();
    00329     for(int ipass=0; ipass<pass_count; ++ipass)
    00330     {
    00331       // setup the shader to be used for this pass
    00332
    00333       Shader* shader = effect->lod(effect_lod)->at(ipass);
    00334
    00335       // --------------- fill render token ---------------
    00336
    00337       // create a render token
    00338       RenderToken* tok = list->newToken(prev_pass != NULL);
    00339
    00340       // multipass chain: implemented as a linked list
    00341       if ( prev_pass != NULL )
    00342         prev_pass->mNextPass = tok;
    00343       prev_pass = tok;
    00344       tok->mNextPass = NULL;
    00345       // track the current state
    00346       tok->mActor = actor;
    00347       tok->mRenderable = actor->lod(geometry_lod);
    00348       // set the shader used (multipassing shader or effect->shader())
    00349       tok->mShader = shader;
    00350
    00351       if ( shaderAnimationEnabled() )
    00352       {
    00353         VL_CHECK(frameClock() >= 0)
    00354         if( frameClock() >= 0 )
    00355         {
    00356           // note that the condition is != as opposed to <
    00357           if ( shader->lastUpdateTime() != frameClock() && shader->shaderAnimator() && shader->shaderAnimator()->isEnabled() )
    00358           {
    00359             // update
    00360             shader->shaderAnimator()->updateShader( shader, camera(), frameClock() );
    00361
    00362             // note that we update this after
    00363             shader->setLastUpdateTime( frameClock() );
    00364           }
    00365         }
    00366       }
    00367
    00368       if ( automaticResourceInit() && shader_set.find(shader) == shader_set.end() )
    00369       {
    00370         shader_set.insert(shader);
    00371
    00372         // link GLSLProgram
    00373         if (shader->glslProgram() && !shader->glslProgram()->linked())
    00374         {
    00375           shader->glslProgram()->linkProgram();
    00376           VL_CHECK( shader->glslProgram()->linked() );
    00377         }
    00378
    00379         // lazy texture creation
    00380         if ( shader->gocRenderStateSet() )
    00381         {
    00382           size_t count = shader->gocRenderStateSet()->renderStatesCount();
    00383           RenderStateSlot* states = shader->gocRenderStateSet()->renderStates();
    00384           for( size_t i=0; i<count; ++i )
    00385           {
    00386             if (states[i].mRS->type() == RS_TextureSampler)
    00387             {
    00388               TextureSampler* tex_unit = static_cast<TextureSampler*>( states[i].mRS.get() );
    00389               VL_CHECK(tex_unit);
    00390               if (tex_unit)
    00391               {
    00392                 if (tex_unit->texture() && tex_unit->texture()->setupParams())
    00393                   tex_unit->texture()->createTexture();
    00394               }
    00395             }
    00396           }
    00397
    00398         }
    00399       }
    00400
    00401       tok->mEffectRenderRank = effect->renderRank();
    00402     }
    00403   }
    00404 }
    00405 //------------------------------------------------------------------------------

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.