using System; using System.Collections.Generic; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.Universal.Internal { /// /// Render all objects that have a 'DepthNormals' and/or 'DepthNormalsOnly' pass into the given depth and normal buffers. /// public partial class DepthNormalOnlyPass : ScriptableRenderPass { internal List shaderTagIds { get; set; } internal bool enableRenderingLayers { get; set; } = false; internal RenderingLayerUtils.MaskSize renderingLayersMaskSize { get; set; } private FilteringSettings m_FilteringSettings; // Statics private static readonly List k_DepthNormals = new List { new ShaderTagId("DepthNormals"), new ShaderTagId("DepthNormalsOnly") }; private static readonly List k_DepthNormalsOnly = new List { new ShaderTagId("DepthNormalsOnly") }; internal static readonly string k_CameraNormalsTextureName = "_CameraNormalsTexture"; private static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture"); private static readonly int s_CameraNormalsTextureID = Shader.PropertyToID(k_CameraNormalsTextureName); private static readonly int s_CameraRenderingLayersTextureID = Shader.PropertyToID("_CameraRenderingLayersTexture"); #if URP_COMPATIBILITY_MODE private RTHandle depthHandle { get; set; } private RTHandle normalHandle { get; set; } private RTHandle renderingLayersHandle { get; set; } private PassData m_PassData; private static readonly RTHandle[] k_ColorAttachment1 = new RTHandle[1]; private static readonly RTHandle[] k_ColorAttachment2 = new RTHandle[2]; #endif /// /// Creates a new DepthNormalOnlyPass instance. /// /// The RenderPassEvent to use. /// The RenderQueueRange to use for creating filtering settings that control what objects get rendered. /// The layer mask to use for creating filtering settings that control what objects get rendered. /// /// /// public DepthNormalOnlyPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask) { profilingSampler = ProfilingSampler.Get(URPProfileId.DrawDepthNormalPrepass); m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask); renderPassEvent = evt; this.shaderTagIds = k_DepthNormals; #if URP_COMPATIBILITY_MODE useNativeRenderPass = false; m_PassData = new PassData(); #endif } /// /// Finds the format to use for the normals texture. /// /// The GraphicsFormat to use with the Normals texture. public static GraphicsFormat GetGraphicsFormat() { if (SystemInfo.IsFormatSupported(GraphicsFormat.R8G8B8A8_SNorm, GraphicsFormatUsage.Render)) return GraphicsFormat.R8G8B8A8_SNorm; // Preferred format else if (SystemInfo.IsFormatSupported(GraphicsFormat.R16G16B16A16_SFloat, GraphicsFormatUsage.Render)) return GraphicsFormat.R16G16B16A16_SFloat; // fallback else return GraphicsFormat.R32G32B32A32_SFloat; // fallback } /// /// Configures the pass. /// /// The RTHandle used to render depth to. /// The RTHandle used to render normals. /// public void Setup(RTHandle depthHandle, RTHandle normalHandle) { #if URP_COMPATIBILITY_MODE this.depthHandle = depthHandle; this.normalHandle = normalHandle; #endif enableRenderingLayers = false; } /// /// Configure the pass /// /// The RTHandle used to render depth to. /// The RTHandle used to render normals. /// The RTHandle used to render decals. public void Setup(RTHandle depthHandle, RTHandle normalHandle, RTHandle decalLayerHandle) { Setup(depthHandle, normalHandle); #if URP_COMPATIBILITY_MODE renderingLayersHandle = decalLayerHandle; #endif enableRenderingLayers = true; } #if URP_COMPATIBILITY_MODE /// [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsoleteFrom2023_3)] public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { RTHandle[] colorHandles; if (enableRenderingLayers) { k_ColorAttachment2[0] = normalHandle; k_ColorAttachment2[1] = renderingLayersHandle; colorHandles = k_ColorAttachment2; } else { k_ColorAttachment1[0] = normalHandle; colorHandles = k_ColorAttachment1; } // Disable obsolete warning for internal usage #pragma warning disable CS0618 if (renderingData.cameraData.renderer.useDepthPriming && (renderingData.cameraData.renderType == CameraRenderType.Base || renderingData.cameraData.clearDepth)) ConfigureTarget(colorHandles, renderingData.cameraData.renderer.cameraDepthTargetHandle); else ConfigureTarget(colorHandles, depthHandle); ConfigureClear(ClearFlag.All, Color.black); #pragma warning restore CS0618 } #endif private static void ExecutePass(RasterCommandBuffer cmd, PassData passData, RendererList rendererList) { // Enable Rendering Layers if (passData.enableRenderingLayers) cmd.SetKeyword(ShaderGlobalKeywords.WriteRenderingLayers, true); // Draw cmd.DrawRendererList(rendererList); // Clean up if (passData.enableRenderingLayers) cmd.SetKeyword(ShaderGlobalKeywords.WriteRenderingLayers, false); } #if URP_COMPATIBILITY_MODE /// [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsoleteFrom2023_3)] public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { ContextContainer frameData = renderingData.frameData; UniversalRenderingData universalRenderingData = frameData.Get(); UniversalCameraData cameraData = frameData.Get(); UniversalLightData lightData = frameData.Get(); m_PassData.enableRenderingLayers = enableRenderingLayers; var param = InitRendererListParams(universalRenderingData, cameraData,lightData); var rendererList = context.CreateRendererList(ref param); var cmd = CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer); using (new ProfilingScope(cmd, profilingSampler)) { ExecutePass(cmd, m_PassData, rendererList); } } #endif /// public override void OnCameraCleanup(CommandBuffer cmd) { if (cmd == null) { throw new ArgumentNullException("cmd"); } #if URP_COMPATIBILITY_MODE normalHandle = null; depthHandle = null; renderingLayersHandle = null; #endif // This needs to be reset as the renderer might change this in runtime (UUM-36069) shaderTagIds = k_DepthNormals; } /// /// Shared pass data /// private class PassData { internal bool enableRenderingLayers; internal RenderingLayerUtils.MaskSize maskSize; internal RendererListHandle rendererList; } private RendererListParams InitRendererListParams(UniversalRenderingData renderingData, UniversalCameraData cameraData, UniversalLightData lightData) { var sortFlags = cameraData.defaultOpaqueSortFlags; var drawSettings = RenderingUtils.CreateDrawingSettings(this.shaderTagIds, renderingData, cameraData, lightData, sortFlags); drawSettings.perObjectData = PerObjectData.None; return new RendererListParams(renderingData.cullResults, drawSettings, m_FilteringSettings); } internal void Render(RenderGraph renderGraph, ContextContainer frameData, in TextureHandle cameraNormalsTexture, in TextureHandle depthTexture, in TextureHandle renderingLayersTexture, uint batchLayerMask, bool setGlobalDepth, bool setGlobalNormalAndRenderingLayers, bool allowPartialPass) { if (allowPartialPass) { this.shaderTagIds = k_DepthNormalsOnly; } else { this.shaderTagIds = k_DepthNormals; } UniversalRenderingData renderingData = frameData.Get(); UniversalCameraData cameraData = frameData.Get(); UniversalLightData lightData = frameData.Get(); using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler)) { builder.SetRenderAttachment(cameraNormalsTexture, 0, AccessFlags.Write); builder.SetRenderAttachmentDepth(depthTexture, AccessFlags.ReadWrite); passData.enableRenderingLayers = enableRenderingLayers; if (passData.enableRenderingLayers) { builder.SetRenderAttachment(renderingLayersTexture, 1, AccessFlags.Write); passData.maskSize = renderingLayersMaskSize; } var param = InitRendererListParams(renderingData, cameraData, lightData); param.filteringSettings.batchLayerMask = batchLayerMask; passData.rendererList = renderGraph.CreateRendererList(param); builder.UseRendererList(passData.rendererList); if (cameraData.xr.enabled) { builder.EnableFoveatedRasterization(cameraData.xr.supportsFoveatedRendering && cameraData.xrUniversal.canFoveateIntermediatePasses); builder.SetExtendedFeatureFlags(ExtendedFeatureFlags.MultiviewRenderRegionsCompatible); } if (setGlobalNormalAndRenderingLayers) { builder.SetGlobalTextureAfterPass(cameraNormalsTexture, s_CameraNormalsTextureID); if (passData.enableRenderingLayers) builder.SetGlobalTextureAfterPass(renderingLayersTexture, s_CameraRenderingLayersTextureID); } if (setGlobalDepth) builder.SetGlobalTextureAfterPass(depthTexture, s_CameraDepthTextureID); // Required here because of RenderingLayerUtils.SetupProperties builder.AllowGlobalStateModification(true); builder.SetRenderFunc((PassData data, RasterGraphContext context) => { RenderingLayerUtils.SetupProperties(context.cmd, data.maskSize); ExecutePass(context.cmd, data, data.rendererList); }); } } } }