using System;
using Unity.Collections;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal
{
///
/// Write stencil bits for stencil-based cross-fade LOD.
///
sealed class StencilCrossFadeRenderPass
{
private Material[] m_StencilDitherMaskSeedMaterials;
private readonly int _StencilDitherPattern = Shader.PropertyToID("_StencilDitherPattern");
private readonly int _StencilRefDitherMask = Shader.PropertyToID("_StencilRefDitherMask");
private readonly int _StencilWriteDitherMask = Shader.PropertyToID("_StencilWriteDitherMask");
private readonly ProfilingSampler m_ProfilingSampler;
internal StencilCrossFadeRenderPass(Shader shader)
{
m_StencilDitherMaskSeedMaterials = new Material[3];
m_ProfilingSampler = new ProfilingSampler("StencilDitherMaskSeed");
int[] stencilRefs = {
(int)UniversalRendererStencilRef.CrossFadeStencilRef_0,
(int)UniversalRendererStencilRef.CrossFadeStencilRef_1,
(int)UniversalRendererStencilRef.CrossFadeStencilRef_All };
int writeMask = (int)UniversalRendererStencilRef.CrossFadeStencilRef_All;
Debug.Assert(writeMask < 0x100); // 8 bits for stencil
for (int i = 0; i < m_StencilDitherMaskSeedMaterials.Length; ++i)
{
m_StencilDitherMaskSeedMaterials[i] = CoreUtils.CreateEngineMaterial(shader);
m_StencilDitherMaskSeedMaterials[i].SetInteger(_StencilDitherPattern, i + 1);
m_StencilDitherMaskSeedMaterials[i].SetFloat(_StencilWriteDitherMask, (float)writeMask);
m_StencilDitherMaskSeedMaterials[i].SetFloat(_StencilRefDitherMask, (float)stencilRefs[i]);
}
}
public void Dispose()
{
foreach (var m in m_StencilDitherMaskSeedMaterials)
CoreUtils.Destroy(m);
m_StencilDitherMaskSeedMaterials = null;
}
///
/// Shared pass data for render graph
///
private class PassData
{
public TextureHandle depthTarget;
public Material[] stencilDitherMaskSeedMaterials;
}
///
/// Set render graph pass
///
public void Render(RenderGraph renderGraph, ScriptableRenderContext context, TextureHandle depthTarget)
{
using (var builder = renderGraph.AddRasterRenderPass("Prepare Cross Fade Stencil", out var passData, m_ProfilingSampler))
{
builder.SetRenderAttachmentDepth(depthTarget, AccessFlags.Write);
passData.stencilDitherMaskSeedMaterials = m_StencilDitherMaskSeedMaterials;
passData.depthTarget = depthTarget;
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
ExecutePass(context.cmd, data.depthTarget, data.stencilDitherMaskSeedMaterials);
});
}
}
private static void ExecutePass(RasterCommandBuffer cmd, RTHandle depthTarget, Material[] stencilDitherMaskSeedMaterials)
{
Vector2Int scaledViewportSize = depthTarget.GetScaledSize(depthTarget.rtHandleProperties.currentViewportSize);
Rect viewport = new Rect(0.0f, 0.0f, scaledViewportSize.x, scaledViewportSize.y);
cmd.SetViewport(viewport);
// render one stencil value in each pass because SV_StencilRef is not fully supported.
for (int i = 0; i < stencilDitherMaskSeedMaterials.Length; ++i)
{
cmd.DrawProcedural(Matrix4x4.identity, stencilDitherMaskSeedMaterials[i], 0, MeshTopology.Triangles, 3, 1);
}
}
}
}