BsRenderQueue.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "BsRenderQueue.h"
  2. #include "BsSubMesh.h"
  3. #include "BsShader.h"
  4. #include "BsMesh.h"
  5. #include "BsMaterial.h"
  6. #include "BsRenderableElement.h"
  7. using namespace std::placeholders;
  8. namespace BansheeEngine
  9. {
  10. RenderQueue::RenderQueue(StateReduction mode)
  11. :mStateReductionMode(mode)
  12. {
  13. }
  14. void RenderQueue::clear()
  15. {
  16. mSortableElements.clear();
  17. mSortableElementIdx.clear();
  18. mElements.clear();
  19. mSortedRenderElements.clear();
  20. }
  21. void RenderQueue::add(RenderableElement* element, float distFromCamera)
  22. {
  23. SPtr<MaterialCore> material = element->material;
  24. SPtr<ShaderCore> shader = material->getShader();
  25. mElements.push_back(element);
  26. UINT32 queuePriority = shader->getQueuePriority();
  27. QueueSortType sortType = shader->getQueueSortType();
  28. UINT32 shaderId = shader->getId();
  29. bool separablePasses = shader->getAllowSeparablePasses();
  30. switch (sortType)
  31. {
  32. case QueueSortType::None:
  33. distFromCamera = 0;
  34. break;
  35. case QueueSortType::BackToFront:
  36. distFromCamera = -distFromCamera;
  37. break;
  38. }
  39. UINT32 numPasses = material->getNumPasses();
  40. if (!separablePasses)
  41. numPasses = std::min(1U, numPasses);
  42. for (UINT32 i = 0; i < numPasses; i++)
  43. {
  44. UINT32 idx = (UINT32)mSortableElementIdx.size();
  45. mSortableElementIdx.push_back(idx);
  46. mSortableElements.push_back(SortableElement());
  47. SortableElement& sortableElem = mSortableElements.back();
  48. sortableElem.seqIdx = idx;
  49. sortableElem.priority = queuePriority;
  50. sortableElem.shaderId = shaderId;
  51. sortableElem.passIdx = i;
  52. sortableElem.distFromCamera = distFromCamera;
  53. }
  54. }
  55. void RenderQueue::sort()
  56. {
  57. std::function<bool(UINT32, UINT32, const Vector<SortableElement>&)> sortMethod;
  58. switch (mStateReductionMode)
  59. {
  60. case StateReduction::None:
  61. sortMethod = &elementSorterNoGroup;
  62. break;
  63. case StateReduction::Material:
  64. sortMethod = &elementSorterPreferGroup;
  65. break;
  66. case StateReduction::Distance:
  67. sortMethod = &elementSorterPreferSort;
  68. break;
  69. }
  70. if (mSortableElementIdx.size() > 1)
  71. {
  72. int a = 5;
  73. }
  74. // Sort only indices since we generate an entirely new data set anyway, it doesn't make sense to move sortable elements
  75. std::sort(mSortableElementIdx.begin(), mSortableElementIdx.end(), std::bind(sortMethod, _1, _2, mSortableElements));
  76. UINT32 prevShaderId = (UINT32)-1;
  77. UINT32 prevPassIdx = (UINT32)-1;
  78. RenderableElement* renderElem = nullptr;
  79. INT32 currentElementIdx = -1;
  80. UINT32 numPassesInCurrentElement = 0;
  81. bool separablePasses = true;
  82. for (UINT32 i = 0; i < (UINT32)mSortableElementIdx.size(); i++)
  83. {
  84. UINT32 idx = mSortableElementIdx[i];
  85. while (numPassesInCurrentElement == 0)
  86. {
  87. currentElementIdx++;
  88. renderElem = mElements[currentElementIdx];
  89. numPassesInCurrentElement = renderElem->material->getNumPasses();
  90. separablePasses = renderElem->material->getShader()->getAllowSeparablePasses();
  91. }
  92. const SortableElement& elem = mSortableElements[idx];
  93. if (separablePasses)
  94. {
  95. mSortedRenderElements.push_back(RenderQueueElement());
  96. RenderQueueElement& sortedElem = mSortedRenderElements.back();
  97. sortedElem.renderElem = renderElem;
  98. sortedElem.passIdx = elem.passIdx;
  99. if (prevShaderId != elem.shaderId || prevPassIdx != elem.passIdx)
  100. {
  101. sortedElem.applyPass = true;
  102. prevShaderId = elem.shaderId;
  103. prevPassIdx = elem.passIdx;
  104. }
  105. else
  106. sortedElem.applyPass = false;
  107. numPassesInCurrentElement--;
  108. }
  109. else
  110. {
  111. for (UINT32 j = 0; j < numPassesInCurrentElement; j++)
  112. {
  113. mSortedRenderElements.push_back(RenderQueueElement());
  114. RenderQueueElement& sortedElem = mSortedRenderElements.back();
  115. sortedElem.renderElem = renderElem;
  116. sortedElem.passIdx = j;
  117. sortedElem.applyPass = true;
  118. prevShaderId = elem.shaderId;
  119. prevPassIdx = j;
  120. }
  121. numPassesInCurrentElement = 0;
  122. }
  123. }
  124. }
  125. bool RenderQueue::elementSorterNoGroup(UINT32 aIdx, UINT32 bIdx, const Vector<SortableElement>& lookup)
  126. {
  127. const SortableElement& a = lookup[aIdx];
  128. const SortableElement& b = lookup[bIdx];
  129. UINT8 isHigher = (a.priority > b.priority) << 2 |
  130. (a.distFromCamera < b.distFromCamera) << 1 |
  131. (a.seqIdx < b.seqIdx);
  132. UINT8 isLower = (a.priority < b.priority) << 2 |
  133. (a.distFromCamera > b.distFromCamera) << 1 |
  134. (a.seqIdx > b.seqIdx);
  135. return isHigher > isLower;
  136. }
  137. bool RenderQueue::elementSorterPreferGroup(UINT32 aIdx, UINT32 bIdx, const Vector<SortableElement>& lookup)
  138. {
  139. const SortableElement& a = lookup[aIdx];
  140. const SortableElement& b = lookup[bIdx];
  141. UINT8 isHigher = (a.priority > b.priority) << 4 |
  142. (a.shaderId < b.shaderId) << 3 |
  143. (a.passIdx < b.passIdx) << 2 |
  144. (a.distFromCamera < b.distFromCamera) << 1 |
  145. (a.seqIdx < b.seqIdx);
  146. UINT8 isLower = (a.priority < b.priority) << 4 |
  147. (a.shaderId > b.shaderId) << 3 |
  148. (a.passIdx > b.passIdx) << 2 |
  149. (a.distFromCamera > b.distFromCamera) << 1 |
  150. (a.seqIdx > b.seqIdx);
  151. return isHigher > isLower;
  152. }
  153. bool RenderQueue::elementSorterPreferSort(UINT32 aIdx, UINT32 bIdx, const Vector<SortableElement>& lookup)
  154. {
  155. const SortableElement& a = lookup[aIdx];
  156. const SortableElement& b = lookup[bIdx];
  157. UINT8 isHigher = (a.priority > b.priority) << 4 |
  158. (a.distFromCamera < b.distFromCamera) << 3 |
  159. (a.shaderId < b.shaderId) << 2 |
  160. (a.passIdx < b.passIdx) << 1 |
  161. (a.seqIdx < b.seqIdx);
  162. UINT8 isLower = (a.priority < b.priority) << 4 |
  163. (a.distFromCamera > b.distFromCamera) << 3 |
  164. (a.shaderId > b.shaderId) << 2 |
  165. (a.passIdx > b.passIdx) << 1 |
  166. (a.seqIdx > b.seqIdx);
  167. return isHigher > isLower;
  168. }
  169. const Vector<RenderQueueElement>& RenderQueue::getSortedElements() const
  170. {
  171. return mSortedRenderElements;
  172. }
  173. }