Geen omschrijving
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LayerUtility.cs 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using Unity.Mathematics;
  2. using System.Collections.Generic;
  3. namespace UnityEngine.Rendering.Universal
  4. {
  5. internal struct LayerBatch
  6. {
  7. #if UNITY_EDITOR
  8. public int startIndex;
  9. public int endIndex;
  10. #endif
  11. public int startLayerID;
  12. public int endLayerValue;
  13. public SortingLayerRange layerRange;
  14. public LightStats lightStats;
  15. private unsafe fixed int renderTargetIds[4];
  16. private unsafe fixed bool renderTargetUsed[4];
  17. public List<Light2D> lights;
  18. public List<Light2D> shadowLights;
  19. public List<ShadowCasterGroup2D> shadowCasters;
  20. internal int[] activeBlendStylesIndices;
  21. public void InitRTIds(int index)
  22. {
  23. for (var i = 0; i < 4; i++)
  24. {
  25. unsafe
  26. {
  27. renderTargetUsed[i] = false;
  28. renderTargetIds[i] = Shader.PropertyToID($"_LightTexture_{index}_{i}");
  29. }
  30. }
  31. lights = new List<Light2D>();
  32. shadowLights = new List<Light2D>();
  33. shadowCasters = new List<ShadowCasterGroup2D>();
  34. }
  35. public RenderTargetIdentifier GetRTId(CommandBuffer cmd, RenderTextureDescriptor desc, int index)
  36. {
  37. unsafe
  38. {
  39. if (!renderTargetUsed[index])
  40. {
  41. cmd.GetTemporaryRT(renderTargetIds[index], desc, FilterMode.Bilinear);
  42. renderTargetUsed[index] = true;
  43. }
  44. return new RenderTargetIdentifier(renderTargetIds[index]);
  45. }
  46. }
  47. public void ReleaseRT(CommandBuffer cmd)
  48. {
  49. for (var i = 0; i < 4; i++)
  50. {
  51. unsafe
  52. {
  53. if (!renderTargetUsed[i])
  54. continue;
  55. cmd.ReleaseTemporaryRT(renderTargetIds[i]);
  56. renderTargetUsed[i] = false;
  57. }
  58. }
  59. }
  60. }
  61. internal static class LayerUtility
  62. {
  63. private static LayerBatch[] s_LayerBatches;
  64. public static uint maxTextureCount { get; private set; }
  65. public static void InitializeBudget(uint maxTextureCount)
  66. {
  67. LayerUtility.maxTextureCount = math.max(4, maxTextureCount);
  68. }
  69. private static bool CanBatchLightsInLayer(int layerIndex1, int layerIndex2, SortingLayer[] sortingLayers, ILight2DCullResult lightCullResult)
  70. {
  71. var layerId1 = sortingLayers[layerIndex1].id;
  72. var layerId2 = sortingLayers[layerIndex2].id;
  73. foreach (var light in lightCullResult.visibleLights)
  74. {
  75. // If the lit layers are different don't batch.
  76. if (light.IsLitLayer(layerId1) != light.IsLitLayer(layerId2))
  77. return false;
  78. }
  79. foreach (var group in lightCullResult.visibleShadows)
  80. {
  81. foreach (var shadowCaster in group.GetShadowCasters())
  82. {
  83. // Don't batch when the layer has different shadow casters
  84. if (shadowCaster.IsShadowedLayer(layerId1) != shadowCaster.IsShadowedLayer(layerId2))
  85. return false;
  86. }
  87. }
  88. return true;
  89. }
  90. private static int FindUpperBoundInBatch(int startLayerIndex, SortingLayer[] sortingLayers, ILight2DCullResult lightCullResult)
  91. {
  92. // start checking at the next layer
  93. for (var i = startLayerIndex + 1; i < sortingLayers.Length; i++)
  94. {
  95. if (!CanBatchLightsInLayer(startLayerIndex, i, sortingLayers, lightCullResult))
  96. return i - 1;
  97. }
  98. return sortingLayers.Length - 1;
  99. }
  100. private static void InitializeBatchInfos(SortingLayer[] cachedSortingLayers)
  101. {
  102. var count = cachedSortingLayers.Length;
  103. var needInit = s_LayerBatches == null;
  104. if (s_LayerBatches is null)
  105. {
  106. s_LayerBatches = new LayerBatch[count];
  107. }
  108. #if UNITY_EDITOR
  109. // we should fix. Make a non allocating version of this
  110. if (!Application.isPlaying && s_LayerBatches.Length != count)
  111. {
  112. s_LayerBatches = new LayerBatch[count];
  113. needInit = true;
  114. }
  115. #endif
  116. if (needInit)
  117. {
  118. for (var i = 0; i < s_LayerBatches.Length; i++)
  119. {
  120. ref var layerBatch = ref s_LayerBatches[i];
  121. layerBatch.InitRTIds(i);
  122. }
  123. }
  124. }
  125. public static LayerBatch[] CalculateBatches(ILight2DCullResult lightCullResult, out int batchCount)
  126. {
  127. var cachedSortingLayers = Light2DManager.GetCachedSortingLayer();
  128. InitializeBatchInfos(cachedSortingLayers);
  129. batchCount = 0;
  130. for (var i = 0; i < cachedSortingLayers.Length;)
  131. {
  132. var layerToRender = cachedSortingLayers[i].id;
  133. ref var layerBatch = ref s_LayerBatches[batchCount++];
  134. var lightStats = lightCullResult.GetLightStatsByLayer(layerToRender, ref layerBatch);
  135. // Find the highest layer that share the same set of lights and shadows as this layer.
  136. var upperLayerInBatch = FindUpperBoundInBatch(i, cachedSortingLayers, lightCullResult);
  137. // Some renderers override their sorting layer value with short.MinValue or short.MaxValue.
  138. // When drawing the first sorting layer, we should include the range from short.MinValue to layerValue.
  139. // Similarly, when drawing the last sorting layer, include the range from layerValue to short.MaxValue.
  140. var startLayerValue = (short)cachedSortingLayers[i].value;
  141. var lowerBound = (i == 0) ? short.MinValue : startLayerValue;
  142. var endLayerValue = (short)cachedSortingLayers[upperLayerInBatch].value;
  143. var upperBound = (upperLayerInBatch == cachedSortingLayers.Length - 1) ? short.MaxValue : endLayerValue;
  144. // Renderer within this range share the same set of lights so they should be rendered together.
  145. var sortingLayerRange = new SortingLayerRange(lowerBound, upperBound);
  146. #if UNITY_EDITOR
  147. layerBatch.startIndex = i;
  148. layerBatch.endIndex = upperLayerInBatch;
  149. #endif
  150. layerBatch.startLayerID = layerToRender;
  151. layerBatch.endLayerValue = endLayerValue;
  152. layerBatch.layerRange = sortingLayerRange;
  153. layerBatch.lightStats = lightStats;
  154. i = upperLayerInBatch + 1;
  155. }
  156. SetupActiveBlendStyles();
  157. return s_LayerBatches;
  158. }
  159. public static void GetFilterSettings(Renderer2DData rendererData, ref LayerBatch layerBatch, short cameraSortingLayerBoundsIndex, out FilteringSettings filterSettings)
  160. {
  161. filterSettings = FilteringSettings.defaultValue;
  162. filterSettings.renderQueueRange = RenderQueueRange.all;
  163. filterSettings.layerMask = -1;
  164. filterSettings.renderingLayerMask = 0xFFFFFFFF;
  165. short upperBound = layerBatch.layerRange.upperBound;
  166. if (rendererData.useCameraSortingLayerTexture && cameraSortingLayerBoundsIndex >= layerBatch.layerRange.lowerBound && cameraSortingLayerBoundsIndex < layerBatch.layerRange.upperBound)
  167. upperBound = cameraSortingLayerBoundsIndex;
  168. filterSettings.sortingLayerRange = new SortingLayerRange(layerBatch.layerRange.lowerBound, upperBound);
  169. }
  170. static void SetupActiveBlendStyles()
  171. {
  172. // Calculate active blend styles to save on total light textures allocated
  173. for (int i = 0; i < s_LayerBatches.Length; ++i)
  174. {
  175. ref var layer = ref s_LayerBatches[i];
  176. // Determine number of blend styles used
  177. int size = 0;
  178. for (var blendStyleIndex = 0; blendStyleIndex < RendererLighting.k_ShapeLightTextureIDs.Length; blendStyleIndex++)
  179. {
  180. var blendStyleMask = (uint)(1 << blendStyleIndex);
  181. var blendStyleUsed = (layer.lightStats.blendStylesUsed & blendStyleMask) > 0;
  182. if (blendStyleUsed)
  183. size++;
  184. }
  185. if (layer.activeBlendStylesIndices == null || layer.activeBlendStylesIndices.Length != size)
  186. layer.activeBlendStylesIndices = new int[size];
  187. // Save indices so we don't have to copy the whole Light2DBlendStyle struct
  188. var index = 0;
  189. for (var blendStyleIndex = 0; blendStyleIndex < RendererLighting.k_ShapeLightTextureIDs.Length; blendStyleIndex++)
  190. {
  191. var blendStyleMask = (uint)(1 << blendStyleIndex);
  192. var blendStyleUsed = (layer.lightStats.blendStylesUsed & blendStyleMask) > 0;
  193. if (blendStyleUsed)
  194. layer.activeBlendStylesIndices[index++] = blendStyleIndex;
  195. }
  196. }
  197. }
  198. }
  199. }