source: OGRE/trunk/ogrenew/OgreMain/src/OgreCompositorChain.cpp @ 692

Revision 692, 12.6 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreCompositorChain.h"
27#include "OgreCompositionTechnique.h"
28#include "OgreCompositorInstance.h"
29#include "OgreViewport.h"
30#include "OgreCamera.h"
31#include "OgreRenderTarget.h"
32#include "OgreLogManager.h"
33#include "OgreCompositorManager.h"
34#include "OgreSceneManager.h"
35#include "OgreRenderQueueInvocation.h"
36namespace Ogre {
37CompositorChain::CompositorChain(Viewport *vp):
38    mViewport(vp),
39        mOriginalScene(0),
40    mDirty(true),
41        mAnyCompositorsEnabled(false)
42{
43        mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
44    assert(mViewport);
45}
46//-----------------------------------------------------------------------
47CompositorChain::~CompositorChain()
48{
49        destroyResources();
50}
51//-----------------------------------------------------------------------
52void CompositorChain::destroyResources(void)
53{
54        if (mViewport)
55        {
56                removeAllCompositors();
57                mViewport->getTarget()->removeListener(this);
58                /// Destroy "original scene" compositor instance
59                mOriginalScene->getTechnique()->destroyInstance(mOriginalScene);
60                mViewport = 0;
61        }
62}
63//-----------------------------------------------------------------------
64CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, size_t technique)
65{
66        // Init on demand
67        if (!mOriginalScene)
68        {
69                mViewport->getTarget()->addListener(this);
70               
71                /// Create base "original scene" compositor
72                CompositorPtr base = CompositorManager::getSingleton().load("Ogre/Scene",
73                        ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
74                mOriginalScene = base->getSupportedTechnique(0)->createInstance(this);
75        }
76
77
78        filter->touch();
79    if(technique >= filter->getNumSupportedTechniques())
80    {
81        /// Warn user
82        LogManager::getSingleton().logMessage(
83            "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
84        );
85        return 0;
86    }
87    CompositionTechnique *tech = filter->getSupportedTechnique(technique);
88    CompositorInstance *t = tech->createInstance(this);
89   
90    if(addPosition == LAST)
91        addPosition = mInstances.size();
92    else
93        assert(addPosition <= mInstances.size() && "Index out of bounds.");
94    mInstances.insert(mInstances.begin()+addPosition, t);
95   
96    mDirty = true;
97        mAnyCompositorsEnabled = true;
98    return t;
99}
100//-----------------------------------------------------------------------
101void CompositorChain::removeCompositor(size_t index)
102{
103    assert (index < mInstances.size() && "Index out of bounds.");
104    Instances::iterator i = mInstances.begin() + index;
105    (*i)->getTechnique()->destroyInstance(*i);
106    mInstances.erase(i);
107   
108    mDirty = true;
109}
110//-----------------------------------------------------------------------
111size_t CompositorChain::getNumCompositors()
112{
113    return mInstances.size();
114}
115//-----------------------------------------------------------------------
116void CompositorChain::removeAllCompositors()
117{
118    Instances::iterator i, iend;
119    iend = mInstances.end();
120    for (i = mInstances.begin(); i != iend; ++i)
121    {
122        (*i)->getTechnique()->destroyInstance(*i);
123    }
124    mInstances.clear();
125   
126    mDirty = true;
127}
128//-----------------------------------------------------------------------
129void CompositorChain::_removeInstance(CompositorInstance *i)
130{
131        mInstances.erase(std::find(mInstances.begin(), mInstances.end(), i));
132        i->getTechnique()->destroyInstance(i);
133}
134//-----------------------------------------------------------------------
135CompositorInstance *CompositorChain::getCompositor(size_t index)
136{
137    assert (index < mInstances.size() && "Index out of bounds.");
138    return mInstances[index];
139}
140
141//-----------------------------------------------------------------------
142CompositorChain::InstanceIterator CompositorChain::getCompositors()
143{
144    return InstanceIterator(mInstances.begin(), mInstances.end());
145}
146//-----------------------------------------------------------------------
147void CompositorChain::setCompositorEnabled(size_t position, bool state)
148{
149    getCompositor(position)->setEnabled(state);
150}
151//-----------------------------------------------------------------------
152void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
153{
154        /// Compile if state is dirty
155        if(mDirty)
156                _compile();
157
158        // Do nothing if no compositors enabled
159        if (!mAnyCompositorsEnabled)
160        {
161                return;
162        }
163
164
165        /// Update dependent render targets; this is done in the preRenderTarget
166        /// and not the preViewportUpdate for a reason: at this time, the
167        /// target Rendertarget will not yet have been set as current.
168        /// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
169        /// order would be screwed up and problems would arise with copying rendertextures.
170    Camera *cam = mViewport->getCamera();
171    /// Iterate over compiled state
172    CompositorInstance::CompiledState::iterator i;
173    for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
174    {
175                /// Skip if this is a target that should only be initialised initially
176                if(i->onlyInitial && i->hasBeenRendered)
177                        continue;
178                i->hasBeenRendered = true;
179                /// Setup and render
180        preTargetOperation(*i, i->target->getViewport(0), cam);
181        i->target->update();
182        postTargetOperation(*i, i->target->getViewport(0), cam);
183    }
184}
185//-----------------------------------------------------------------------
186void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
187{
188        // Only set up if there is at least one compositor enabled, and it's this viewport
189    if(evt.source != mViewport || !mAnyCompositorsEnabled)
190        return;
191
192        Camera *cam = mViewport->getCamera();
193        /// Prepare for output operation
194        preTargetOperation(mOutputOperation, mViewport, cam);
195}
196//-----------------------------------------------------------------------
197void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
198{
199    SceneManager *sm = cam->getSceneManager();
200        /// Set up render target listener
201        mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
202        /// Register it
203        sm->addRenderQueueListener(&mOurListener);
204        /// Set visiblity mask
205        mOldVisibilityMask = sm->getVisibilityMask();
206        sm->setVisibilityMask(op.visibilityMask);
207        /// Set whether we find visibles
208        mOldFindVisibleObjects = sm->getFindVisibleObjects();
209        sm->setFindVisibleObjects(op.findVisibleObjects);
210    /// Set LOD bias level
211    mOldLodBias = cam->getLodBias();
212    cam->setLodBias(cam->getLodBias() * op.lodBias);
213        /// Set material scheme
214        mOldMaterialScheme = vp->getMaterialScheme();
215        vp->setMaterialScheme(op.materialScheme);
216    /// XXX TODO
217    //vp->setClearEveryFrame( true );
218    //vp->setOverlaysEnabled( false );
219    //vp->setBackgroundColour( op.clearColour );
220}
221//-----------------------------------------------------------------------
222void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
223{
224    SceneManager *sm = cam->getSceneManager();
225        /// Unregister our listener
226        sm->removeRenderQueueListener(&mOurListener);
227        /// Flush remaing operations
228        mOurListener.flushUpTo((uint8)RENDER_QUEUE_COUNT);
229        /// Restore default scene and camera settings
230        sm->setVisibilityMask(mOldVisibilityMask);
231        sm->setFindVisibleObjects(mOldFindVisibleObjects);
232    cam->setLodBias(mOldLodBias);
233        vp->setMaterialScheme(mOldMaterialScheme);
234}
235//-----------------------------------------------------------------------
236void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
237{
238        // Only tidy up if there is at least one compositor enabled, and it's this viewport
239    if(evt.source != mViewport || !mAnyCompositorsEnabled)
240        return;
241
242        postTargetOperation(mOutputOperation, mViewport, mViewport->getCamera());
243}
244//-----------------------------------------------------------------------
245void CompositorChain::viewportRemoved(const RenderTargetViewportEvent& evt)
246{
247        // this chain is now orphaned
248        // can't delete it since held from outside, but release all resources being used
249        destroyResources();
250
251}
252//-----------------------------------------------------------------------
253void CompositorChain::_compile()
254{
255        bool compositorsEnabled = false;
256
257    /// Set previous CompositorInstance for each compositor in the list
258    CompositorInstance *lastComposition = mOriginalScene;
259        mOriginalScene->mPreviousInstance = 0;
260    for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
261    {
262        if((*i)->getEnabled())
263        {
264                        compositorsEnabled = true;
265            (*i)->mPreviousInstance = lastComposition;
266            lastComposition = (*i);
267        }
268    }
269   
270    /// Clear compiled state
271    mCompiledState.clear();
272    mOutputOperation = CompositorInstance::TargetOperation(0);
273
274    /// Compile misc targets
275    lastComposition->_compileTargetOperations(mCompiledState);
276   
277    /// Final target viewport (0)
278    lastComposition->_compileOutputOperation(mOutputOperation);
279
280        // Deal with viewport settings
281        if (compositorsEnabled != mAnyCompositorsEnabled)
282        {
283                mAnyCompositorsEnabled = compositorsEnabled;
284                if (mAnyCompositorsEnabled)
285                {
286                        // Save old viewport clearing options
287                        mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
288                        // Don't clear anything every frame since we have our own clear ops
289                        mViewport->setClearEveryFrame(false);
290                }
291                else
292                {
293                        // Reset clearing options
294                        mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
295                                mOldClearEveryFrameBuffers);
296                }
297        }
298   
299    mDirty = false;
300}
301//-----------------------------------------------------------------------
302void CompositorChain::_markDirty()
303{
304    mDirty = true;
305}
306//-----------------------------------------------------------------------
307Viewport *CompositorChain::getViewport()
308{
309    return mViewport;
310}
311//-----------------------------------------------------------------------
312void CompositorChain::RQListener::renderQueueStarted(uint8 id,
313        const String& invocation, bool& skipThisQueue)
314{
315        // Skip shadows invocation, since this is nested within main viewport update
316        if (invocation == RenderQueueInvocation::RENDER_QUEUE_INVOCATION_SHADOWS)
317                return;
318
319        flushUpTo(id);
320        /// If noone wants to render this queue, skip it
321        /// Don't skip the OVERLAY queue because that's handled seperately
322        if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
323        {
324                skipThisQueue = true;
325        }
326}
327//-----------------------------------------------------------------------
328void CompositorChain::RQListener::renderQueueEnded(uint8 id,
329        const String& invocation, bool& repeatThisQueue)
330{
331}
332//-----------------------------------------------------------------------
333void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
334{
335        mOperation = op;
336        mSceneManager = sm;
337        mRenderSystem = rs;
338        currentOp = op->renderSystemOperations.begin();
339        lastOp = op->renderSystemOperations.end();
340}
341//-----------------------------------------------------------------------
342void CompositorChain::RQListener::flushUpTo(uint8 id)
343{
344        /// Process all RenderSystemOperations up to and including render queue id.
345    /// Including, because the operations for RenderQueueGroup x should be executed
346        /// at the beginning of the RenderQueueGroup render for x.
347        while(currentOp != lastOp && currentOp->first <= id)
348        {
349                currentOp->second->execute(mSceneManager, mRenderSystem);
350                ++currentOp;
351        }
352}
353//-----------------------------------------------------------------------
354}
Note: See TracBrowser for help on using the repository browser.