Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreCompositorInstance.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

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