Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/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: select the first that matches
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       {
00312         effect = eom_it->second.get();
00313         break;
00314       }
00315     }
00316 
00317     if ( !isEnabled(effect->enableMask()) )
00318       continue;
00319 
00320     // --------------- LOD evaluation ---------------
00321 
00322     int effect_lod = effect->evaluateLOD( actor, camera() );
00323 
00324     int geometry_lod = 0;
00325     if ( evaluateLOD() )
00326       geometry_lod = actor->evaluateLOD( camera() );
00327 
00328     // --------------- M U L T I   P A S S I N G ---------------
00329 
00330     RenderToken* prev_pass = NULL;
00331     const int pass_count = effect->lod(effect_lod)->size();
00332     for(int ipass=0; ipass<pass_count; ++ipass)
00333     {
00334       // setup the shader to be used for this pass
00335 
00336       Shader* shader = effect->lod(effect_lod)->at(ipass);
00337 
00338       // --------------- fill render token ---------------
00339 
00340       // create a render token
00341       RenderToken* tok = list->newToken(prev_pass != NULL);
00342 
00343       // multipass chain: implemented as a linked list
00344       if ( prev_pass != NULL )
00345         prev_pass->mNextPass = tok;
00346       prev_pass = tok;
00347       tok->mNextPass = NULL;
00348       // track the current state
00349       tok->mActor = actor;
00350       tok->mRenderable = actor->lod(geometry_lod);
00351       // set the shader used (multipassing shader or effect->shader())
00352       tok->mShader = shader;
00353 
00354       if ( shaderAnimationEnabled() )
00355       {
00356         VL_CHECK(frameClock() >= 0)
00357         if( frameClock() >= 0 )
00358         {
00359           // note that the condition is != as opposed to <
00360           if ( shader->lastUpdateTime() != frameClock() && shader->shaderAnimator() && shader->shaderAnimator()->isEnabled() )
00361           {
00362             // update
00363             shader->shaderAnimator()->updateShader( shader, camera(), frameClock() );
00364 
00365             // note that we update this after
00366             shader->setLastUpdateTime( frameClock() );
00367           }
00368         }
00369       }
00370 
00371       if ( automaticResourceInit() && shader_set.find(shader) == shader_set.end() )
00372       {
00373         shader_set.insert(shader);
00374 
00375         // link GLSLProgram
00376         if (shader->glslProgram() && !shader->glslProgram()->linked())
00377         {
00378           shader->glslProgram()->linkProgram();
00379           VL_CHECK( shader->glslProgram()->linked() );
00380         }
00381 
00382         // lazy texture creation
00383         if ( shader->gocRenderStateSet() )
00384         {
00385           size_t count = shader->gocRenderStateSet()->renderStatesCount();
00386           RenderStateSlot* states = shader->gocRenderStateSet()->renderStates();
00387           for( size_t i=0; i<count; ++i )
00388           {
00389             if (states[i].mRS->type() == RS_TextureSampler)
00390             {
00391               TextureSampler* tex_unit = static_cast<TextureSampler*>( states[i].mRS.get() );
00392               VL_CHECK(tex_unit);
00393               if (tex_unit)
00394               {
00395                 if (tex_unit->texture() && tex_unit->texture()->setupParams())
00396                   tex_unit->texture()->createTexture();
00397               }
00398             }
00399           }
00400           
00401         }
00402       }
00403 
00404       tok->mEffectRenderRank = effect->renderRank();
00405     }
00406   }
00407 }
00408 //------------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:40.
Permission is granted to use this page to write and publish articles regarding Visualization Library.