OgreRenderQueueSortingGrouping.h
Go to the documentation of this file.
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4  (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #ifndef __RenderQueueSortingGrouping_H__
29 #define __RenderQueueSortingGrouping_H__
30 
31 // Precompiler options
32 #include "OgrePrerequisites.h"
33 #include "OgreIteratorWrappers.h"
34 #include "OgreMaterial.h"
35 #include "OgreTechnique.h"
36 #include "OgrePass.h"
37 #include "OgreRadixSort.h"
38 
39 namespace Ogre {
40 
52  {
57 
58  RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
59  };
60 
61 
70  {
71  public:
74 
81  virtual void visit(RenderablePass* rp) = 0;
82 
83  /* When visiting a collection grouped by pass, this is
84  called when the grouping pass changes.
85  @remarks
86  If this method is called, the RenderablePass visit
87  method will not be called for this collection. The
88  Renderable visit method will be called for each item
89  underneath the pass grouping level.
90  @return True to continue, false to skip the Renderables underneath
91  */
92  virtual bool visit(const Pass* p) = 0;
99  virtual void visit(Renderable* r) = 0;
100 
101 
102  };
103 
114  {
115  public:
125  {
127  OM_PASS_GROUP = 1,
129  OM_SORT_DESCENDING = 2,
133  OM_SORT_ASCENDING = 6
134  };
135 
136  protected:
139  {
140  bool _OgreExport operator()(const Pass* a, const Pass* b) const
141  {
142  // Sort by passHash, which is pass, then texture unit changes
143  uint32 hasha = a->getHash();
144  uint32 hashb = b->getHash();
145  if (hasha == hashb)
146  {
147  // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash
148  return a < b;
149  }
150  else
151  {
152  return hasha < hashb;
153  }
154  }
155  };
158  {
159  const Camera* camera;
160 
162  : camera(cam)
163  {
164  }
165 
166  bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
167  {
168  if (a.renderable == b.renderable)
169  {
170  // Same renderable, sort by pass hash
171  return a.pass->getHash() < b.pass->getHash();
172  }
173  else
174  {
175  // Different renderables, sort by depth
176  Real adepth = a.renderable->getSquaredViewDepth(camera);
177  Real bdepth = b.renderable->getSquaredViewDepth(camera);
178  if (Math::RealEqual(adepth, bdepth))
179  {
180  // Must return deterministic result, doesn't matter what
181  return a.pass < b.pass;
182  }
183  else
184  {
185  // Sort DESCENDING by depth (i.e. far objects first)
186  return (adepth > bdepth);
187  }
188  }
189 
190  }
191  };
192 
200 
203  {
205  {
206  return p.pass->getHash();
207  }
208  };
209 
212 
215  {
216  const Camera* camera;
217 
219  : camera(cam)
220  {
221  }
222 
223  float operator()(const RenderablePass& p) const
224  {
225  // Sort DESCENDING by depth (ie far objects first), use negative distance
226  // here because radix sorter always dealing with accessing sort
227  return static_cast<float>(- p.renderable->getSquaredViewDepth(camera));
228  }
229  };
230 
233 
236 
241 
248 
249  public:
252 
254  void clear(void);
255 
262 
269  {
270  mOrganisationMode = 0;
271  }
272 
279  {
280  mOrganisationMode |= om;
281  }
282 
284  void addRenderable(Pass* pass, Renderable* rend);
285 
289  void sort(const Camera* cam);
290 
298 
301  void merge( const QueuedRenderableCollection& rhs );
302  };
303 
324  {
325  protected:
326 
344 
347 
349  void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
356 
357  public:
359  bool splitPassesByLightingType,
360  bool splitNoShadowPasses,
361  bool shadowCastersNotReceivers);
362 
364 
370  { return mSolidsBasic; }
374  { return mSolidsDiffuseSpecular; }
378  { return mSolidsDecal; }
382  { return mSolidsNoShadowReceive; }
385  { return mTransparentsUnsorted; }
388  { return mTransparents; }
389 
390 
398 
406 
414 
416  void addRenderable(Renderable* pRend, Technique* pTech);
417 
420  void sort(const Camera* cam);
421 
424  void clear(void);
425 
430  {
431  mSplitPassesByLightingType = split;
432  }
433 
437  void setSplitNoShadowPasses(bool split)
438  {
439  mSplitNoShadowPasses = split;
440  }
441 
446  {
447  mShadowCastersNotReceivers = ind;
448  }
449 
452  void merge( const RenderPriorityGroup* rhs );
453 
454 
455  };
456 
457 
466  {
467  public:
471  protected:
482 
483 
484  public:
486  bool splitPassesByLightingType,
487  bool splitNoShadowPasses,
488  bool shadowCastersNotReceivers)
489  : mParent(parent)
490  , mSplitPassesByLightingType(splitPassesByLightingType)
491  , mSplitNoShadowPasses(splitNoShadowPasses)
492  , mShadowCastersNotReceivers(shadowCastersNotReceivers)
493  , mShadowsEnabled(true)
494  , mOrganisationMode(0)
495  {
496  }
497 
499  // destroy contents now
500  PriorityMap::iterator i;
501  for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
502  {
503  OGRE_DELETE i->second;
504  }
505  }
506 
509  {
510  return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
511  }
512 
515  {
516  return ConstPriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
517  }
518 
520  void addRenderable(Renderable* pRend, Technique* pTech, ushort priority)
521  {
522  // Check if priority group is there
523  PriorityMap::iterator i = mPriorityGroups.find(priority);
524  RenderPriorityGroup* pPriorityGrp;
525  if (i == mPriorityGroups.end())
526  {
527  // Missing, create
528  pPriorityGrp = OGRE_NEW RenderPriorityGroup(this,
529  mSplitPassesByLightingType,
530  mSplitNoShadowPasses,
531  mShadowCastersNotReceivers);
532  if (mOrganisationMode)
533  {
534  pPriorityGrp->resetOrganisationModes();
535  pPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode);
536  }
537 
538  mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
539  }
540  else
541  {
542  pPriorityGrp = i->second;
543  }
544 
545  // Add
546  pPriorityGrp->addRenderable(pRend, pTech);
547 
548  }
549 
557  void clear(bool destroy = false)
558  {
559  PriorityMap::iterator i, iend;
560  iend = mPriorityGroups.end();
561  for (i = mPriorityGroups.begin(); i != iend; ++i)
562  {
563  if (destroy)
564  OGRE_DELETE i->second;
565  else
566  i->second->clear();
567  }
568 
569  if (destroy)
570  mPriorityGroups.clear();
571 
572  }
573 
586  void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
587 
589  bool getShadowsEnabled(void) const { return mShadowsEnabled; }
590 
595  {
596  mSplitPassesByLightingType = split;
597  PriorityMap::iterator i, iend;
598  iend = mPriorityGroups.end();
599  for (i = mPriorityGroups.begin(); i != iend; ++i)
600  {
601  i->second->setSplitPassesByLightingType(split);
602  }
603  }
608  void setSplitNoShadowPasses(bool split)
609  {
610  mSplitNoShadowPasses = split;
611  PriorityMap::iterator i, iend;
612  iend = mPriorityGroups.end();
613  for (i = mPriorityGroups.begin(); i != iend; ++i)
614  {
615  i->second->setSplitNoShadowPasses(split);
616  }
617  }
622  {
623  mShadowCastersNotReceivers = ind;
624  PriorityMap::iterator i, iend;
625  iend = mPriorityGroups.end();
626  for (i = mPriorityGroups.begin(); i != iend; ++i)
627  {
628  i->second->setShadowCastersCannotBeReceivers(ind);
629  }
630  }
638  {
639  mOrganisationMode = 0;
640 
641  PriorityMap::iterator i, iend;
642  iend = mPriorityGroups.end();
643  for (i = mPriorityGroups.begin(); i != iend; ++i)
644  {
645  i->second->resetOrganisationModes();
646  }
647  }
648 
656  {
657  mOrganisationMode |= om;
658 
659  PriorityMap::iterator i, iend;
660  iend = mPriorityGroups.end();
661  for (i = mPriorityGroups.begin(); i != iend; ++i)
662  {
663  i->second->addOrganisationMode(om);
664  }
665  }
666 
674  {
675  mOrganisationMode = 0;
676 
677  PriorityMap::iterator i, iend;
678  iend = mPriorityGroups.end();
679  for (i = mPriorityGroups.begin(); i != iend; ++i)
680  {
681  i->second->defaultOrganisationMode();
682  }
683  }
684 
687  void merge( const RenderQueueGroup* rhs )
688  {
690 
691  while( it.hasMoreElements() )
692  {
693  ushort priority = it.peekNextKey();
694  RenderPriorityGroup* pSrcPriorityGrp = it.getNext();
695  RenderPriorityGroup* pDstPriorityGrp;
696 
697  // Check if priority group is there
698  PriorityMap::iterator i = mPriorityGroups.find(priority);
699  if (i == mPriorityGroups.end())
700  {
701  // Missing, create
702  pDstPriorityGrp = OGRE_NEW RenderPriorityGroup(this,
703  mSplitPassesByLightingType,
704  mSplitNoShadowPasses,
705  mShadowCastersNotReceivers);
706  if (mOrganisationMode)
707  {
708  pDstPriorityGrp->resetOrganisationModes();
709  pDstPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode);
710  }
711 
712  mPriorityGroups.insert(PriorityMap::value_type(priority, pDstPriorityGrp));
713  }
714  else
715  {
716  pDstPriorityGrp = i->second;
717  }
718 
719  // merge
720  pDstPriorityGrp->merge( pSrcPriorityGrp );
721  }
722  }
723  };
724 
729 }
730 
731 #endif
732 
733 
#define _OgreExport
Definition: OgrePlatform.h:257
Superclass for all objects that wish to use custom memory allocators when their new / delete operator...
A viewpoint from which the scene will be rendered.
Definition: OgreCamera.h:87
Concrete IteratorWrapper for const access to the underlying key-value container.
bool hasMoreElements() const
Returns true if there are more items in the collection.
KeyType peekNextKey(void) const
Returns the next(=current) key element in the collection, without advancing to the next.
ValueType getNext()
Returns the next(=current) value element in the collection, and advances to the next.
Concrete IteratorWrapper for nonconst access to the underlying key-value container.
static bool RealEqual(Real a, Real b, Real tolerance=std::numeric_limits< Real >::epsilon())
Compare 2 reals, using tolerance for inaccuracies.
Class defining a single pass of a Technique (of a Material), i.e.
Definition: OgrePass.h:81
uint32 getHash(void) const
Gets the 'hash' of this pass, ie a precomputed number to use for sorting.
Definition: OgrePass.h:1500
Lowest level collection of renderables.
void addOrganisationMode(OrganisationMode om)
Add a required sorting / grouping mode to this collection when next used.
void acceptVisitorDescending(QueuedRenderableVisitor *visitor) const
Internal visitor implementation.
void acceptVisitorAscending(QueuedRenderableVisitor *visitor) const
Internal visitor implementation.
static RadixSort< RenderablePassList, RenderablePass, uint32 > msRadixSorter1
Radix sorter for accessing sort value 1 (Pass)
void acceptVisitorGrouped(QueuedRenderableVisitor *visitor) const
Internal visitor implementation.
void merge(const QueuedRenderableCollection &rhs)
Merge renderable collection.
vector< RenderablePass >::type RenderablePassList
Vector of RenderablePass objects, this is built on the assumption that vectors only ever increase in ...
void addRenderable(Pass *pass, Renderable *rend)
Add a renderable to the collection using a given pass.
OrganisationMode
Organisation modes required for this collection.
RenderablePassList mSortedDescending
Sorted descending (can iterate backwards to get ascending)
void removePassGroup(Pass *p)
Remove the group entry (if any) for a given Pass.
static RadixSort< RenderablePassList, RenderablePass, float > msRadixSorter2
Radix sorter for sort value 2 (distance)
map< Pass *, RenderableList *, PassGroupLess >::type PassGroupRenderableMap
Map of pass to renderable lists, this is a grouping by pass.
void clear(void)
Empty the collection.
uint8 mOrganisationMode
Bitmask of the organisation modes requested.
void acceptVisitor(QueuedRenderableVisitor *visitor, OrganisationMode om) const
Accept a visitor over the collection contents.
void sort(const Camera *cam)
Perform any sorting that is required on this collection.
void resetOrganisationModes(void)
Reset the organisation modes required for this collection.
Visitor interface for items in a QueuedRenderableCollection.
virtual void visit(Renderable *r)=0
Visit method called once per Renderable on a grouped collection.
virtual void visit(RenderablePass *rp)=0
Called when visiting a RenderablePass, i.e.
virtual bool visit(const Pass *p)=0
Class for performing a radix sort (fast comparison-less sort based on byte value) on various standard...
Definition: OgreRadixSort.h:89
Collection of renderables by priority.
void setSplitPassesByLightingType(bool split)
Sets whether or not the queue will split passes by their lighting type, ie ambient,...
void addSolidRenderable(Technique *pTech, Renderable *rend, bool toNoShadowMap)
Internal method for adding a solid renderable.
void sort(const Camera *cam)
Sorts the objects which have been added to the queue; transparent objects by their depth in relation ...
const QueuedRenderableCollection & getSolidsNoShadowReceive(void) const
Get the collection of solids for which shadow receipt is disabled (only applicable when shadows are e...
const QueuedRenderableCollection & getSolidsDiffuseSpecular(void) const
Get the collection of solids currently queued per light (only applicable in additive shadow modes).
const QueuedRenderableCollection & getSolidsDecal(void) const
Get the collection of solids currently queued for decal passes (only applicable in additive shadow mo...
QueuedRenderableCollection mSolidsDiffuseSpecular
Solid per-light pass list, used with additive shadows.
QueuedRenderableCollection mTransparentsUnsorted
Unsorted transparent list.
const QueuedRenderableCollection & getSolidsBasic(void) const
Get the collection of basic solids currently queued, this includes all solids when there are no shado...
RenderPriorityGroup(RenderQueueGroup *parent, bool splitPassesByLightingType, bool splitNoShadowPasses, bool shadowCastersNotReceivers)
void setSplitNoShadowPasses(bool split)
Sets whether or not passes which have shadow receive disabled should be separated.
void addUnsortedTransparentRenderable(Technique *pTech, Renderable *rend)
Internal method for adding an unsorted transparent renderable.
void addTransparentRenderable(Technique *pTech, Renderable *rend)
Internal method for adding a transparent renderable.
void defaultOrganisationMode(void)
Set the sorting / grouping mode for the solids in this group to the default.
void addRenderable(Renderable *pRend, Technique *pTech)
Add a renderable to this group.
const QueuedRenderableCollection & getTransparents(void) const
Get the collection of transparent objects currently queued.
QueuedRenderableCollection mSolidsBasic
Solid pass list, used when no shadows, modulative shadows, or ambient passes for additive.
QueuedRenderableCollection mTransparents
Transparent list.
void setShadowCastersCannotBeReceivers(bool ind)
Sets whether or not objects which cast shadows should be treated as never receiving shadows.
void clear(void)
Clears this group of renderables.
void addSolidRenderableSplitByLightType(Technique *pTech, Renderable *rend)
Internal method for adding a solid renderable.
QueuedRenderableCollection mSolidsNoShadowReceive
Solid pass list, used when shadows are enabled but shadow receive is turned off for these passes.
void merge(const RenderPriorityGroup *rhs)
Merge group of renderables.
void removePassEntry(Pass *p)
remove a pass entry from all collections
void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
Add a required sorting / grouping mode for the solids in this group.
QueuedRenderableCollection mSolidsDecal
Solid decal (texture) pass list, used with additive shadows.
const QueuedRenderableCollection & getTransparentsUnsorted(void) const
Get the collection of transparent objects currently queued.
RenderQueueGroup * mParent
Parent queue group.
void resetOrganisationModes(void)
Reset the organisation modes required for the solids in this group.
A grouping level underneath RenderQueue which groups renderables to be issued at coarsely the same ti...
void addRenderable(Renderable *pRend, Technique *pTech, ushort priority)
Add a renderable to this group, with the given priority.
void defaultOrganisationMode(void)
Setthe sorting / grouping mode for the solids in this group to the default.
void setShadowsEnabled(bool enabled)
Indicate whether a given queue group will be doing any shadow setup.
void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
Add a required sorting / grouping mode for the solids in this group.
ConstMapIterator< PriorityMap > ConstPriorityMapIterator
MapIterator< PriorityMap > PriorityMapIterator
void merge(const RenderQueueGroup *rhs)
Merge group of renderables.
void resetOrganisationModes(void)
Reset the organisation modes required for the solids in this group.
ConstPriorityMapIterator getIterator(void) const
Get a const iterator for browsing through child contents.
void setShadowCastersCannotBeReceivers(bool ind)
Sets whether or not objects which cast shadows should be treated as never receiving shadows.
bool mShadowsEnabled
Whether shadows are enabled for this queue.
map< ushort, RenderPriorityGroup *, std::less< ushort > >::type PriorityMap
PriorityMap mPriorityGroups
Map of RenderPriorityGroup objects.
PriorityMapIterator getIterator(void)
Get an iterator for browsing through child contents.
uint8 mOrganisationMode
Bitmask of the organisation modes requested (for new priority groups)
void setSplitNoShadowPasses(bool split)
Sets whether or not the queue will split passes which have shadow receive turned off (in their parent...
RenderQueueGroup(RenderQueue *parent, bool splitPassesByLightingType, bool splitNoShadowPasses, bool shadowCastersNotReceivers)
void setSplitPassesByLightingType(bool split)
Sets whether or not the queue will split passes by their lighting type, ie ambient,...
bool getShadowsEnabled(void) const
Are shadows enabled for this queue?
void clear(bool destroy=false)
Clears this group of renderables.
Class to manage the scene object rendering queue.
Abstract class defining the interface all renderable objects must implement.
virtual Real getSquaredViewDepth(const Camera *cam) const =0
Returns the camera-relative squared depth of this renderable.
Class representing an approach to rendering this particular Material.
Definition: OgreTechnique.h:54
#define OGRE_NEW
#define OGRE_DELETE
unsigned char uint8
Definition: OgrePlatform.h:361
float Real
Software floating point type.
unsigned int uint32
Definition: OgrePlatform.h:359
unsigned short ushort
Comparator to order objects by descending camera distance.
bool _OgreExport operator()(const RenderablePass &a, const RenderablePass &b) const
bool _OgreExport operator()(const Pass *a, const Pass *b) const
Functor for descending sort value 2 for radix sort (distance)
Functor for accessing sort value 1 for radix sort (Pass)
Struct associating a single Pass with a single Renderable.
Renderable * renderable
Pointer to the Renderable details.
RenderablePass(Renderable *rend, Pass *p)
Pass * pass
Pointer to the Pass.
std::vector< T, A > type

Copyright © 2012 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.