using System;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal.Internal
{
///
/// Render all objects that have a 'DepthOnly' pass into the given depth buffer.
///
/// You can use this pass to prime a depth buffer for subsequent rendering.
/// Use it as a z-prepass, or use it to generate a depth buffer.
///
public partial class DepthOnlyPass : ScriptableRenderPass
{
internal ShaderTagId shaderTagId { get; set; } = k_ShaderTagId;
FilteringSettings m_FilteringSettings;
#if URP_COMPATIBILITY_MODE
private RTHandle destination { get; set; }
private GraphicsFormat depthStencilFormat;
private PassData m_PassData;
#endif
// Statics
private static readonly ShaderTagId k_ShaderTagId = new ShaderTagId("DepthOnly");
private static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture");
///
/// Creates a new DepthOnlyPass 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 DepthOnlyPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask)
{
profilingSampler = new ProfilingSampler("Draw Depth Only");
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
renderPassEvent = evt;
this.shaderTagId = k_ShaderTagId;
#if URP_COMPATIBILITY_MODE
useNativeRenderPass = false;
m_PassData = new PassData();
#endif
}
///
/// Configures the pass.
///
/// The RenderTextureDescriptor used for the depthStencilFormat.
/// The RTHandle used to render to.
///
///
///
public void Setup(
RenderTextureDescriptor baseDescriptor,
RTHandle depthAttachmentHandle)
{
#if URP_COMPATIBILITY_MODE
this.destination = depthAttachmentHandle;
this.depthStencilFormat = baseDescriptor.depthStencilFormat;
#endif
}
#if URP_COMPATIBILITY_MODE
///
[Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsoleteFrom2023_3)]
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
var desc = renderingData.cameraData.cameraTargetDescriptor;
// Disable obsolete warning for internal usage
#pragma warning disable CS0618
// When depth priming is in use the camera target should not be overridden so the Camera's MSAA depth attachment is used.
if (renderingData.cameraData.renderer.useDepthPriming && (renderingData.cameraData.renderType == CameraRenderType.Base || renderingData.cameraData.clearDepth))
{
ConfigureTarget(renderingData.cameraData.renderer.cameraDepthTargetHandle);
// Only clear depth here so we don't clear any bound color target. It might be unused by this pass but that doesn't mean we can just clear it. (e.g. in case of overlay cameras + depth priming)
ConfigureClear(ClearFlag.Depth, Color.black);
}
// When not using depth priming the camera target should be set to our non MSAA depth target.
else
{
useNativeRenderPass = true;
ConfigureTarget(destination);
ConfigureClear(ClearFlag.All, Color.black);
}
#pragma warning restore CS0618
}
#endif
private static void ExecutePass(RasterCommandBuffer cmd, RendererList rendererList)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.DepthPrepass)))
{
cmd.DrawRendererList(rendererList);
}
}
#if URP_COMPATIBILITY_MODE
///
[Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsoleteFrom2023_3)]
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
ContextContainer frameData = renderingData.frameData;
UniversalRenderingData universalRenderingData = frameData.Get();
UniversalCameraData cameraData = frameData.Get();
UniversalLightData lightData = frameData.Get();
var param = InitRendererListParams(universalRenderingData, cameraData, lightData);
RendererList rendererList = context.CreateRendererList(ref param);
ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), rendererList);
}
#endif
private class PassData
{
internal RendererListHandle rendererList;
}
private RendererListParams InitRendererListParams(UniversalRenderingData renderingData, UniversalCameraData cameraData, UniversalLightData lightData)
{
var sortFlags = cameraData.defaultOpaqueSortFlags;
var drawSettings = RenderingUtils.CreateDrawingSettings(this.shaderTagId, renderingData, cameraData, lightData, sortFlags);
drawSettings.perObjectData = PerObjectData.None;
drawSettings.lodCrossFadeStencilMask = 0; // For stencil-based Lod, we use texture dither instead of stencil testing because we have the same shader variants for cross-fade shadow.
return new RendererListParams(renderingData.cullResults, drawSettings, m_FilteringSettings);
}
internal void Render(RenderGraph renderGraph, ContextContainer frameData, in TextureHandle depthTexture, uint batchLayerMask, bool setGlobalDepth)
{
UniversalRenderingData renderingData = frameData.Get();
UniversalCameraData cameraData = frameData.Get();
UniversalLightData lightData = frameData.Get();
using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData, profilingSampler))
{
var param = InitRendererListParams(renderingData, cameraData, lightData);
param.filteringSettings.batchLayerMask = batchLayerMask;
passData.rendererList = renderGraph.CreateRendererList(param);
builder.UseRendererList(passData.rendererList);
builder.SetRenderAttachmentDepth(depthTexture, AccessFlags.ReadWrite);
if (setGlobalDepth)
builder.SetGlobalTextureAfterPass(depthTexture, s_CameraDepthTextureID);
builder.AllowGlobalStateModification(true);
if (cameraData.xr.enabled)
{
builder.EnableFoveatedRasterization(cameraData.xr.supportsFoveatedRendering && cameraData.xrUniversal.canFoveateIntermediatePasses);
builder.SetExtendedFeatureFlags(ExtendedFeatureFlags.MultiviewRenderRegionsCompatible);
}
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
ExecutePass(context.cmd, data.rendererList);
});
}
}
}
}