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;
public RTHandle colorTarget { get => m_ColorTarget; }
///
/// Creates a new DrawScreenSpaceUIPass instance.
///
/// The RenderPassEvent to use.
///
public DrawScreenSpaceUIPass(RenderPassEvent evt, bool renderOffscreen)
{
base.profilingSampler = new ProfilingSampler(nameof(DrawScreenSpaceUIPass));
renderPassEvent = evt;
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
///
///
///
public static void ConfigureDescriptor(ref RenderTextureDescriptor descriptor)
{
descriptor.graphicsFormat = GraphicsFormat.R8G8B8A8_SRGB;
descriptor.depthBufferBits = 0;
}
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();
}
///
/// Configure the pass with the off-screen destination color texture and the depth texture to execute the pass on.
///
/// Descriptor for the color buffer.
/// Depth texture to render to.
public void Setup(RenderTextureDescriptor descriptor, in RTHandle depthTexture)
{
if (m_RenderOffscreen)
{
DrawScreenSpaceUIPass.ConfigureDescriptor(ref descriptor);
RenderingUtils.ReAllocateIfNeeded(ref m_ColorTarget, descriptor, name: "_OverlayUITexture");
m_DepthTarget = depthTexture;
}
}
///
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.DebugScreenTextureHandle);
}
else
{
// Create RTHandle alias to use RTHandle apis
if (m_ColorTarget != cameraTarget)
{
m_ColorTarget?.Release();
m_ColorTarget = RTHandles.Alloc(cameraTarget);
}
CoreUtils.SetRenderTarget(renderingData.commandBuffer, m_ColorTarget);
}
}
using (new ProfilingScope(renderingData.commandBuffer, ProfilingSampler.Get(URPProfileId.DrawScreenSpaceUI)))
{
ExecutePass(context, m_PassData);
}
}
//RenderGraph path
internal void RenderOffscreen(RenderGraph renderGraph, out TextureHandle output, ref RenderingData renderingData)
{
using (var builder = renderGraph.AddRenderPass("Draw Screen Space UI Pass - Offscreen", out var passData, base.profilingSampler))
{
RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
ConfigureDescriptor(ref descriptor);
output = UniversalRenderer.CreateRenderGraphTexture(renderGraph, descriptor, "_OverlayUITexture", true);
builder.UseColorBuffer(output, 0);
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, ref RenderingData renderingData)
{
using (var builder = renderGraph.AddRenderPass("Draw Screen Space UI Pass - Overlay", out var passData, base.profilingSampler))
{
builder.WriteTexture(colorBuffer);
passData.cmd = renderingData.commandBuffer;
passData.camera = renderingData.cameraData.camera;
builder.SetRenderFunc((PassData data, RenderGraphContext context) =>
{
ExecutePass(context.renderContext, data);
});
}
}
}
}