source: OGRE/trunk/ogrenew/OgreMain/include/OgreRenderQueueSortingGrouping.h @ 657

Revision 657, 15.5 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

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