using System;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal.Internal
{
/// <summary>
/// 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.
/// </summary>
public partial class DepthOnlyPass : ScriptableRenderPass
{
internal ShaderTagId shaderTagId { get; set; } = k_ShaderTagId;
FilteringSettings m_FilteringSettings;
// Statics
private static readonly ShaderTagId k_ShaderTagId = new ShaderTagId("DepthOnly");
private static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture");
/// <summary>
/// Creates a new <c>DepthOnlyPass</c> instance.
/// </summary>
/// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
/// <param name="renderQueueRange">The <c>RenderQueueRange</c> to use for creating filtering settings that control what objects get rendered.</param>
/// <param name="layerMask">The layer mask to use for creating filtering settings that control what objects get rendered.</param>
/// <seealso cref="RenderPassEvent"/>
/// <seealso cref="RenderQueueRange"/>
/// <seealso cref="LayerMask"/>
public DepthOnlyPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask)
{
profilingSampler = new ProfilingSampler("Draw Depth Only");
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
renderPassEvent = evt;
shaderTagId = k_ShaderTagId;
}
/// <summary>
/// Configures the pass.
/// </summary>
/// <param name="baseDescriptor">The <c>RenderTextureDescriptor</c> used for the depthStencilFormat.</param>
/// <param name="depthAttachmentHandle">The <c>RTHandle</c> used to render to.</param>
/// <seealso cref="RenderTextureDescriptor"/>
/// <seealso cref="RTHandle"/>
/// <seealso cref="GraphicsFormat"/>
public void Setup(
RenderTextureDescriptor baseDescriptor,
RTHandle depthAttachmentHandle)
{
}
private static void ExecutePass(RasterCommandBuffer cmd, RendererList rendererList)
{
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.DepthPrepass)))
{
cmd.DrawRendererList(rendererList);
}
}
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<UniversalRenderingData>();
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
UniversalLightData lightData = frameData.Get<UniversalLightData>();
using (var builder = renderGraph.AddRasterRenderPass<PassData>(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);
// Apply MultiviewRenderRegionsCompatible flag only to the peripheral view in Quad Views
if (cameraData.xr.multipassId == 0)
{
builder.SetExtendedFeatureFlags(ExtendedFeatureFlags.MultiviewRenderRegionsCompatible);
}
}
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
{
ExecutePass(context.cmd, data.rendererList);
});
}
}
}
}