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

Revision 139, 15.1 KB checked in by mattausch, 19 years ago (diff)

fixed bug with tight octree boxes
added more flexible renderqueue (can delete per flag)
reordered functions in visibility terrain scene manager

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