using UnityEngine.Experimental.Rendering; using UnityEngine.Experimental.Rendering.RenderGraphModule; namespace UnityEngine.Rendering.Universal { /// /// Draw screen space overlay UI into the given color and depth target /// internal class DrawScreenSpaceUIPass : ScriptableRenderPass { PassData m_PassData; RTHandle m_ColorTarget; RTHandle m_DepthTarget; // Whether to render on an offscreen render texture or on the current active render target bool m_RenderOffscreen; /// /// Creates a new DrawScreenSpaceUIPass instance. /// /// The RenderPassEvent to use. /// public DrawScreenSpaceUIPass(RenderPassEvent evt, bool renderOffscreen) { base.profilingSampler = new ProfilingSampler(nameof(DrawScreenSpaceUIPass)); renderPassEvent = evt; useNativeRenderPass = false; m_RenderOffscreen = renderOffscreen; m_PassData = new PassData(); } // Common to RenderGraph and non-RenderGraph paths private class PassData { internal CommandBuffer cmd; internal Camera camera; internal TextureHandle offscreenTexture; } /// /// Get a descriptor for the required color texture for this pass. /// /// Camera target descriptor. /// Unscaled pixel width of the camera. /// Unscaled pixel height of the camera. /// public static void ConfigureColorDescriptor(ref RenderTextureDescriptor descriptor, int cameraWidth, int cameraHeight) { descriptor.graphicsFormat = GraphicsFormat.R8G8B8A8_SRGB; descriptor.depthBufferBits = 0; descriptor.width = cameraWidth; descriptor.height = cameraHeight; } /// /// Get a descriptor for the required depth texture for this pass. /// /// Camera target descriptor. /// Depth stencil format required. /// Unscaled pixel width of the camera. /// Unscaled pixel height of the camera. /// public static void ConfigureDepthDescriptor(ref RenderTextureDescriptor descriptor, int depthBufferBits, int cameraWidth, int cameraHeight) { descriptor.graphicsFormat = GraphicsFormat.None; descriptor.depthBufferBits = depthBufferBits; descriptor.width = cameraWidth; descriptor.height = cameraHeight; } private static void ExecutePass(ScriptableRenderContext context, PassData passData) { context.ExecuteCommandBuffer(passData.cmd); passData.cmd.Clear(); context.DrawUIOverlay(passData.camera); } // Non-RenderGraph path public void Dispose() { m_ColorTarget?.Release(); m_DepthTarget?.Release(); } /// /// Configure the pass with the off-screen destination color texture and depth texture to execute the pass on. /// /// Camera rendering data containing all relevant render target information. /// Depth buffer bits required for depth/stencil effects. public void Setup(ref CameraData cameraData, int depthBufferBits) { if (m_RenderOffscreen) { RenderTextureDescriptor colorDescriptor = cameraData.cameraTargetDescriptor; ConfigureColorDescriptor(ref colorDescriptor, cameraData.pixelWidth, cameraData.pixelHeight); RenderingUtils.ReAllocateIfNeeded(ref m_ColorTarget, colorDescriptor, name: "_OverlayUITexture"); RenderTextureDescriptor depthDescriptor = cameraData.cameraTargetDescriptor; ConfigureDepthDescriptor(ref depthDescriptor, depthBufferBits, cameraData.pixelWidth, cameraData.pixelHeight); RenderingUtils.ReAllocateIfNeeded(ref m_DepthTarget, depthDescriptor, name: "_OverlayUITexture_Depth"); } } /// public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { m_PassData.cmd = renderingData.commandBuffer; m_PassData.camera = renderingData.cameraData.camera; if (m_RenderOffscreen) { CoreUtils.SetRenderTarget(renderingData.commandBuffer, m_ColorTarget, m_DepthTarget, ClearFlag.Color, Color.clear); renderingData.commandBuffer.SetGlobalTexture(ShaderPropertyId.overlayUITexture, m_ColorTarget); } else { DebugHandler debugHandler = GetActiveDebugHandler(ref renderingData); var cameraTarget = RenderingUtils.GetCameraTargetIdentifier(ref renderingData); bool resolveToDebugScreen = debugHandler != null && debugHandler.WriteToDebugScreenTexture(ref renderingData.cameraData); if (resolveToDebugScreen) { CoreUtils.SetRenderTarget(renderingData.commandBuffer, debugHandler.DebugScreenColorHandle, debugHandler.DebugScreenDepthHandle); } else { // Get RTHandle alias to use RTHandle apis RTHandleStaticHelpers.SetRTHandleStaticWrapper(cameraTarget); var colorTargetHandle = RTHandleStaticHelpers.s_RTHandleWrapper; CoreUtils.SetRenderTarget(renderingData.commandBuffer, colorTargetHandle); } } using (new ProfilingScope(renderingData.commandBuffer, ProfilingSampler.Get(URPProfileId.DrawScreenSpaceUI))) { ExecutePass(context, m_PassData); } } //RenderGraph path internal void RenderOffscreen(RenderGraph renderGraph, int depthBufferBits, out TextureHandle output, ref RenderingData renderingData) { using (var builder = renderGraph.AddRenderPass("Draw Screen Space UI Pass - Offscreen", out var passData, base.profilingSampler)) { RenderTextureDescriptor colorDescriptor = renderingData.cameraData.cameraTargetDescriptor; ConfigureColorDescriptor(ref colorDescriptor, renderingData.cameraData.pixelWidth, renderingData.cameraData.pixelHeight); output = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorDescriptor, "_OverlayUITexture", true); builder.UseColorBuffer(output, 0); RenderTextureDescriptor depthDescriptor = renderingData.cameraData.cameraTargetDescriptor; ConfigureDepthDescriptor(ref depthDescriptor, depthBufferBits, renderingData.cameraData.pixelWidth, renderingData.cameraData.pixelHeight); TextureHandle depthBuffer = UniversalRenderer.CreateRenderGraphTexture(renderGraph, depthDescriptor, "_OverlayUITexture_Depth", false); builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.cmd = renderingData.commandBuffer; passData.camera = renderingData.cameraData.camera; passData.offscreenTexture = output; builder.SetRenderFunc((PassData data, RenderGraphContext context) => { ExecutePass(context.renderContext, data); data.cmd.SetGlobalTexture(ShaderPropertyId.overlayUITexture, data.offscreenTexture); }); } } internal void RenderOverlay(RenderGraph renderGraph, in TextureHandle colorBuffer, in TextureHandle depthBuffer, ref RenderingData renderingData) { using (var builder = renderGraph.AddRenderPass("Draw Screen Space UI Pass - Overlay", out var passData, base.profilingSampler)) { builder.UseColorBuffer(colorBuffer, 0); builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.cmd = renderingData.commandBuffer; passData.camera = renderingData.cameraData.camera; builder.SetRenderFunc((PassData data, RenderGraphContext context) => { ExecutePass(context.renderContext, data); }); } } } }