Brak opisu
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.

ScreenSpaceShadows.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. using System;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. namespace UnityEngine.Rendering.Universal
  5. {
  6. [Serializable]
  7. internal class ScreenSpaceShadowsSettings
  8. {
  9. }
  10. [SupportedOnRenderer(typeof(UniversalRendererData))]
  11. [DisallowMultipleRendererFeature("Screen Space Shadows")]
  12. [Tooltip("Screen Space Shadows")]
  13. [URPHelpURL("renderer-feature-screen-space-shadows")]
  14. internal class ScreenSpaceShadows : ScriptableRendererFeature
  15. {
  16. #if UNITY_EDITOR
  17. [UnityEditor.ShaderKeywordFilter.SelectIf(true, keywordNames: ShaderKeywordStrings.MainLightShadowScreen)]
  18. private const bool k_RequiresScreenSpaceShadowsKeyword = true;
  19. #endif
  20. // Serialized Fields
  21. [SerializeField, HideInInspector] private Shader m_Shader = null;
  22. [SerializeField] private ScreenSpaceShadowsSettings m_Settings = new ScreenSpaceShadowsSettings();
  23. // Private Fields
  24. private Material m_Material;
  25. private ScreenSpaceShadowsPass m_SSShadowsPass = null;
  26. private ScreenSpaceShadowsPostPass m_SSShadowsPostPass = null;
  27. // Constants
  28. private const string k_ShaderName = "Hidden/Universal Render Pipeline/ScreenSpaceShadows";
  29. /// <inheritdoc/>
  30. public override void Create()
  31. {
  32. if (m_SSShadowsPass == null)
  33. m_SSShadowsPass = new ScreenSpaceShadowsPass();
  34. if (m_SSShadowsPostPass == null)
  35. m_SSShadowsPostPass = new ScreenSpaceShadowsPostPass();
  36. LoadMaterial();
  37. m_SSShadowsPass.renderPassEvent = RenderPassEvent.AfterRenderingGbuffer;
  38. m_SSShadowsPostPass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
  39. }
  40. /// <inheritdoc/>
  41. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  42. {
  43. if (UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData))
  44. return;
  45. if (!LoadMaterial())
  46. {
  47. Debug.LogErrorFormat(
  48. "{0}.AddRenderPasses(): Missing material. {1} render pass will not be added. Check for missing reference in the renderer resources.",
  49. GetType().Name, name);
  50. return;
  51. }
  52. bool allowMainLightShadows = renderingData.shadowData.supportsMainLightShadows && renderingData.lightData.mainLightIndex != -1;
  53. bool shouldEnqueue = allowMainLightShadows && m_SSShadowsPass.Setup(m_Settings, m_Material);
  54. if (shouldEnqueue)
  55. {
  56. bool isDeferredRenderingMode = renderer is UniversalRenderer && ((UniversalRenderer)renderer).renderingModeRequested == RenderingMode.Deferred;
  57. m_SSShadowsPass.renderPassEvent = isDeferredRenderingMode
  58. ? RenderPassEvent.AfterRenderingGbuffer
  59. : RenderPassEvent.AfterRenderingPrePasses + 1; // We add 1 to ensure this happens after depth priming depth copy pass that might be scheduled
  60. renderer.EnqueuePass(m_SSShadowsPass);
  61. renderer.EnqueuePass(m_SSShadowsPostPass);
  62. }
  63. }
  64. /// <inheritdoc/>
  65. protected override void Dispose(bool disposing)
  66. {
  67. m_SSShadowsPass?.Dispose();
  68. m_SSShadowsPass = null;
  69. CoreUtils.Destroy(m_Material);
  70. }
  71. private bool LoadMaterial()
  72. {
  73. if (m_Material != null)
  74. {
  75. return true;
  76. }
  77. if (m_Shader == null)
  78. {
  79. m_Shader = Shader.Find(k_ShaderName);
  80. if (m_Shader == null)
  81. {
  82. return false;
  83. }
  84. }
  85. m_Material = CoreUtils.CreateEngineMaterial(m_Shader);
  86. return m_Material != null;
  87. }
  88. private class ScreenSpaceShadowsPass : ScriptableRenderPass
  89. {
  90. // Profiling tag
  91. private static string m_ProfilerTag = "ScreenSpaceShadows";
  92. private static ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
  93. // Private Variables
  94. private Material m_Material;
  95. private ScreenSpaceShadowsSettings m_CurrentSettings;
  96. private RTHandle m_RenderTarget;
  97. private int m_ScreenSpaceShadowmapTextureID;
  98. private PassData m_PassData;
  99. internal ScreenSpaceShadowsPass()
  100. {
  101. m_CurrentSettings = new ScreenSpaceShadowsSettings();
  102. m_ScreenSpaceShadowmapTextureID = Shader.PropertyToID("_ScreenSpaceShadowmapTexture");
  103. m_PassData = new PassData();
  104. }
  105. public void Dispose()
  106. {
  107. m_RenderTarget?.Release();
  108. }
  109. internal bool Setup(ScreenSpaceShadowsSettings featureSettings, Material material)
  110. {
  111. m_CurrentSettings = featureSettings;
  112. m_Material = material;
  113. ConfigureInput(ScriptableRenderPassInput.Depth);
  114. return m_Material != null;
  115. }
  116. /// <inheritdoc/>
  117. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  118. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  119. {
  120. var desc = renderingData.cameraData.cameraTargetDescriptor;
  121. desc.depthBufferBits = 0;
  122. desc.msaaSamples = 1;
  123. // UUM-41070: We require `Linear | Render` but with the deprecated FormatUsage this was checking `Blend`
  124. // For now, we keep checking for `Blend` until the performance hit of doing the correct checks is evaluated
  125. desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R8_UNorm, GraphicsFormatUsage.Blend)
  126. ? GraphicsFormat.R8_UNorm
  127. : GraphicsFormat.B8G8R8A8_UNorm;
  128. RenderingUtils.ReAllocateHandleIfNeeded(ref m_RenderTarget, desc, FilterMode.Point, TextureWrapMode.Clamp, name: "_ScreenSpaceShadowmapTexture");
  129. cmd.SetGlobalTexture(m_RenderTarget.name, m_RenderTarget.nameID);
  130. // Disable obsolete warning for internal usage
  131. #pragma warning disable CS0618
  132. ConfigureTarget(m_RenderTarget);
  133. ConfigureClear(ClearFlag.None, Color.white);
  134. #pragma warning restore CS0618
  135. }
  136. private class PassData
  137. {
  138. internal TextureHandle target;
  139. internal Material material;
  140. internal int shadowmapID;
  141. }
  142. /// <summary>
  143. /// Initialize the shared pass data.
  144. /// </summary>
  145. /// <param name="passData"></param>
  146. private void InitPassData(ref PassData passData)
  147. {
  148. passData.material = m_Material;
  149. passData.shadowmapID = m_ScreenSpaceShadowmapTextureID;
  150. }
  151. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  152. {
  153. if (m_Material == null)
  154. {
  155. Debug.LogErrorFormat("{0}.Execute(): Missing material. ScreenSpaceShadows pass will not execute. Check for missing reference in the renderer resources.", GetType().Name);
  156. return;
  157. }
  158. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  159. var desc = cameraData.cameraTargetDescriptor;
  160. desc.depthBufferBits = 0;
  161. desc.msaaSamples = 1;
  162. // UUM-41070: We require `Linear | Render` but with the deprecated FormatUsage this was checking `Blend`
  163. // For now, we keep checking for `Blend` until the performance hit of doing the correct checks is evaluated
  164. desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R8_UNorm, GraphicsFormatUsage.Blend)
  165. ? GraphicsFormat.R8_UNorm
  166. : GraphicsFormat.B8G8R8A8_UNorm;
  167. TextureHandle color = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "_ScreenSpaceShadowmapTexture", true);
  168. using (var builder = renderGraph.AddRasterRenderPass<PassData>("Blit Screen Space Shadows", out var passData, m_ProfilingSampler))
  169. {
  170. passData.target = color;
  171. builder.SetRenderAttachment(color, 0, AccessFlags.Write);
  172. InitPassData(ref passData);
  173. builder.AllowGlobalStateModification(true);
  174. if (color.IsValid())
  175. builder.SetGlobalTextureAfterPass(color, m_ScreenSpaceShadowmapTextureID);
  176. builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) =>
  177. {
  178. ExecutePass(rgContext.cmd, data, data.target);
  179. });
  180. }
  181. }
  182. private static void ExecutePass(RasterCommandBuffer cmd, PassData data, RTHandle target)
  183. {
  184. Blitter.BlitTexture(cmd, target, Vector2.one, data.material, 0);
  185. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadows, false);
  186. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowCascades, false);
  187. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowScreen, true);
  188. }
  189. /// <inheritdoc/>
  190. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  191. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  192. {
  193. if (m_Material == null)
  194. {
  195. Debug.LogErrorFormat("{0}.Execute(): Missing material. ScreenSpaceShadows pass will not execute. Check for missing reference in the renderer resources.", GetType().Name);
  196. return;
  197. }
  198. InitPassData(ref m_PassData);
  199. var cmd = renderingData.commandBuffer;
  200. using (new ProfilingScope(cmd, m_ProfilingSampler))
  201. {
  202. ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), m_PassData, m_RenderTarget);
  203. }
  204. }
  205. }
  206. private class ScreenSpaceShadowsPostPass : ScriptableRenderPass
  207. {
  208. // Profiling tag
  209. private static string m_ProfilerTag = "ScreenSpaceShadows Post";
  210. private static ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
  211. private static readonly RTHandle k_CurrentActive = RTHandles.Alloc(BuiltinRenderTextureType.CurrentActive);
  212. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  213. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
  214. {
  215. // Disable obsolete warning for internal usage
  216. #pragma warning disable CS0618
  217. ConfigureTarget(k_CurrentActive);
  218. #pragma warning restore CS0618
  219. }
  220. private static void ExecutePass(RasterCommandBuffer cmd, UniversalShadowData shadowData)
  221. {
  222. int cascadesCount = shadowData.mainLightShadowCascadesCount;
  223. bool mainLightShadows = shadowData.supportsMainLightShadows;
  224. bool receiveShadowsNoCascade = mainLightShadows && cascadesCount == 1;
  225. bool receiveShadowsCascades = mainLightShadows && cascadesCount > 1;
  226. // Before transparent object pass, force to disable screen space shadow of main light
  227. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowScreen, false);
  228. // then enable main light shadows with or without cascades
  229. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadows, receiveShadowsNoCascade);
  230. cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowCascades, receiveShadowsCascades);
  231. }
  232. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  233. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  234. {
  235. var cmd = renderingData.commandBuffer;
  236. UniversalShadowData shadowData = renderingData.frameData.Get<UniversalShadowData>();
  237. using (new ProfilingScope(cmd, m_ProfilingSampler))
  238. {
  239. ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), shadowData);
  240. }
  241. }
  242. internal class PassData
  243. {
  244. internal ScreenSpaceShadowsPostPass pass;
  245. internal UniversalShadowData shadowData;
  246. }
  247. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  248. {
  249. using (var builder = renderGraph.AddRasterRenderPass<PassData>("Set Screen Space Shadow Keywords", out var passData, m_ProfilingSampler))
  250. {
  251. UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
  252. TextureHandle color = resourceData.activeColorTexture;
  253. builder.SetRenderAttachment(color, 0, AccessFlags.Write);
  254. passData.shadowData = frameData.Get<UniversalShadowData>();
  255. passData.pass = this;
  256. builder.AllowGlobalStateModification(true);
  257. builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) =>
  258. {
  259. ExecutePass(rgContext.cmd, data.shadowData);
  260. });
  261. }
  262. }
  263. }
  264. }
  265. }