source: GTP/trunk/App/Demos/Geom/OgreStuff/include/OgreRenderQueueSortingGrouping.h @ 1092

Revision 1092, 13.9 KB checked in by gumbau, 18 years ago (diff)

LodStrips? and LODTrees demos

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 _OgrePrivate 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
199        /** Sets whether or not the queue will split passes by their lighting type,
200        ie ambient, per-light and decal.
201        */
202        void setSplitPassesByLightingType(bool split)
203        {
204            mSplitPassesByLightingType = split;
205        }
206
207        /** Sets whether or not passes which have shadow receive disabled should
208            be separated.
209        */
210        void setSplitNoShadowPasses(bool split)
211        {
212            mSplitNoShadowPasses = split;
213        }
214
215
216    };
217
218
219    /** A grouping level underneath RenderQueue which groups renderables
220    to be issued at coarsely the same time to the renderer.
221    @remarks
222        Each instance of this class itself hold RenderPriorityGroup instances,
223        which are the groupings of renderables by priority for fine control
224        of ordering (not required for most instances).
225    @par
226        This is an internal OGRE class, not intended for apps to use.
227    */
228    class _OgrePrivate RenderQueueGroup
229    {
230    public:
231        typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
232        typedef MapIterator<PriorityMap> PriorityMapIterator;
233    protected:
234        RenderQueue* mParent;
235        bool mSplitPassesByLightingType;
236        bool mSplitNoShadowPasses;
237        /// Map of RenderPriorityGroup objects
238        PriorityMap mPriorityGroups;
239                /// Whether shadows are enabled for this queue
240                bool mShadowsEnabled;
241
242
243    public:
244                RenderQueueGroup(RenderQueue* parent, bool splitPassesByLightingType,
245            bool splitNoShadowPasses)
246            :mParent(parent), mSplitPassesByLightingType(splitPassesByLightingType),
247            mSplitNoShadowPasses(splitNoShadowPasses), mShadowsEnabled(true) {}
248
249        ~RenderQueueGroup() {
250            // destroy contents now
251            PriorityMap::iterator i;
252            for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
253            {
254                delete i->second;
255            }
256        }
257
258        /** Get an iterator for browsing through child contents. */
259        PriorityMapIterator getIterator(void)
260        {
261            return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
262        }
263
264        /** Add a renderable to this group, with the given priority. */
265        void addRenderable(Renderable* pRend, ushort priority)
266        {
267            // Check if priority group is there
268            PriorityMap::iterator i = mPriorityGroups.find(priority);
269            RenderPriorityGroup* pPriorityGrp;
270            if (i == mPriorityGroups.end())
271            {
272                // Missing, create
273                pPriorityGrp = new RenderPriorityGroup(this,
274                    mSplitPassesByLightingType, mSplitNoShadowPasses);
275                mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
276            }
277            else
278            {
279                pPriorityGrp = i->second;
280            }
281
282            // Add
283            pPriorityGrp->addRenderable(pRend);
284
285        }
286
287        /** Clears this group of renderables.
288        @param destroy
289            If false, doesn't delete any priority groups, just empties them. Saves on
290            memory deallocations since the chances are rougly the same kinds of
291            renderables are going to be sent to the queue again next time. If
292                        true, completely destroys.
293        */
294        void clear(bool destroy = false)
295        {
296            PriorityMap::iterator i, iend;
297            iend = mPriorityGroups.end();
298            for (i = mPriorityGroups.begin(); i != iend; ++i)
299            {
300                                if (destroy)
301                                        delete i->second;
302                                else
303                                        i->second->clear();
304            }
305
306                        if (destroy)
307                                mPriorityGroups.clear();
308
309        }
310
311                /** Indicate whether a given queue group will be doing any
312                shadow setup.
313                @remarks
314                This method allows you to inform the queue about a queue group, and to
315                indicate whether this group will require shadow processing of any sort.
316                In order to preserve rendering order, OGRE has to treat queue groups
317                as very separate elements of the scene, and this can result in it
318                having to duplicate shadow setup for each group. Therefore, if you
319                know that a group which you are using will never need shadows, you
320                should preregister the group using this method in order to improve
321                the performance.
322                */
323                void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
324
325                /** Are shadows enabled for this queue? */
326                bool getShadowsEnabled(void) const { return mShadowsEnabled; }
327
328        /** Sets whether or not the queue will split passes by their lighting type,
329        ie ambient, per-light and decal.
330        */
331        void setSplitPassesByLightingType(bool split)
332        {
333            mSplitPassesByLightingType = split;
334            PriorityMap::iterator i, iend;
335            iend = mPriorityGroups.end();
336            for (i = mPriorityGroups.begin(); i != iend; ++i)
337            {
338                i->second->setSplitPassesByLightingType(split);
339            }
340        }
341        /** Sets whether or not the queue will split passes which have shadow receive
342        turned off (in their parent material), which is needed when certain shadow
343        techniques are used.
344        */
345        void setSplitNoShadowPasses(bool split)
346        {
347            mSplitNoShadowPasses = split;
348            PriorityMap::iterator i, iend;
349            iend = mPriorityGroups.end();
350            for (i = mPriorityGroups.begin(); i != iend; ++i)
351            {
352                i->second->setSplitNoShadowPasses(split);
353            }
354        }
355
356    };
357
358
359
360}
361
362#endif
363
364
Note: See TracBrowser for help on using the repository browser.