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

Revision 193, 15.2 KB checked in by mattausch, 19 years ago (diff)

changed to ogre 103
added readme

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