123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- using System;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.Rendering.RenderGraphModule;
-
- namespace UnityEngine.Rendering.Universal
- {
- [Serializable]
- internal class ScreenSpaceShadowsSettings
- {
- }
-
- [SupportedOnRenderer(typeof(UniversalRendererData))]
- [DisallowMultipleRendererFeature("Screen Space Shadows")]
- [Tooltip("Screen Space Shadows")]
- [URPHelpURL("renderer-feature-screen-space-shadows")]
- internal class ScreenSpaceShadows : ScriptableRendererFeature
- {
- #if UNITY_EDITOR
- [UnityEditor.ShaderKeywordFilter.SelectIf(true, keywordNames: ShaderKeywordStrings.MainLightShadowScreen)]
- private const bool k_RequiresScreenSpaceShadowsKeyword = true;
- #endif
-
- // Serialized Fields
- [SerializeField, HideInInspector] private Shader m_Shader = null;
- [SerializeField] private ScreenSpaceShadowsSettings m_Settings = new ScreenSpaceShadowsSettings();
-
- // Private Fields
- private Material m_Material;
- private ScreenSpaceShadowsPass m_SSShadowsPass = null;
- private ScreenSpaceShadowsPostPass m_SSShadowsPostPass = null;
-
- // Constants
- private const string k_ShaderName = "Hidden/Universal Render Pipeline/ScreenSpaceShadows";
-
- /// <inheritdoc/>
- public override void Create()
- {
- if (m_SSShadowsPass == null)
- m_SSShadowsPass = new ScreenSpaceShadowsPass();
- if (m_SSShadowsPostPass == null)
- m_SSShadowsPostPass = new ScreenSpaceShadowsPostPass();
-
- LoadMaterial();
-
- m_SSShadowsPass.renderPassEvent = RenderPassEvent.AfterRenderingGbuffer;
- m_SSShadowsPostPass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
- }
-
- /// <inheritdoc/>
- public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
- {
- if (UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData))
- return;
-
- if (!LoadMaterial())
- {
- Debug.LogErrorFormat(
- "{0}.AddRenderPasses(): Missing material. {1} render pass will not be added. Check for missing reference in the renderer resources.",
- GetType().Name, name);
- return;
- }
-
- bool allowMainLightShadows = renderingData.shadowData.supportsMainLightShadows && renderingData.lightData.mainLightIndex != -1;
- bool shouldEnqueue = allowMainLightShadows && m_SSShadowsPass.Setup(m_Settings, m_Material);
-
- if (shouldEnqueue)
- {
- bool isDeferredRenderingMode = renderer is UniversalRenderer && ((UniversalRenderer)renderer).renderingModeRequested == RenderingMode.Deferred;
-
- m_SSShadowsPass.renderPassEvent = isDeferredRenderingMode
- ? RenderPassEvent.AfterRenderingGbuffer
- : RenderPassEvent.AfterRenderingPrePasses + 1; // We add 1 to ensure this happens after depth priming depth copy pass that might be scheduled
-
- renderer.EnqueuePass(m_SSShadowsPass);
- renderer.EnqueuePass(m_SSShadowsPostPass);
- }
- }
-
- /// <inheritdoc/>
- protected override void Dispose(bool disposing)
- {
- m_SSShadowsPass?.Dispose();
- m_SSShadowsPass = null;
- CoreUtils.Destroy(m_Material);
- }
-
- private bool LoadMaterial()
- {
- if (m_Material != null)
- {
- return true;
- }
-
- if (m_Shader == null)
- {
- m_Shader = Shader.Find(k_ShaderName);
- if (m_Shader == null)
- {
- return false;
- }
- }
-
- m_Material = CoreUtils.CreateEngineMaterial(m_Shader);
-
- return m_Material != null;
- }
-
- private class ScreenSpaceShadowsPass : ScriptableRenderPass
- {
- // Profiling tag
- private static string m_ProfilerTag = "ScreenSpaceShadows";
- private static ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
-
- // Private Variables
- private Material m_Material;
- private ScreenSpaceShadowsSettings m_CurrentSettings;
- private RTHandle m_RenderTarget;
- private int m_ScreenSpaceShadowmapTextureID;
- private PassData m_PassData;
-
- internal ScreenSpaceShadowsPass()
- {
- m_CurrentSettings = new ScreenSpaceShadowsSettings();
- m_ScreenSpaceShadowmapTextureID = Shader.PropertyToID("_ScreenSpaceShadowmapTexture");
- m_PassData = new PassData();
- }
-
- public void Dispose()
- {
- m_RenderTarget?.Release();
- }
-
- internal bool Setup(ScreenSpaceShadowsSettings featureSettings, Material material)
- {
- m_CurrentSettings = featureSettings;
- m_Material = material;
- ConfigureInput(ScriptableRenderPassInput.Depth);
-
- return m_Material != null;
- }
-
- /// <inheritdoc/>
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
- {
- var desc = renderingData.cameraData.cameraTargetDescriptor;
- desc.depthBufferBits = 0;
- desc.msaaSamples = 1;
- // UUM-41070: We require `Linear | Render` but with the deprecated FormatUsage this was checking `Blend`
- // For now, we keep checking for `Blend` until the performance hit of doing the correct checks is evaluated
- desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R8_UNorm, GraphicsFormatUsage.Blend)
- ? GraphicsFormat.R8_UNorm
- : GraphicsFormat.B8G8R8A8_UNorm;
-
- RenderingUtils.ReAllocateHandleIfNeeded(ref m_RenderTarget, desc, FilterMode.Point, TextureWrapMode.Clamp, name: "_ScreenSpaceShadowmapTexture");
- cmd.SetGlobalTexture(m_RenderTarget.name, m_RenderTarget.nameID);
-
- // Disable obsolete warning for internal usage
- #pragma warning disable CS0618
- ConfigureTarget(m_RenderTarget);
- ConfigureClear(ClearFlag.None, Color.white);
- #pragma warning restore CS0618
- }
-
- private class PassData
- {
- internal TextureHandle target;
- internal Material material;
- internal int shadowmapID;
- }
-
- /// <summary>
- /// Initialize the shared pass data.
- /// </summary>
- /// <param name="passData"></param>
- private void InitPassData(ref PassData passData)
- {
- passData.material = m_Material;
- passData.shadowmapID = m_ScreenSpaceShadowmapTextureID;
- }
-
- public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
- {
- if (m_Material == null)
- {
- Debug.LogErrorFormat("{0}.Execute(): Missing material. ScreenSpaceShadows pass will not execute. Check for missing reference in the renderer resources.", GetType().Name);
- return;
- }
- UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
- var desc = cameraData.cameraTargetDescriptor;
- desc.depthBufferBits = 0;
- desc.msaaSamples = 1;
- // UUM-41070: We require `Linear | Render` but with the deprecated FormatUsage this was checking `Blend`
- // For now, we keep checking for `Blend` until the performance hit of doing the correct checks is evaluated
- desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R8_UNorm, GraphicsFormatUsage.Blend)
- ? GraphicsFormat.R8_UNorm
- : GraphicsFormat.B8G8R8A8_UNorm;
- TextureHandle color = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "_ScreenSpaceShadowmapTexture", true);
-
- using (var builder = renderGraph.AddRasterRenderPass<PassData>("Blit Screen Space Shadows", out var passData, m_ProfilingSampler))
- {
- passData.target = color;
- builder.SetRenderAttachment(color, 0, AccessFlags.Write);
-
- InitPassData(ref passData);
- builder.AllowGlobalStateModification(true);
-
- if (color.IsValid())
- builder.SetGlobalTextureAfterPass(color, m_ScreenSpaceShadowmapTextureID);
-
- builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) =>
- {
- ExecutePass(rgContext.cmd, data, data.target);
- });
- }
- }
-
- private static void ExecutePass(RasterCommandBuffer cmd, PassData data, RTHandle target)
- {
- Blitter.BlitTexture(cmd, target, Vector2.one, data.material, 0);
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadows, false);
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowCascades, false);
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowScreen, true);
- }
-
- /// <inheritdoc/>
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- if (m_Material == null)
- {
- Debug.LogErrorFormat("{0}.Execute(): Missing material. ScreenSpaceShadows pass will not execute. Check for missing reference in the renderer resources.", GetType().Name);
- return;
- }
-
- InitPassData(ref m_PassData);
- var cmd = renderingData.commandBuffer;
- using (new ProfilingScope(cmd, m_ProfilingSampler))
- {
- ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), m_PassData, m_RenderTarget);
- }
- }
- }
-
- private class ScreenSpaceShadowsPostPass : ScriptableRenderPass
- {
- // Profiling tag
- private static string m_ProfilerTag = "ScreenSpaceShadows Post";
- private static ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
- private static readonly RTHandle k_CurrentActive = RTHandles.Alloc(BuiltinRenderTextureType.CurrentActive);
-
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
- {
- // Disable obsolete warning for internal usage
- #pragma warning disable CS0618
- ConfigureTarget(k_CurrentActive);
- #pragma warning restore CS0618
- }
-
- private static void ExecutePass(RasterCommandBuffer cmd, UniversalShadowData shadowData)
- {
- int cascadesCount = shadowData.mainLightShadowCascadesCount;
- bool mainLightShadows = shadowData.supportsMainLightShadows;
- bool receiveShadowsNoCascade = mainLightShadows && cascadesCount == 1;
- bool receiveShadowsCascades = mainLightShadows && cascadesCount > 1;
-
- // Before transparent object pass, force to disable screen space shadow of main light
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowScreen, false);
-
- // then enable main light shadows with or without cascades
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadows, receiveShadowsNoCascade);
- cmd.SetKeyword(ShaderGlobalKeywords.MainLightShadowCascades, receiveShadowsCascades);
- }
-
- [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- var cmd = renderingData.commandBuffer;
- UniversalShadowData shadowData = renderingData.frameData.Get<UniversalShadowData>();
-
- using (new ProfilingScope(cmd, m_ProfilingSampler))
- {
- ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), shadowData);
- }
- }
-
- internal class PassData
- {
- internal ScreenSpaceShadowsPostPass pass;
- internal UniversalShadowData shadowData;
- }
- public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
- {
- using (var builder = renderGraph.AddRasterRenderPass<PassData>("Set Screen Space Shadow Keywords", out var passData, m_ProfilingSampler))
- {
- UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
-
- TextureHandle color = resourceData.activeColorTexture;
- builder.SetRenderAttachment(color, 0, AccessFlags.Write);
- passData.shadowData = frameData.Get<UniversalShadowData>();
- passData.pass = this;
-
- builder.AllowGlobalStateModification(true);
-
- builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) =>
- {
- ExecutePass(rgContext.cmd, data.shadowData);
- });
- }
- }
- }
- }
- }
|