source: trunk/VUT/work/ogre_changes/OgreMain/include/OgreRenderQueueSortingGrouping.h @ 115

Revision 115, 14.3 KB checked in by mattausch, 19 years ago (diff)

added depth pass algorithm + delayed transparent object rendering (so depth ordering is right)

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#ifndef __RenderQueueSortingGrouping_H__
26#define __RenderQueueSortingGrouping_H__
27
28// Precompiler options
29#include "OgrePrerequisites.h"
30#include "OgreIteratorWrappers.h"
31#include "OgreMaterial.h"
32#include "OgreTechnique.h"
33#include "OgrePass.h"
34#include "OgreMaterialManager.h"
35
36namespace Ogre {
37
38    /** Renderables in the queue grouped by priority.
39    @remarks
40        This class simply groups renderables for rendering. All the
41        renderables contained in this class are destined for the same
42        RenderQueueGroup (coarse groupings like those between the main
43        scene and overlays) and have the same priority (fine groupings
44        for detailed overlap control).
45    @par
46        This class optimises the grouped renderables by sorting them by
47        material to reduce render state changes, and outsorts transparent
48        objects.
49    */
50    class RenderPriorityGroup
51    {
52        /** Internal struct reflecting a single Pass for a Renderable.
53        This is used to sort transparent objects.
54        */
55        struct RenderablePass
56        {
57            /// Pointer to the Renderable details
58            Renderable* renderable;
59            /// Pointer to the Pass
60            Pass* pass;
61
62            RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
63        };
64
65        /// Comparator to order non-transparent object passes
66        struct SolidQueueItemLess
67        {
68            bool _OgreExport operator()(const Pass* a, const Pass* b) const
69            {
70                // Sort by passHash, which is pass, then texture unit changes
71                unsigned long hasha = a->getHash();
72                unsigned long hashb = b->getHash();
73                if (hasha == hashb)
74                {
75                    // Must differentiate by pointer incase 2 passes end up with the same hash
76                    return a < b;
77                }
78                else
79                {
80                    return hasha < hashb;
81                }
82            }
83        };
84        /// Comparator to order transparent object passes
85        struct TransparentQueueItemLess
86        {
87            const Camera* camera;
88            bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
89            {
90                if (a.renderable == b.renderable)
91                {
92                    // Same renderable, sort by pass hash
93                    return a.pass->getHash() < b.pass->getHash();
94                }
95                else
96                {
97                    // Different renderables, sort by depth
98                    Real adepth = a.renderable->getSquaredViewDepth(camera);
99                    Real bdepth = b.renderable->getSquaredViewDepth(camera);
100                                    if (adepth == bdepth)
101                                    {
102                        // Must return deterministic result, doesn't matter what
103                        return a.pass < b.pass;
104                                    }
105                                    else
106                                    {
107                                        // Sort DESCENDING by depth (ie far objects first)
108                                            return (adepth > bdepth);
109                                    }
110                }
111
112            }
113        };
114    public:
115        /** Vector of RenderablePass objects, this is built on the assumption that
116         vectors only ever increase in size, so even if we do clear() the memory stays
117         allocated, ie fast */
118        typedef std::vector<RenderablePass> TransparentRenderablePassList;
119        typedef std::vector<Renderable*> RenderableList;
120        /** Map of pass to renderable lists, used for solid objects since ordering within objects not
121        important. */
122        typedef std::map<Pass*, RenderableList*, SolidQueueItemLess> SolidRenderablePassMap;
123    protected:
124        /// Parent queue group
125        RenderQueueGroup* mParent;
126        bool mSplitPassesByLightingType;
127        bool mSplitNoShadowPasses;
128        /// Solid pass list, used when no shadows, modulative shadows, or ambient passes for additive
129        SolidRenderablePassMap mSolidPasses;
130        /// Solid per-light pass list, used with additive shadows
131        SolidRenderablePassMap mSolidPassesDiffuseSpecular;
132        /// Solid decal (texture) pass list, used with additive shadows
133        SolidRenderablePassMap mSolidPassesDecal;
134        /// Solid pass list, used when shadows are enabled but shadow receive is turned off for these passes
135        SolidRenderablePassMap mSolidPassesNoShadow;
136
137                /// Transparent list
138                TransparentRenderablePassList mTransparentPasses;
139
140        /// Totally empties and destroys a solid pass map
141        void destroySolidPassMap(SolidRenderablePassMap& passmap);
142
143        /// remove a pass entry from all solid pass maps
144        void removeSolidPassEntry(Pass* p);
145
146        /// Clear a solid pass map at the end of a frame
147        void clearSolidPassMap(SolidRenderablePassMap& passmap);
148        /// Internal method for adding a solid renderable
149        void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
150        /// Internal method for adding a solid renderable
151        void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
152        /// Internal method for adding a transparent renderable
153        void addTransparentRenderable(Technique* pTech, Renderable* rend);
154
155    public:
156        RenderPriorityGroup(RenderQueueGroup* parent,
157            bool splitPassesByLightingType, bool splitNoShadowPasses)
158            :mParent(parent), mSplitPassesByLightingType(splitPassesByLightingType),
159            mSplitNoShadowPasses(splitNoShadowPasses) { }
160
161        ~RenderPriorityGroup() {
162            // destroy all the pass map entries
163            destroySolidPassMap(mSolidPasses);
164            destroySolidPassMap(mSolidPassesDecal);
165            destroySolidPassMap(mSolidPassesDiffuseSpecular);
166            destroySolidPassMap(mSolidPassesNoShadow);
167            mTransparentPasses.clear();
168
169        }
170
171        /** Get the collection of solid passes currently queued */
172        const SolidRenderablePassMap& _getSolidPasses(void) const
173        { return mSolidPasses; }
174        /** Get the collection of solid passes currently queued (per-light) */
175        const SolidRenderablePassMap& _getSolidPassesDiffuseSpecular(void) const
176        { return mSolidPassesDiffuseSpecular; }
177        /** Get the collection of solid passes currently queued (decal textures)*/
178        const SolidRenderablePassMap& _getSolidPassesDecal(void) const
179        { return mSolidPassesDecal; }
180        /** Get the collection of solid passes for which shadow receipt is disabled*/
181        const SolidRenderablePassMap& _getSolidPassesNoShadow(void) const
182        { return mSolidPassesNoShadow; }
183        /** Get the collection of transparent passes currently queued */
184        const TransparentRenderablePassList& _getTransparentPasses(void) const
185        { return mTransparentPasses; }
186
187
188        /** Add a renderable to this group. */
189        void addRenderable(Renderable* pRend);
190
191                /** Sorts the objects which have been added to the queue; transparent objects by their
192            depth in relation to the passed in Camera. */
193                void sort(const Camera* cam);
194
195        /** Clears this group of renderables.
196        */
197        void clear(void);
198#ifdef GTP_VISIBILITY_MODIFIED_OGRE
199                /** Clears solids in this group of renderables. Leaves transparents in group.
200        */
201        void clearSolids(void);
202#endif // GTP_VISIBILITY_MODIFIED_OGRE         
203        /** Sets whether or not the queue will split passes by their lighting type,
204        ie ambient, per-light and decal.
205        */
206        void setSplitPassesByLightingType(bool split)
207        {
208            mSplitPassesByLightingType = split;
209        }
210
211        /** Sets whether or not passes which have shadow receive disabled should
212            be separated.
213        */
214        void setSplitNoShadowPasses(bool split)
215        {
216            mSplitNoShadowPasses = split;
217        }
218
219
220    };
221
222
223    /** A grouping level underneath RenderQueue which groups renderables
224    to be issued at coarsely the same time to the renderer.
225    @remarks
226        Each instance of this class itself hold RenderPriorityGroup instances,
227        which are the groupings of renderables by priority for fine control
228        of ordering (not required for most instances).
229    @par
230        This is an internal OGRE class, not intended for apps to use.
231    */
232    class RenderQueueGroup
233    {
234    public:
235        typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
236        typedef MapIterator<PriorityMap> PriorityMapIterator;
237    protected:
238        RenderQueue* mParent;
239        bool mSplitPassesByLightingType;
240        bool mSplitNoShadowPasses;
241        /// Map of RenderPriorityGroup objects
242        PriorityMap mPriorityGroups;
243                /// Whether shadows are enabled for this queue
244                bool mShadowsEnabled;
245
246
247    public:
248                RenderQueueGroup(RenderQueue* parent, bool splitPassesByLightingType,
249            bool splitNoShadowPasses)
250            :mParent(parent), mSplitPassesByLightingType(splitPassesByLightingType),
251            mSplitNoShadowPasses(splitNoShadowPasses), mShadowsEnabled(true) {}
252
253        ~RenderQueueGroup() {
254            // destroy contents now
255            PriorityMap::iterator i;
256            for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
257            {
258                delete i->second;
259            }
260        }
261
262        /** Get an iterator for browsing through child contents. */
263        PriorityMapIterator getIterator(void)
264        {
265            return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
266        }
267
268        /** Add a renderable to this group, with the given priority. */
269        void addRenderable(Renderable* pRend, ushort priority)
270        {
271            // Check if priority group is there
272            PriorityMap::iterator i = mPriorityGroups.find(priority);
273            RenderPriorityGroup* pPriorityGrp;
274            if (i == mPriorityGroups.end())
275            {
276                // Missing, create
277                pPriorityGrp = new RenderPriorityGroup(this,
278                    mSplitPassesByLightingType, mSplitNoShadowPasses);
279                mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
280            }
281            else
282            {
283                pPriorityGrp = i->second;
284            }
285
286            // Add
287            pPriorityGrp->addRenderable(pRend);
288
289        }
290
291        /** Clears this group of renderables.
292        @remarks
293            Doesn't delete any priority groups, just empties them. Saves on
294            memory deallocations since the chances are rougly the same kinds of
295            renderables are going to be sent to the queue again next time.
296        */
297        void clear(void)
298        {
299            PriorityMap::iterator i, iend;
300            iend = mPriorityGroups.end();
301            for (i = mPriorityGroups.begin(); i != iend; ++i)
302            {
303                i->second->clear();
304            }
305
306        }
307#ifdef GTP_VISIBILITY_MODIFIED_OGRE     
308                /** Clears only solid renderables. Leaves transparents in queue. */
309                void clearSolids(void)
310        {
311            PriorityMap::iterator i, iend;
312            iend = mPriorityGroups.end();
313            for (i = mPriorityGroups.begin(); i != iend; ++i)
314            {
315                i->second->clearSolids();
316            }
317        }
318#endif // GTP_VISIBILITY_MODIFIED_OGRE         
319
320                /** Indicate whether a given queue group will be doing any
321                shadow setup.
322                @remarks
323                This method allows you to inform the queue about a queue group, and to
324                indicate whether this group will require shadow processing of any sort.
325                In order to preserve rendering order, OGRE has to treat queue groups
326                as very separate elements of the scene, and this can result in it
327                having to duplicate shadow setup for each group. Therefore, if you
328                know that a group which you are using will never need shadows, you
329                should preregister the group using this method in order to improve
330                the performance.
331                */
332                void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
333
334                /** Are shadows enabled for this queue? */
335                bool getShadowsEnabled(void) const { return mShadowsEnabled; }
336
337        /** Sets whether or not the queue will split passes by their lighting type,
338        ie ambient, per-light and decal.
339        */
340        void setSplitPassesByLightingType(bool split)
341        {
342            mSplitPassesByLightingType = split;
343            PriorityMap::iterator i, iend;
344            iend = mPriorityGroups.end();
345            for (i = mPriorityGroups.begin(); i != iend; ++i)
346            {
347                i->second->setSplitPassesByLightingType(split);
348            }
349        }
350        /** Sets whether or not the queue will split passes which have shadow receive
351        turned off (in their parent material), which is needed when certain shadow
352        techniques are used.
353        */
354        void setSplitNoShadowPasses(bool split)
355        {
356            mSplitNoShadowPasses = split;
357            PriorityMap::iterator i, iend;
358            iend = mPriorityGroups.end();
359            for (i = mPriorityGroups.begin(); i != iend; ++i)
360            {
361                i->second->setSplitNoShadowPasses(split);
362            }
363        }
364
365    };
366
367
368
369}
370
371#endif
372
373
Note: See TracBrowser for help on using the repository browser.