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"); /// /// 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; shaderTagIds = k_DepthNormals; } /// /// 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) { 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); enableRenderingLayers = true; } 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); } /// public override void OnCameraCleanup(CommandBuffer cmd) { if (cmd == null) { throw new ArgumentNullException("cmd"); } // 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); // Apply MultiviewRenderRegionsCompatible flag only to the peripheral view in Quad Views if (cameraData.xr.multipassId == 0) { 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(static (PassData data, RasterGraphContext context) => { RenderingLayerUtils.SetupProperties(context.cmd, data.maskSize); ExecutePass(context.cmd, data, data.rendererList); }); } } } }