171 lines
8.3 KiB
C#
171 lines
8.3 KiB
C#
using System;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.Universal
|
|
{
|
|
/// <summary>
|
|
/// Draw screen space overlay UI into the given color and depth target
|
|
/// </summary>
|
|
internal class DrawScreenSpaceUIPass : ScriptableRenderPass
|
|
{
|
|
/// <summary>
|
|
/// Creates a new <c>DrawScreenSpaceUIPass</c> instance.
|
|
/// </summary>
|
|
/// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
|
|
/// <seealso cref="RenderPassEvent"/>
|
|
public DrawScreenSpaceUIPass(RenderPassEvent evt)
|
|
{
|
|
profilingSampler = ProfilingSampler.Get(URPProfileId.DrawScreenSpaceUI);
|
|
renderPassEvent = evt;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a descriptor for the required color texture for offscreen UI pass.
|
|
/// </summary>
|
|
internal static void ConfigureOffscreenUITextureDesc(ref TextureDesc textureDesc)
|
|
{
|
|
textureDesc.format = GraphicsFormat.R8G8B8A8_SRGB;
|
|
textureDesc.depthBufferBits = 0;
|
|
textureDesc.width = Screen.width;
|
|
textureDesc.height = Screen.height;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a descriptor for the required depth texture for this pass.
|
|
/// </summary>
|
|
/// <param name="descriptor">Camera target descriptor.</param>
|
|
/// <param name="depthStencilFormat">Depth stencil format required.</param>
|
|
/// <param name="screenWidth">The full screen width.</param>
|
|
/// <param name="screenHeight">The full screen height.</param>
|
|
/// <seealso cref="RenderTextureDescriptor"/>
|
|
private static void ConfigureDepthDescriptor(ref RenderTextureDescriptor descriptor, GraphicsFormat depthStencilFormat, int screenWidth, int screenHeight)
|
|
{
|
|
descriptor.graphicsFormat = GraphicsFormat.None;
|
|
descriptor.depthStencilFormat = depthStencilFormat;
|
|
descriptor.width = screenWidth;
|
|
descriptor.height = screenHeight;
|
|
}
|
|
|
|
private static void ExecutePass(RasterCommandBuffer commandBuffer, PassData passData, RendererList rendererList)
|
|
{
|
|
commandBuffer.DrawRendererList(rendererList);
|
|
}
|
|
|
|
// Specific to RG cases which have to go through Unsafe commands
|
|
private static void ExecutePass(UnsafeCommandBuffer commandBuffer, UnsafePassData passData, RendererList rendererList)
|
|
{
|
|
commandBuffer.DrawRendererList(rendererList);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
//RenderGraph path
|
|
private class PassData
|
|
{
|
|
internal RendererListHandle rendererList;
|
|
}
|
|
|
|
// Specific to RG cases which have to go through Unsafe commands
|
|
private class UnsafePassData
|
|
{
|
|
internal RendererListHandle rendererList;
|
|
internal TextureHandle colorTarget;
|
|
}
|
|
|
|
internal void RenderOffscreen(RenderGraph renderGraph, ContextContainer frameData, GraphicsFormat depthStencilFormat, TextureHandle overlayUITexture)
|
|
{
|
|
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
|
|
RenderTextureDescriptor depthDescriptor = cameraData.cameraTargetDescriptor;
|
|
ConfigureDepthDescriptor(ref depthDescriptor, depthStencilFormat, Screen.width, Screen.height);
|
|
TextureHandle depthBuffer = UniversalRenderer.CreateRenderGraphTexture(renderGraph, depthDescriptor, "_OverlayUITexture_Depth", false);
|
|
|
|
// Render uGUI and UIToolkit overlays
|
|
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Draw Screen Space UIToolkit/uGUI - Offscreen", out var passData, profilingSampler))
|
|
{
|
|
// UIToolkit/uGUI pass accept custom shaders, we need to make sure we use all global textures
|
|
builder.UseAllGlobalTextures(true);
|
|
|
|
builder.SetRenderAttachment(overlayUITexture, 0);
|
|
|
|
passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.UIToolkit_UGUI);
|
|
builder.UseRendererList(passData.rendererList);
|
|
|
|
builder.SetRenderAttachmentDepth(depthBuffer, AccessFlags.ReadWrite);
|
|
|
|
if (overlayUITexture.IsValid())
|
|
builder.SetGlobalTextureAfterPass(overlayUITexture, ShaderPropertyId.overlayUITexture);
|
|
|
|
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
|
|
{
|
|
context.cmd.ClearRenderTarget(true, true, Color.clear);
|
|
ExecutePass(context.cmd, data, data.rendererList);
|
|
});
|
|
}
|
|
// Render IMGUI overlay and software cursor in a UnsafePass
|
|
// Doing so allow us to safely cover cases when graphics commands called through onGUI() in user scripts are not supported by RenderPass API
|
|
// Besides, Vulkan backend doesn't support SetSRGWrite() in RenderPass API and we have some of them at IMGUI levels
|
|
// Note, these specific UI calls doesn't need depth buffer unlike UIToolkit/uGUI
|
|
using (var builder = renderGraph.AddUnsafePass<UnsafePassData>("Draw Screen Space IMGUI/SoftwareCursor - Offscreen", out var passData, profilingSampler))
|
|
{
|
|
passData.colorTarget = overlayUITexture;
|
|
builder.UseTexture(overlayUITexture, AccessFlags.Write);
|
|
|
|
passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.LowLevel);
|
|
builder.UseRendererList(passData.rendererList);
|
|
|
|
builder.SetRenderFunc(static (UnsafePassData data, UnsafeGraphContext context) =>
|
|
{
|
|
context.cmd.SetRenderTarget(data.colorTarget);
|
|
ExecutePass(context.cmd, data, data.rendererList);
|
|
});
|
|
}
|
|
}
|
|
|
|
internal void RenderOverlay(RenderGraph renderGraph, ContextContainer frameData, in TextureHandle colorBuffer, in TextureHandle depthBuffer)
|
|
{
|
|
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
|
|
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
|
|
UniversalRenderer renderer = cameraData.renderer as UniversalRenderer;
|
|
|
|
// Render uGUI and UIToolkit overlays
|
|
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Draw UIToolkit/uGUI Overlay", out var passData, profilingSampler))
|
|
{
|
|
// UIToolkit/uGUI pass accept custom shaders, we need to make sure we use all global textures
|
|
builder.UseAllGlobalTextures(true);
|
|
|
|
builder.SetRenderAttachment(colorBuffer, 0);
|
|
builder.SetRenderAttachmentDepth(depthBuffer, AccessFlags.ReadWrite);
|
|
|
|
passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.UIToolkit_UGUI);
|
|
builder.UseRendererList(passData.rendererList);
|
|
|
|
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
|
|
{
|
|
ExecutePass(context.cmd, data, data.rendererList);
|
|
});
|
|
}
|
|
// Render IMGUI overlay and software cursor in a UnsafePass
|
|
// Doing so allow us to safely cover cases when graphics commands called through onGUI() in user scripts are not supported by RenderPass API
|
|
// Besides, Vulkan backend doesn't support SetSRGWrite() in RenderPass API and we have some of them at IMGUI levels
|
|
// Note, these specific UI calls doesn't need depth buffer unlike UIToolkit/uGUI
|
|
using (var builder = renderGraph.AddUnsafePass<UnsafePassData>("Draw IMGUI/SoftwareCursor Overlay", out var passData, profilingSampler))
|
|
{
|
|
passData.colorTarget = colorBuffer;
|
|
builder.UseTexture(colorBuffer, AccessFlags.Write);
|
|
|
|
passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.LowLevel);
|
|
builder.UseRendererList(passData.rendererList);
|
|
|
|
builder.SetRenderFunc(static (UnsafePassData data, UnsafeGraphContext context) =>
|
|
{
|
|
context.cmd.SetRenderTarget(data.colorTarget);
|
|
ExecutePass(context.cmd, data, data.rendererList);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|