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

Revision 692, 18.2 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 "OgreCompositorInstance.h"
27#include "OgreCompositorChain.h"
28#include "OgreCompositorManager.h"
29#include "OgreCompositionTargetPass.h"
30#include "OgreCompositionPass.h"
31#include "OgreCompositionTechnique.h"
32#include "OgreTechnique.h"
33#include "OgrePass.h"
34#include "OgreTexture.h"
35#include "OgreLogManager.h"
36#include "OgreMaterialManager.h"
37#include "OgreTextureManager.h"
38#include "OgreSceneManager.h"
39#include "OgreStringConverter.h"
40#include "OgreException.h"
41#include "OgreHardwarePixelBuffer.h"
42#include "OgreCamera.h"
43
44namespace Ogre {
45CompositorInstance::CompositorInstance(Compositor *filter, CompositionTechnique *technique,
46    CompositorChain *chain):
47    mCompositor(filter), mTechnique(technique), mChain(chain),
48                mEnabled(false)
49{
50}
51//-----------------------------------------------------------------------
52CompositorInstance::~CompositorInstance()
53{
54        clearCompilationState();
55    freeResources();
56}
57//-----------------------------------------------------------------------
58void CompositorInstance::setEnabled(bool value)
59{
60    if (mEnabled != value)
61    {
62        mEnabled = value;
63
64        // Create of free resource.
65        if (value)
66        {
67            createResources();
68        }
69        else
70        {
71            freeResources();
72        }
73
74        /// Notify chain state needs recompile.
75        mChain->_markDirty();
76    }
77}
78//-----------------------------------------------------------------------
79bool CompositorInstance::getEnabled()
80{
81    return mEnabled;
82}
83//-----------------------------------------------------------------------
84
85/** Clear framebuffer RenderSystem operation
86 */
87class RSClearOperation: public CompositorInstance::RenderSystemOperation
88{
89public:
90        RSClearOperation(uint32 buffers, ColourValue colour, Real depth, unsigned short stencil):
91                buffers(buffers), colour(colour), depth(depth), stencil(stencil)
92        {}
93        /// Which buffers to clear (FrameBufferType)
94        uint32 buffers;
95        /// Colour to clear in case FBT_COLOUR is set
96        ColourValue colour;
97        /// Depth to set in case FBT_DEPTH is set
98        Real depth;
99        /// Stencil value to set in case FBT_STENCIL is set
100        unsigned short stencil;
101
102        virtual void execute(SceneManager *sm, RenderSystem *rs)
103        {
104                rs->clearFrameBuffer(buffers, colour, depth, stencil);
105        }
106};
107
108/** "Set stencil state" RenderSystem operation
109 */
110class RSStencilOperation: public CompositorInstance::RenderSystemOperation
111{
112public:
113        RSStencilOperation(bool stencilCheck,CompareFunction func,uint32 refValue,uint32 mask,
114                StencilOperation stencilFailOp,StencilOperation depthFailOp,StencilOperation passOp,
115                bool twoSidedOperation):
116                stencilCheck(stencilCheck),func(func),refValue(refValue),mask(mask),
117                stencilFailOp(stencilFailOp),depthFailOp(depthFailOp),passOp(passOp),
118                twoSidedOperation(twoSidedOperation)
119        {}
120        bool stencilCheck;
121        CompareFunction func;
122    uint32 refValue;
123        uint32 mask;
124    StencilOperation stencilFailOp;
125    StencilOperation depthFailOp;
126    StencilOperation passOp;
127    bool twoSidedOperation;
128
129        virtual void execute(SceneManager *sm, RenderSystem *rs)
130        {
131                rs->setStencilCheckEnabled(stencilCheck);
132                rs->setStencilBufferParams(func, refValue, mask, stencilFailOp, depthFailOp, passOp, twoSidedOperation);
133        }
134};
135
136/** "Render quad" RenderSystem operation
137 */
138class RSQuadOperation: public CompositorInstance::RenderSystemOperation
139{
140public:
141        RSQuadOperation(CompositorInstance *instance, uint32 pass_id, MaterialPtr mat):
142          mat(mat),instance(instance), pass_id(pass_id)
143        {
144                mat->load();
145                instance->_fireNotifyMaterialSetup(pass_id, mat);
146                technique = mat->getTechnique(0);
147                assert(technique);
148        }
149        MaterialPtr mat;
150        Technique *technique;
151        CompositorInstance *instance;
152        uint32 pass_id;
153
154        virtual void execute(SceneManager *sm, RenderSystem *rs)
155        {
156                // Fire listener
157                instance->_fireNotifyMaterialRender(pass_id, mat);
158                // Queue passes from mat
159                Technique::PassIterator i = technique->getPassIterator();
160                while(i.hasMoreElements())
161                {
162                        sm->_injectRenderWithPass(i.getNext(), CompositorManager::getSingleton()._getTexturedRectangle2D());
163                }
164        }
165};
166
167void CompositorInstance::collectPasses(TargetOperation &finalState, CompositionTargetPass *target)
168{
169        /// Here, passes are converted into render target operations
170    Pass *targetpass;
171    Technique *srctech;
172        MaterialPtr mat, srcmat;
173       
174    CompositionTargetPass::PassIterator it = target->getPassIterator();
175    while(it.hasMoreElements())
176    {
177        CompositionPass *pass = it.getNext();
178        switch(pass->getType())
179        {
180        case CompositionPass::PT_CLEAR:
181                        queueRenderSystemOp(finalState, new RSClearOperation(
182                                pass->getClearBuffers(),
183                                pass->getClearColour(),
184                                pass->getClearDepth(),
185                                pass->getClearStencil()
186                                ));
187            break;
188                case CompositionPass::PT_STENCIL:
189                        queueRenderSystemOp(finalState, new RSStencilOperation(
190                                pass->getStencilCheck(),pass->getStencilFunc(), pass->getStencilRefValue(),
191                                pass->getStencilMask(), pass->getStencilFailOp(), pass->getStencilDepthFailOp(),
192                                pass->getStencilPassOp(), pass->getStencilTwoSidedOperation()
193                                ));
194            break;
195        case CompositionPass::PT_RENDERSCENE:
196                        if(pass->getFirstRenderQueue() < finalState.currentQueueGroupID)
197                        {
198                                /// Mismatch -- warn user
199                                /// XXX We could support repeating the last queue, with some effort
200                                LogManager::getSingleton().logMessage("Warning in compilation of Compositor "
201                                        +mCompositor->getName()+": Attempt to render queue "+
202                                        StringConverter::toString(pass->getFirstRenderQueue())+" before "+
203                                        StringConverter::toString(finalState.currentQueueGroupID));
204                        }
205                        /// Add render queues
206                        for(int x=pass->getFirstRenderQueue(); x<=pass->getLastRenderQueue(); ++x)
207                        {
208                                assert(x>=0);
209                                finalState.renderQueues.set(x);
210                        }
211                        finalState.currentQueueGroupID = pass->getLastRenderQueue()+1;
212                        finalState.findVisibleObjects = true;
213                        finalState.materialScheme = target->getMaterialScheme();
214
215            break;
216        case CompositionPass::PT_RENDERQUAD:
217            srcmat = pass->getMaterial();
218                        if(srcmat.isNull())
219            {
220                /// No material -- warn user
221                                LogManager::getSingleton().logMessage("Warning in compilation of Compositor "
222                                        +mCompositor->getName()+": No material defined for composition pass");
223                break;
224            }
225                        srcmat->load();
226                        if(srcmat->getNumSupportedTechniques()==0) 
227                        {
228                                /// No supported techniques -- warn user
229                                LogManager::getSingleton().logMessage("Warning in compilation of Compositor "
230                                        +mCompositor->getName()+": material "+srcmat->getName()+" has no supported techniques");
231                break;
232                        }
233                        srctech = srcmat->getBestTechnique(0);
234                        /// Create local material
235                        MaterialPtr mat = createLocalMaterial();
236                        /// Copy and adapt passes from source material
237                        Technique::PassIterator i = srctech->getPassIterator();
238                        while(i.hasMoreElements())
239                        {
240                                Pass *srcpass = i.getNext();
241                                /// Create new target pass
242                                targetpass = mat->getTechnique(0)->createPass();
243                                (*targetpass) = (*srcpass);
244                                /// Set up inputs
245                                for(size_t x=0; x<pass->getNumInputs(); ++x)
246                                {
247                                        String inp = pass->getInput(x);
248                                        if(!inp.empty())
249                                        {
250                                                if(x < targetpass->getNumTextureUnitStates())
251                                                {
252                                                        targetpass->getTextureUnitState((ushort)x)->setTextureName(getSourceForTex(inp));
253                                                }
254                                                else
255                                                {
256                                                        /// Texture unit not there
257                                                        LogManager::getSingleton().logMessage("Warning in compilation of Compositor "
258                                                                +mCompositor->getName()+": material "+srcmat->getName()+" texture unit "
259                                                                +StringConverter::toString(x)+" out of bounds");
260                                                }
261                                        }
262                                }
263                        }
264                        queueRenderSystemOp(finalState, new RSQuadOperation(this,pass->getIdentifier(),mat));
265            break;
266        }
267    }
268}
269//-----------------------------------------------------------------------
270void CompositorInstance::_prepareForCompilation()
271{
272        clearCompilationState();
273}
274//-----------------------------------------------------------------------
275void CompositorInstance::_compileTargetOperations(CompiledState &compiledState)
276{
277    /// Collect targets of previous state
278        if(mPreviousInstance)
279            mPreviousInstance->_compileTargetOperations(compiledState);
280    /// Texture targets
281    CompositionTechnique::TargetPassIterator it = mTechnique->getTargetPassIterator();
282    while(it.hasMoreElements())
283    {
284        CompositionTargetPass *target = it.getNext();
285       
286        TargetOperation ts(getTargetForTex(target->getOutputName()));
287        /// Set "only initial" flag, visibilityMask and lodBias according to CompositionTargetPass.
288        ts.onlyInitial = target->getOnlyInitial();
289        ts.visibilityMask = target->getVisibilityMask();
290        ts.lodBias = target->getLodBias();
291        /// Check for input mode previous
292        if(target->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
293        {
294            /// Collect target state for previous compositor
295            /// The TargetOperation for the final target is collected seperately as it is merged
296            /// with later operations
297            mPreviousInstance->_compileOutputOperation(ts);
298        }
299        /// Collect passes of our own target
300        collectPasses(ts, target);
301        compiledState.push_back(ts);
302    }
303}
304//-----------------------------------------------------------------------
305void CompositorInstance::_compileOutputOperation(TargetOperation &finalState)
306{
307    /// Final target
308    CompositionTargetPass *tpass = mTechnique->getOutputTargetPass();
309   
310    /// Logical-and together the visibilityMask, and multiply the lodBias
311    finalState.visibilityMask &= tpass->getVisibilityMask();
312    finalState.lodBias *= tpass->getLodBias();
313   
314    if(tpass->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
315    {
316        /// Collect target state for previous compositor
317        /// The TargetOperation for the final target is collected seperately as it is merged
318        /// with later operations
319        mPreviousInstance->_compileOutputOperation(finalState);
320    }
321    /// Collect passes
322    collectPasses(finalState, tpass);
323}
324//-----------------------------------------------------------------------
325Compositor *CompositorInstance::getCompositor()
326{
327    return mCompositor;
328}
329//-----------------------------------------------------------------------
330CompositionTechnique *CompositorInstance::getTechnique()
331{
332    return mTechnique;
333}
334//-----------------------------------------------------------------------
335CompositorChain *CompositorInstance::getChain()
336{
337        return mChain;
338}
339//-----------------------------------------------------------------------
340MaterialPtr CompositorInstance::createLocalMaterial()
341{
342static size_t dummyCounter = 0;
343    MaterialPtr mat =
344        MaterialManager::getSingleton().create(
345            "CompositorInstanceMaterial"+StringConverter::toString(dummyCounter),
346            ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME
347        );
348    ++dummyCounter;
349    /// This is safe, as we hold a private reference
350    /// XXX does not compile due to ResourcePtr conversion :
351    ///     MaterialManager::getSingleton().remove(mat);
352    MaterialManager::getSingleton().remove(mat->getName());
353    /// Remove all passes from first technique
354    mat->getTechnique(0)->removeAllPasses();
355    return mat;
356}
357//-----------------------------------------------------------------------
358void CompositorInstance::createResources()
359{
360static size_t dummyCounter = 0;
361    freeResources();
362    /// Create temporary textures
363    /// In principle, temporary textures could be shared between multiple viewports
364    /// (CompositorChains). This will save a lot of memory in case more viewports
365    /// are composited.
366    CompositionTechnique::TextureDefinitionIterator it = mTechnique->getTextureDefinitionIterator();
367    while(it.hasMoreElements())
368    {
369        CompositionTechnique::TextureDefinition *def = it.getNext();
370        /// Determine width and height
371        size_t width = def->width;
372        size_t height = def->height;
373        if(width == 0)
374            width = mChain->getViewport()->getActualWidth();
375        if(height == 0)
376            height = mChain->getViewport()->getActualHeight();
377        /// Make the tetxure
378        TexturePtr tex = TextureManager::getSingleton().createManual(
379            "CompositorInstanceTexture"+StringConverter::toString(dummyCounter),
380            ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
381            (uint)width, (uint)height, 0, def->format, TU_RENDERTARGET );   
382        ++dummyCounter;
383        mLocalTextures[def->name] = tex;
384       
385        /// Set up viewport over entire texture
386        RenderTexture *rtt = tex->getBuffer()->getRenderTarget();
387        rtt->setAutoUpdated( false );
388
389        Camera* camera = mChain->getViewport()->getCamera();
390
391        // Save last viewport and current aspect ratio
392        Viewport* oldViewport = camera->getViewport();
393        Real aspectRatio = camera->getAspectRatio();
394
395        Viewport* v = rtt->addViewport( camera );
396        v->setClearEveryFrame( false );
397        v->setOverlaysEnabled( false );
398        v->setBackgroundColour( ColourValue( 0, 0, 0, 0 ) );
399
400        // Should restore aspect ratio, in case of auto aspect ratio
401        // enabled, it'll changed when add new viewport.
402        camera->setAspectRatio(aspectRatio);
403        // Should restore last viewport, i.e. never disturb user code
404        // which might based on that.
405        camera->_notifyViewport(oldViewport);
406    }
407   
408}
409//-----------------------------------------------------------------------
410void CompositorInstance::freeResources()
411{
412    /// Remove temporary textures
413    /// LocalTextureMap mLocalTextures;
414    LocalTextureMap::iterator i, iend=mLocalTextures.end();
415    for(i=mLocalTextures.begin(); i!=iend; ++i)
416    {
417        TextureManager::getSingleton().remove(i->second->getName());
418    }
419    mLocalTextures.clear();
420}
421//-----------------------------------------------------------------------
422RenderTarget *CompositorInstance::getTargetForTex(const String &name)
423{
424    LocalTextureMap::iterator i = mLocalTextures.find(name);
425    if(i == mLocalTextures.end())
426    {
427        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Non-existent local texture name", "CompositorInstance::getTargetForTex");
428    }
429    return i->second->getBuffer()->getRenderTarget();
430}
431//-----------------------------------------------------------------------
432const String &CompositorInstance::getSourceForTex(const String &name)
433{
434    LocalTextureMap::iterator i = mLocalTextures.find(name);
435    if(i == mLocalTextures.end())
436    {
437        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Non-existent local texture name", "CompositorInstance::getSourceForTex");
438    }
439    return i->second->getName();
440}
441//-----------------------------------------------------------------------
442void CompositorInstance::queueRenderSystemOp(TargetOperation &finalState, RenderSystemOperation *op)
443{
444        /// Store operation for current QueueGroup ID
445        finalState.renderSystemOperations.push_back(RenderSystemOpPair(finalState.currentQueueGroupID, op));
446        /// Save a pointer, so that it will be freed on recompile
447        mRenderSystemOperations.push_back(op);
448}
449//-----------------------------------------------------------------------
450void CompositorInstance::clearCompilationState()
451{
452        RenderSystemOperations::iterator i, iend=mRenderSystemOperations.end();
453    for(i=mRenderSystemOperations.begin(); i!=iend; ++i)
454    {
455                delete (*i);
456    }
457        mRenderSystemOperations.clear();
458}
459//-----------------------------------------------------------------------
460void CompositorInstance::addListener(Listener *l)
461{
462        mListeners.push_back(l);
463}
464//-----------------------------------------------------------------------
465void CompositorInstance::removeListener(Listener *l)
466{
467        mListeners.erase(std::find(mListeners.begin(), mListeners.end(), l));
468}
469//-----------------------------------------------------------------------
470void CompositorInstance::_fireNotifyMaterialSetup(uint32 pass_id, MaterialPtr &mat)
471{
472        Listeners::iterator i, iend=mListeners.end();
473        for(i=mListeners.begin(); i!=iend; ++i)
474                (*i)->notifyMaterialSetup(pass_id, mat);
475}
476//-----------------------------------------------------------------------
477void CompositorInstance::_fireNotifyMaterialRender(uint32 pass_id, MaterialPtr &mat)
478{
479        Listeners::iterator i, iend=mListeners.end();
480        for(i=mListeners.begin(); i!=iend; ++i)
481                (*i)->notifyMaterialRender(pass_id, mat);
482}
483//-----------------------------------------------------------------------
484CompositorInstance::RenderSystemOperation::~RenderSystemOperation()
485{
486}
487//-----------------------------------------------------------------------
488CompositorInstance::Listener::~Listener()
489{
490}
491void CompositorInstance::Listener::notifyMaterialSetup(uint32 pass_id, MaterialPtr &mat)
492{
493}
494void CompositorInstance::Listener::notifyMaterialRender(uint32 pass_id, MaterialPtr &mat)
495{
496}
497//-----------------------------------------------------------------------
498
499}
Note: See TracBrowser for help on using the repository browser.