暫無描述
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.

ShadowRendering.cs 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine.Experimental.Rendering;
  4. using Unity.Collections;
  5. #if USING_SPRITESHAPE
  6. using UnityEngine.U2D;
  7. #endif
  8. #if UNITY_EDITOR
  9. using UnityEditor;
  10. #endif
  11. namespace UnityEngine.Rendering.Universal
  12. {
  13. // TODO: Culling of shadow casters, rotate color channels for shadow casting, check get material functions.
  14. internal static class ShadowRendering
  15. {
  16. private static readonly int k_LightPosID = Shader.PropertyToID("_LightPos");
  17. private static readonly int k_ShadowRadiusID = Shader.PropertyToID("_ShadowRadius");
  18. private static readonly int k_ShadowColorMaskID = Shader.PropertyToID("_ShadowColorMask");
  19. private static readonly int k_ShadowModelMatrixID = Shader.PropertyToID("_ShadowModelMatrix");
  20. private static readonly int k_ShadowModelInvMatrixID = Shader.PropertyToID("_ShadowModelInvMatrix");
  21. private static readonly int k_ShadowModelScaleID = Shader.PropertyToID("_ShadowModelScale");
  22. private static readonly int k_ShadowContractionDistanceID = Shader.PropertyToID("_ShadowContractionDistance");
  23. private static readonly int k_ShadowAlphaCutoffID = Shader.PropertyToID("_ShadowAlphaCutoff");
  24. private static readonly int k_SoftShadowAngle = Shader.PropertyToID("_SoftShadowAngle");
  25. private static readonly int k_ShadowSoftnessFalloffIntensityID = Shader.PropertyToID("_ShadowSoftnessFalloffIntensity");
  26. private static readonly int k_ShadowShadowColorID = Shader.PropertyToID("_ShadowColor");
  27. private static readonly int k_ShadowUnshadowColorID = Shader.PropertyToID("_UnshadowColor");
  28. private static readonly ProfilingSampler m_ProfilingSamplerShadows = new ProfilingSampler("Draw 2D Shadow Texture");
  29. private static readonly ProfilingSampler m_ProfilingSamplerShadowsA = new ProfilingSampler("Draw 2D Shadows (A)");
  30. private static readonly ProfilingSampler m_ProfilingSamplerShadowsR = new ProfilingSampler("Draw 2D Shadows (R)");
  31. private static readonly ProfilingSampler m_ProfilingSamplerShadowsG = new ProfilingSampler("Draw 2D Shadows (G)");
  32. private static readonly ProfilingSampler m_ProfilingSamplerShadowsB = new ProfilingSampler("Draw 2D Shadows (B)");
  33. private static readonly float k_MaxShadowSoftnessAngle = 15;
  34. private static readonly Color k_ShadowColorLookup = new Color(0, 0, 1, 0);
  35. private static readonly Color k_UnshadowColorLookup = new Color(0, 1, 0, 0);
  36. private static RTHandle[] m_RenderTargets = null;
  37. private static int[] m_RenderTargetIds = null;
  38. private static RenderTargetIdentifier[] m_LightInputTextures = null;
  39. private static readonly ProfilingSampler[] m_ProfilingSamplerShadowColorsLookup = new ProfilingSampler[4] { m_ProfilingSamplerShadowsA, m_ProfilingSamplerShadowsB, m_ProfilingSamplerShadowsG, m_ProfilingSamplerShadowsR };
  40. public static uint maxTextureCount { get; private set; }
  41. public static RenderTargetIdentifier[] lightInputTextures { get { return m_LightInputTextures; } }
  42. internal static void InitializeBudget(uint maxTextureCount)
  43. {
  44. if (m_RenderTargets == null || m_RenderTargets.Length != maxTextureCount)
  45. {
  46. m_RenderTargets = new RTHandle[maxTextureCount];
  47. m_RenderTargetIds = new int[maxTextureCount];
  48. ShadowRendering.maxTextureCount = maxTextureCount;
  49. for (int i = 0; i < maxTextureCount; i++)
  50. {
  51. m_RenderTargetIds[i] = Shader.PropertyToID($"ShadowTex_{i}");
  52. m_RenderTargets[i] = RTHandles.Alloc(m_RenderTargetIds[i], $"ShadowTex_{i}");
  53. }
  54. }
  55. if (m_LightInputTextures == null || m_LightInputTextures.Length != maxTextureCount)
  56. {
  57. m_LightInputTextures = new RenderTargetIdentifier[maxTextureCount];
  58. }
  59. }
  60. private static Material CreateMaterial(Shader shader, int offset, int pass)
  61. {
  62. Material material = CoreUtils.CreateEngineMaterial(shader);
  63. material.SetInt(k_ShadowColorMaskID, 1 << (offset + 1));
  64. material.SetPass(pass);
  65. return material;
  66. }
  67. private static Material GetProjectedShadowMaterial(
  68. Material material,
  69. Func<Renderer2DResources, Shader> shaderFunc,
  70. int offset, int pass)
  71. {
  72. #if !UNITY_EDITOR // In standalone builds, shaders are never changed. We can early exit
  73. if (material != null)
  74. return material;
  75. #endif
  76. if (!GraphicsSettings.TryGetRenderPipelineSettings<Renderer2DResources>(out var renderer2DResources))
  77. return null;
  78. var shader = shaderFunc(renderer2DResources);
  79. if (material != null)
  80. {
  81. if (material.shader != shader)
  82. material = null;
  83. }
  84. if (material == null)
  85. {
  86. material = CoreUtils.CreateEngineMaterial(shader);
  87. material.SetInt(k_ShadowColorMaskID, 1 << (offset + 1));
  88. material.SetPass(pass);
  89. }
  90. return material;
  91. }
  92. internal static Material GetProjectedShadowMaterial(this Renderer2DData rendererData)
  93. {
  94. rendererData.projectedShadowMaterial = GetProjectedShadowMaterial(
  95. rendererData.projectedShadowMaterial,
  96. r => r.projectedShadowShader,
  97. 0, 0);
  98. return rendererData.projectedShadowMaterial;
  99. }
  100. internal static Material GetProjectedUnshadowMaterial(this Renderer2DData rendererData)
  101. {
  102. rendererData.projectedUnshadowMaterial = GetProjectedShadowMaterial(
  103. rendererData.projectedUnshadowMaterial,
  104. r => r.projectedShadowShader,
  105. 1, 1);
  106. return rendererData.projectedUnshadowMaterial;
  107. }
  108. private static Material GetSpriteShadowMaterial(this Renderer2DData rendererData)
  109. {
  110. rendererData.spriteSelfShadowMaterial = GetProjectedShadowMaterial(
  111. rendererData.spriteSelfShadowMaterial,
  112. r => r.spriteShadowShader,
  113. 0, 0);
  114. return rendererData.spriteSelfShadowMaterial;
  115. }
  116. private static Material GetSpriteUnshadowMaterial(this Renderer2DData rendererData)
  117. {
  118. rendererData.spriteUnshadowMaterial = GetProjectedShadowMaterial(
  119. rendererData.spriteUnshadowMaterial,
  120. r => r.spriteUnshadowShader,
  121. 1, 0);
  122. return rendererData.spriteUnshadowMaterial;
  123. }
  124. private static Material GetGeometryShadowMaterial(this Renderer2DData rendererData)
  125. {
  126. rendererData.geometrySelfShadowMaterial = GetProjectedShadowMaterial(
  127. rendererData.geometrySelfShadowMaterial,
  128. r => r.geometryShadowShader,
  129. 0, 0);
  130. return rendererData.geometrySelfShadowMaterial;
  131. }
  132. private static Material GetGeometryUnshadowMaterial(this Renderer2DData rendererData)
  133. {
  134. rendererData.geometryUnshadowMaterial = GetProjectedShadowMaterial(
  135. rendererData.geometryUnshadowMaterial,
  136. r => r.geometryUnshadowShader,
  137. 1, 0);
  138. return rendererData.geometryUnshadowMaterial;
  139. }
  140. private static void CalculateFrustumCornersPerspective(Camera camera, float distance, NativeArray<Vector3> corners)
  141. {
  142. float verticalFieldOfView = camera.fieldOfView; // This will need to be converted if user direction is allowed
  143. float halfHeight = Mathf.Tan(0.5f * verticalFieldOfView * Mathf.Deg2Rad) * distance;
  144. float halfWidth = halfHeight * camera.aspect;
  145. corners[0] = new Vector3(halfWidth, halfHeight, distance);
  146. corners[1] = new Vector3(halfWidth, -halfHeight, distance);
  147. corners[2] = new Vector3(-halfWidth, halfHeight, distance);
  148. corners[3] = new Vector3(-halfWidth, -halfHeight, distance);
  149. }
  150. private static void CalculateFrustumCornersOrthographic(Camera camera, float distance, NativeArray<Vector3> corners)
  151. {
  152. float halfHeight = camera.orthographicSize;
  153. float halfWidth = halfHeight * camera.aspect;
  154. corners[0] = new Vector3(halfWidth, halfHeight, distance);
  155. corners[1] = new Vector3(halfWidth, -halfHeight, distance);
  156. corners[2] = new Vector3(-halfWidth, halfHeight, distance);
  157. corners[3] = new Vector3(-halfWidth, -halfHeight, distance);
  158. }
  159. private static Bounds CalculateWorldSpaceBounds(Camera camera, ILight2DCullResult cullResult)
  160. {
  161. // TODO: This will need to take into account on screen lights as shadows can be cast from offscreen.
  162. const int k_Corners = 4;
  163. NativeArray<Vector3> nearCorners = new NativeArray<Vector3>(k_Corners, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  164. NativeArray<Vector3> farCorners = new NativeArray<Vector3>(k_Corners, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
  165. if (camera.orthographic)
  166. {
  167. CalculateFrustumCornersOrthographic(camera, camera.nearClipPlane, nearCorners);
  168. CalculateFrustumCornersOrthographic(camera, camera.farClipPlane, farCorners);
  169. }
  170. else
  171. {
  172. CalculateFrustumCornersPerspective(camera, camera.nearClipPlane, nearCorners);
  173. CalculateFrustumCornersPerspective(camera, camera.farClipPlane, farCorners);
  174. }
  175. Vector3 minCorner = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  176. Vector3 maxCorner = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  177. for (int i = 0; i < k_Corners; i++)
  178. {
  179. maxCorner = Vector3.Max(maxCorner, nearCorners[i]);
  180. maxCorner = Vector3.Max(maxCorner, farCorners[i]);
  181. minCorner = Vector3.Min(minCorner, nearCorners[i]);
  182. minCorner = Vector3.Min(minCorner, farCorners[i]);
  183. }
  184. nearCorners.Dispose();
  185. farCorners.Dispose();
  186. // Transform the point from camera space to world space
  187. maxCorner = camera.transform.TransformPoint(maxCorner);
  188. minCorner = camera.transform.TransformPoint(minCorner);
  189. // TODO: Iterate through the lights
  190. for (int i = 0; i < cullResult.visibleLights.Count; i++)
  191. {
  192. Vector3 lightPos = cullResult.visibleLights[i].transform.position;
  193. maxCorner = Vector3.Max(maxCorner, lightPos);
  194. minCorner = Vector3.Min(minCorner, lightPos);
  195. }
  196. Vector3 center = 0.5f * (minCorner + maxCorner);
  197. Vector3 size = maxCorner - minCorner;
  198. return new Bounds(center, size); ;
  199. }
  200. internal static void CallOnBeforeRender(Camera camera, ILight2DCullResult cullResult)
  201. {
  202. if (ShadowCasterGroup2DManager.shadowCasterGroups != null)
  203. {
  204. Bounds bounds = CalculateWorldSpaceBounds(camera, cullResult);
  205. List<ShadowCasterGroup2D> groups = ShadowCasterGroup2DManager.shadowCasterGroups;
  206. for (int groupIndex = 0; groupIndex < groups.Count; groupIndex++)
  207. {
  208. ShadowCasterGroup2D group = groups[groupIndex];
  209. List<ShadowCaster2D> shadowCasters = group.GetShadowCasters();
  210. if (shadowCasters != null)
  211. {
  212. for (int shadowCasterIndex = 0; shadowCasterIndex < shadowCasters.Count; shadowCasterIndex++)
  213. {
  214. ShadowCaster2D shadowCaster = shadowCasters[shadowCasterIndex];
  215. if (shadowCaster != null && shadowCaster.shadowCastingSource == ShadowCaster2D.ShadowCastingSources.ShapeProvider)
  216. {
  217. ShapeProviderUtility.CallOnBeforeRender(shadowCaster.shadowShape2DProvider, shadowCaster.shadowShape2DComponent, shadowCaster.m_ShadowMesh, bounds);
  218. }
  219. }
  220. }
  221. }
  222. }
  223. }
  224. private static void CreateShadowRenderTexture(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int shadowIndex)
  225. {
  226. CreateShadowRenderTexture(pass, m_RenderTargetIds[shadowIndex], renderingData, cmdBuffer);
  227. }
  228. internal static void PrerenderShadows(UnsafeCommandBuffer cmdBuffer, Renderer2DData rendererData, ref LayerBatch layer, Light2D light, int shadowIndex, float shadowIntensity)
  229. {
  230. RenderShadows(cmdBuffer, rendererData, ref layer, light);
  231. }
  232. internal static bool PrerenderShadows(this IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, ref LayerBatch layer, Light2D light, int shadowIndex, float shadowIntensity)
  233. {
  234. ShadowRendering.CreateShadowRenderTexture(pass, renderingData, cmdBuffer, shadowIndex);
  235. bool hadShadowsToRender = layer.shadowCasters.Count != 0;
  236. if (hadShadowsToRender)
  237. {
  238. cmdBuffer.SetRenderTarget(m_RenderTargets[shadowIndex].nameID, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
  239. cmdBuffer.ClearRenderTarget(RTClearFlags.All, Color.clear, 1, 0);
  240. RenderShadows(CommandBufferHelpers.GetUnsafeCommandBuffer(cmdBuffer), pass.rendererData, ref layer, light);
  241. }
  242. m_LightInputTextures[shadowIndex] = m_RenderTargets[shadowIndex].nameID;
  243. return hadShadowsToRender;
  244. }
  245. private static void CreateShadowRenderTexture(IRenderPass2D pass, int handleId, RenderingData renderingData, CommandBuffer cmdBuffer)
  246. {
  247. var renderTextureScale = Mathf.Clamp(pass.rendererData.lightRenderTextureScale, 0.01f, 1.0f);
  248. var width = (int)(renderingData.cameraData.cameraTargetDescriptor.width * renderTextureScale);
  249. var height = (int)(renderingData.cameraData.cameraTargetDescriptor.height * renderTextureScale);
  250. var descriptor = new RenderTextureDescriptor(width, height);
  251. descriptor.useMipMap = false;
  252. descriptor.autoGenerateMips = false;
  253. descriptor.depthBufferBits = 24;
  254. descriptor.graphicsFormat = GraphicsFormat.B10G11R11_UFloatPack32;
  255. descriptor.msaaSamples = 1;
  256. descriptor.dimension = TextureDimension.Tex2D;
  257. cmdBuffer.GetTemporaryRT(handleId, descriptor, FilterMode.Bilinear);
  258. }
  259. internal static void ReleaseShadowRenderTexture(CommandBuffer cmdBuffer, int shadowIndex)
  260. {
  261. cmdBuffer.ReleaseTemporaryRT(m_RenderTargetIds[shadowIndex]);
  262. }
  263. private static void SetShadowProjectionGlobals(UnsafeCommandBuffer cmdBuffer, ShadowCaster2D shadowCaster, Light2D light)
  264. {
  265. cmdBuffer.SetGlobalVector(k_ShadowModelScaleID, shadowCaster.m_CachedLossyScale);
  266. cmdBuffer.SetGlobalMatrix(k_ShadowModelMatrixID, shadowCaster.m_CachedShadowMatrix);
  267. cmdBuffer.SetGlobalMatrix(k_ShadowModelInvMatrixID, shadowCaster.m_CachedInverseShadowMatrix);
  268. cmdBuffer.SetGlobalFloat(k_ShadowSoftnessFalloffIntensityID, light.shadowSoftnessFalloffIntensity);
  269. if (shadowCaster.edgeProcessing == ShadowCaster2D.EdgeProcessing.None)
  270. cmdBuffer.SetGlobalFloat(k_ShadowContractionDistanceID, shadowCaster.trimEdge);
  271. else
  272. cmdBuffer.SetGlobalFloat(k_ShadowContractionDistanceID, 0f);
  273. }
  274. internal static void SetGlobalShadowTexture(CommandBuffer cmdBuffer, Light2D light, int shadowIndex)
  275. {
  276. var textureIndex = shadowIndex;
  277. cmdBuffer.SetGlobalTexture("_ShadowTex", m_LightInputTextures[textureIndex]);
  278. cmdBuffer.SetGlobalColor(k_ShadowShadowColorID, k_ShadowColorLookup);
  279. cmdBuffer.SetGlobalColor(k_ShadowUnshadowColorID, k_UnshadowColorLookup);
  280. }
  281. internal static void SetGlobalShadowProp(IRasterCommandBuffer cmdBuffer)
  282. {
  283. cmdBuffer.SetGlobalColor(k_ShadowShadowColorID, k_ShadowColorLookup);
  284. cmdBuffer.SetGlobalColor(k_ShadowUnshadowColorID, k_UnshadowColorLookup);
  285. }
  286. static bool ShadowCasterIsVisible(ShadowCaster2D shadowCaster)
  287. {
  288. #if UNITY_EDITOR
  289. return SceneVisibilityManager.instance == null ? true : !SceneVisibilityManager.instance.IsHidden(shadowCaster.gameObject);
  290. #else
  291. return true;
  292. #endif
  293. }
  294. static Renderer GetRendererFromCaster(ShadowCaster2D shadowCaster, Light2D light, int layerToRender)
  295. {
  296. Renderer renderer = null;
  297. if (shadowCaster.IsLit(light))
  298. {
  299. if (shadowCaster != null && shadowCaster.IsShadowedLayer(layerToRender))
  300. {
  301. shadowCaster.TryGetComponent<Renderer>(out renderer);
  302. }
  303. }
  304. return renderer;
  305. }
  306. private static void RenderProjectedShadows(UnsafeCommandBuffer cmdBuffer, int layerToRender, Light2D light, List<ShadowCaster2D> shadowCasters, Material projectedShadowsMaterial, int pass)
  307. {
  308. // Draw the projected shadows for the shadow caster group. Writing into the group stencil buffer bit
  309. for (var i = 0; i < shadowCasters.Count; i++)
  310. {
  311. var shadowCaster = shadowCasters[i];
  312. if (ShadowCasterIsVisible(shadowCaster) && shadowCaster.castsShadows && shadowCaster.IsLit(light))
  313. {
  314. if (shadowCaster != null && projectedShadowsMaterial != null && shadowCaster.IsShadowedLayer(layerToRender))
  315. {
  316. if (shadowCaster.shadowCastingSource != ShadowCaster2D.ShadowCastingSources.None && shadowCaster.mesh != null)
  317. {
  318. SetShadowProjectionGlobals(cmdBuffer, shadowCaster, light);
  319. cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedShadowsMaterial, 0, pass);
  320. }
  321. }
  322. }
  323. }
  324. }
  325. static int GetRendererSubmeshes(Renderer renderer, ShadowCaster2D shadowCaster2D)
  326. {
  327. int numberOfSubmeshes;
  328. #if USING_SPRITESHAPE
  329. if (renderer is SpriteShapeRenderer)
  330. {
  331. SpriteShapeRenderer spriteShapeRenderer = (SpriteShapeRenderer)renderer;
  332. numberOfSubmeshes = spriteShapeRenderer.GetSplineMeshCount();
  333. }
  334. else
  335. {
  336. numberOfSubmeshes = shadowCaster2D.spriteMaterialCount;
  337. }
  338. #else
  339. numberOfSubmeshes = shadowCaster2D.spriteMaterialCount;
  340. #endif
  341. return numberOfSubmeshes;
  342. }
  343. private static void RenderSelfShadowOption(UnsafeCommandBuffer cmdBuffer, int layerToRender, Light2D light, List<ShadowCaster2D> shadowCasters, Material projectedUnshadowMaterial, Material spriteShadowMaterial, Material spriteUnshadowMaterial, Material geometryShadowMaterial, Material geometryUnshadowMaterial)
  344. {
  345. // Draw the sprites, either as self shadowing or unshadowing
  346. for (var i = 0; i < shadowCasters.Count; i++)
  347. {
  348. ShadowCaster2D shadowCaster = shadowCasters[i];
  349. if (!shadowCaster.IsLit(light))
  350. continue;
  351. Renderer renderer = GetRendererFromCaster(shadowCaster, light, layerToRender);
  352. cmdBuffer.SetGlobalFloat(k_ShadowAlphaCutoffID, shadowCaster.alphaCutoff);
  353. if (renderer != null)
  354. {
  355. if (ShadowCasterIsVisible(shadowCaster) && shadowCaster.selfShadows)
  356. {
  357. int numberOfSubmeshes = GetRendererSubmeshes(renderer, shadowCaster);
  358. for (int submeshIndex = 0; submeshIndex < numberOfSubmeshes; submeshIndex++)
  359. cmdBuffer.DrawRenderer(renderer, spriteShadowMaterial, submeshIndex, 0);
  360. }
  361. else
  362. {
  363. int numberOfSubmeshes = GetRendererSubmeshes(renderer, shadowCaster);
  364. for (int submeshIndex = 0; submeshIndex < numberOfSubmeshes; submeshIndex++)
  365. {
  366. cmdBuffer.DrawRenderer(renderer, spriteUnshadowMaterial, submeshIndex, 0);
  367. }
  368. }
  369. }
  370. else
  371. {
  372. if (shadowCaster.mesh != null)
  373. {
  374. if (ShadowCasterIsVisible(shadowCaster) && shadowCaster.selfShadows)
  375. cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, geometryShadowMaterial, 0, 0);
  376. else
  377. cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, geometryUnshadowMaterial, 0, 0);
  378. }
  379. }
  380. }
  381. // Draw a masked projected shadow that is inside the sprite to remove the shadow (on different channel)
  382. for (var i = 0; i < shadowCasters.Count; i++)
  383. {
  384. ShadowCaster2D shadowCaster = shadowCasters[i];
  385. if (ShadowCasterIsVisible(shadowCaster) && shadowCaster.IsLit(light) && shadowCaster.castingOption == ShadowCaster2D.ShadowCastingOptions.CastShadow && shadowCaster.mesh != null)
  386. {
  387. SetShadowProjectionGlobals(cmdBuffer, shadowCaster, light);
  388. cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedUnshadowMaterial, 0, 1);
  389. }
  390. }
  391. // Fix up shadow removal with transparency
  392. for (var i = 0; i < shadowCasters.Count; i++)
  393. {
  394. ShadowCaster2D shadowCaster = shadowCasters[i];
  395. if (ShadowCasterIsVisible(shadowCaster) && !shadowCaster.selfShadows && shadowCaster.IsLit(light))
  396. {
  397. Renderer renderer = GetRendererFromCaster(shadowCaster, light, layerToRender);
  398. if (renderer != null)
  399. {
  400. int numberOfSubmeshes = GetRendererSubmeshes(renderer, shadowCaster);
  401. for (int submeshIndex = 0; submeshIndex < numberOfSubmeshes; submeshIndex++)
  402. {
  403. cmdBuffer.DrawRenderer(renderer, spriteUnshadowMaterial, submeshIndex, 1);
  404. }
  405. }
  406. else
  407. {
  408. if(shadowCaster.mesh != null)
  409. cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, geometryUnshadowMaterial, 0, 1);
  410. }
  411. }
  412. }
  413. }
  414. private static void RenderShadows(UnsafeCommandBuffer cmdBuffer, Renderer2DData rendererData, ref LayerBatch layer, Light2D light)
  415. {
  416. using (new ProfilingScope(cmdBuffer, m_ProfilingSamplerShadows))
  417. {
  418. var shadowRadius = light.boundingSphere.radius + (light.transform.position - light.boundingSphere.position).magnitude;
  419. cmdBuffer.SetGlobalVector(k_LightPosID, light.transform.position);
  420. cmdBuffer.SetGlobalFloat(k_ShadowRadiusID, shadowRadius);
  421. cmdBuffer.SetGlobalFloat(k_SoftShadowAngle, Mathf.Deg2Rad * light.shadowSoftness * k_MaxShadowSoftnessAngle);
  422. var projectedShadowMaterial = rendererData.GetProjectedShadowMaterial();
  423. var projectedUnshadowMaterial = rendererData.GetProjectedUnshadowMaterial();
  424. var spriteShadowMaterial = rendererData.GetSpriteShadowMaterial();
  425. var spriteUnshadowMaterial = rendererData.GetSpriteUnshadowMaterial();
  426. var geometryShadowMaterial = rendererData.GetGeometryShadowMaterial();
  427. var geometryUnshadowMaterial = rendererData.GetGeometryUnshadowMaterial();
  428. for (var group = 0; group < layer.shadowCasters.Count; group++)
  429. {
  430. var shadowCasters = layer.shadowCasters[group].GetShadowCasters();
  431. // Draw the projected shadows for the shadow caster group. Only writes the composite stencil bit
  432. RenderProjectedShadows(cmdBuffer, layer.startLayerID, light, shadowCasters, projectedShadowMaterial, 0);
  433. // Render self shadowing or non self shadowing
  434. RenderSelfShadowOption(cmdBuffer, layer.startLayerID, light, shadowCasters, projectedUnshadowMaterial, spriteShadowMaterial, spriteUnshadowMaterial, geometryShadowMaterial, geometryUnshadowMaterial);
  435. }
  436. }
  437. }
  438. }
  439. }