UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Samples~/URPPackageSamples/RendererFeatures/DepthBlit/DepthBlitFeature.cs

118 lines
4.6 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
// This Renderer Feature enqueues either the DepthBlitCopyDepthPass or the DepthBlitDepthOnlyPass depending on the current platform support.
// DepthBlitCopyPass is a simplified version of URP CopyDepthPass. The pass copies the depth texture to an RTHandle.
// DepthBlitDepthOnlyPass is a simplified version of the URP DepthOnlyPass. The pass renders depth values to an RTHandle.
// The Renderer Feature also enqueues the DepthBlitEdgePass which takes the RTHandle as input to create an effect to visualize depth, and output it to the screen.
public class DepthBlitFeature : ScriptableRendererFeature
{
public RenderPassEvent evt_Depth = RenderPassEvent.AfterRenderingOpaques;
public RenderPassEvent evt_Edge = RenderPassEvent.AfterRenderingOpaques;
public UniversalRendererData rendererDataAsset; // The field for accessing opaqueLayerMask on the renderer asset
public Shader copyDepthShader;
public Material m_DepthEdgeMaterial;
// The RTHandle for storing the depth texture
private RTHandle m_DepthRTHandle;
private const string k_DepthRTName = "_MyDepthTexture";
// This class is for keeping the TextureHandle reference in the frame data so that it can be shared with multiple passes in the render graph system.
public class TexRefData : ContextItem
{
public TextureHandle depthTextureHandle = TextureHandle.nullHandle;
public override void Reset()
{
depthTextureHandle = TextureHandle.nullHandle;
}
}
// The passes for the effect
private DepthBlitCopyDepthPass m_CopyDepthPass;
private DepthBlitDepthOnlyPass m_DepthOnlyPass; // DepthOnlyPass is for platforms that run OpenGL ES, which does not support CopyDepth.
private DepthBlitEdgePass m_DepthEdgePass;
// Check if the platform supports CopyDepthPass
private bool CanCopyDepth(ref CameraData cameraData)
{
bool msaaEnabledForCamera = cameraData.cameraTargetDescriptor.msaaSamples > 1;
bool supportsTextureCopy = SystemInfo.copyTextureSupport != CopyTextureSupport.None;
bool supportsDepthTarget = RenderingUtils.SupportsRenderTextureFormat(RenderTextureFormat.Depth);
bool supportsDepthCopy = !msaaEnabledForCamera && (supportsDepthTarget || supportsTextureCopy);
bool msaaDepthResolve = msaaEnabledForCamera && SystemInfo.supportsMultisampledTextures != 0;
// Avoid copying MSAA depth on GLES3 platform to avoid invalid results
if (IsGLESDevice() && msaaDepthResolve)
return false;
return supportsDepthCopy || msaaDepthResolve;
}
private bool IsGLESDevice()
{
return SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var cameraData = renderingData.cameraData;
if (renderingData.cameraData.cameraType != CameraType.Game)
return;
// Create an RTHandle for storing the depth
var desc = renderingData.cameraData.cameraTargetDescriptor;
if (CanCopyDepth(ref cameraData))
{
desc.depthBufferBits = 0;
desc.msaaSamples = 1;
}
else
{
desc.graphicsFormat = GraphicsFormat.None;
desc.msaaSamples = 1;
}
RenderingUtils.ReAllocateHandleIfNeeded(ref m_DepthRTHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: k_DepthRTName );
// Setup passes
if (CanCopyDepth(ref cameraData))
{
if (m_CopyDepthPass == null)
m_CopyDepthPass = new DepthBlitCopyDepthPass(evt_Depth, copyDepthShader, m_DepthRTHandle);
renderer.EnqueuePass(m_CopyDepthPass);
}
else
{
if (m_DepthOnlyPass == null)
m_DepthOnlyPass = new DepthBlitDepthOnlyPass(evt_Depth, RenderQueueRange.opaque, rendererDataAsset.opaqueLayerMask, m_DepthRTHandle);
renderer.EnqueuePass(m_DepthOnlyPass);
}
// Pass the RTHandle for the DepthEdge effect
m_DepthEdgePass.SetRTHandle(ref m_DepthRTHandle);
renderer.EnqueuePass(m_DepthEdgePass);
}
public override void Create()
{
m_DepthEdgePass = new DepthBlitEdgePass(m_DepthEdgeMaterial, evt_Edge);
}
protected override void Dispose(bool disposing)
{
m_CopyDepthPass?.Dispose();
m_DepthRTHandle?.Release();
m_DepthEdgePass = null;
m_CopyDepthPass = null;
m_DepthOnlyPass = null;
}
}