Streamingle_URP/Assets/External/VolumetricLights/Scripts/VolumetricLightsDepthPrePassFeature.cs

314 lines
16 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
using System;
#if UNITY_2023_3_OR_NEWER
using UnityEngine.Rendering.RenderGraphModule;
#endif
namespace VolumetricLights {
public class VolumetricLightsDepthPrePassFeature : ScriptableRendererFeature {
static class ShaderParams {
public static int MainTex = Shader.PropertyToID("_MainTex");
public static int CustomDepthTexture = Shader.PropertyToID("_CustomDepthTexture");
public static int CustomDepthAlphaCutoff = Shader.PropertyToID("_AlphaCutOff");
public static int CustomDepthBaseMap = Shader.PropertyToID("_BaseMap");
public const string SKW_DEPTH_PREPASS = "VF2_DEPTH_PREPASS";
public const string SKW_CUSTOM_DEPTH_ALPHA_TEST = "DEPTH_PREPASS_ALPHA_TEST";
}
public class DepthRenderPass : ScriptableRenderPass {
public VolumetricLightsDepthPrePassFeature settings;
const string m_ProfilerTag = "CustomDepthPrePass";
const string m_DepthOnlyShader = "Hidden/VolumetricLights/DepthOnly";
const string m_CustomDepthTextureName = "_CustomDepthTexture";
static FilteringSettings filterSettings;
int currentCutoutLayerMask;
static readonly List<ShaderTagId> shaderTagIdList = new List<ShaderTagId>();
readonly List<Renderer> cutOutRenderers = new List<Renderer>();
RTHandle m_Depth;
Material depthOnlyMaterial, depthOnlyMaterialCutOff;
Material[] depthOverrideMaterials;
public DepthRenderPass(VolumetricLightsDepthPrePassFeature settings) {
this.settings = settings;
renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
//m_Depth.Init("_CustomDepthTexture");
m_Depth = RTHandles.Alloc(ShaderParams.CustomDepthTexture, name: m_CustomDepthTextureName);
shaderTagIdList.Clear();
shaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit"));
shaderTagIdList.Add(new ShaderTagId("UniversalForward"));
shaderTagIdList.Add(new ShaderTagId("LightweightForward"));
filterSettings = new FilteringSettings(RenderQueueRange.transparent, 0);
SetupKeywords();
FindAlphaClippingRenderers();
}
void SetupKeywords() {
if (settings.transparentLayerMask != 0 || settings.alphaCutoutLayerMask != 0) {
Shader.EnableKeyword(ShaderParams.SKW_DEPTH_PREPASS);
} else {
Shader.DisableKeyword(ShaderParams.SKW_DEPTH_PREPASS);
}
}
void FindAlphaClippingRenderers() {
cutOutRenderers.Clear();
if (settings.alphaCutoutLayerMask == 0) return;
Renderer[] rr = Misc.FindObjectsOfType<Renderer>();
for (int r = 0; r < rr.Length; r++) {
if (((1 << rr[r].gameObject.layer) & settings.alphaCutoutLayerMask) != 0) {
cutOutRenderers.Add(rr[r]);
}
}
}
#if UNITY_2023_3_OR_NEWER
[Obsolete]
#endif
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
if (settings.transparentLayerMask != filterSettings.layerMask || settings.alphaCutoutLayerMask != currentCutoutLayerMask) {
filterSettings = new FilteringSettings(RenderQueueRange.transparent, settings.transparentLayerMask);
if (settings.alphaCutoutLayerMask != currentCutoutLayerMask) {
FindAlphaClippingRenderers();
}
currentCutoutLayerMask = settings.alphaCutoutLayerMask;
SetupKeywords();
}
RenderTextureDescriptor depthDesc = cameraTextureDescriptor;
depthDesc.colorFormat = RenderTextureFormat.Depth;
depthDesc.depthBufferBits = 24;
depthDesc.msaaSamples = 1;
cmd.GetTemporaryRT(ShaderParams.CustomDepthTexture, depthDesc, FilterMode.Point);
cmd.SetGlobalTexture(ShaderParams.CustomDepthTexture, m_Depth);
ConfigureTarget(m_Depth);
ConfigureClear(ClearFlag.All, Color.black);
}
#if UNITY_2023_3_OR_NEWER
[Obsolete]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
if (settings.transparentLayerMask == 0 && settings.alphaCutoutLayerMask == 0) return;
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
if (settings.alphaCutoutLayerMask != 0) {
if (depthOnlyMaterialCutOff == null) {
Shader depthOnlyCutOff = Shader.Find(m_DepthOnlyShader);
depthOnlyMaterialCutOff = new Material(depthOnlyCutOff);
}
int renderersCount = cutOutRenderers.Count;
if (depthOverrideMaterials == null || depthOverrideMaterials.Length < renderersCount) {
depthOverrideMaterials = new Material[renderersCount];
}
for (int k = 0; k < renderersCount; k++) {
Renderer renderer = cutOutRenderers[k];
if (renderer != null && renderer.isVisible) {
Material mat = renderer.sharedMaterial;
if (mat != null) {
if (depthOverrideMaterials[k] == null) {
depthOverrideMaterials[k] = Instantiate(depthOnlyMaterialCutOff);
depthOverrideMaterials[k].EnableKeyword(ShaderParams.SKW_CUSTOM_DEPTH_ALPHA_TEST);
}
Material overrideMaterial = depthOverrideMaterials[k];
overrideMaterial.SetFloat(ShaderParams.CustomDepthAlphaCutoff, settings.alphaCutOff);
if (mat.HasProperty(ShaderParams.CustomDepthBaseMap)) {
overrideMaterial.SetTexture(ShaderParams.MainTex, mat.GetTexture(ShaderParams.CustomDepthBaseMap));
} else if (mat.HasProperty(ShaderParams.MainTex)) {
overrideMaterial.SetTexture(ShaderParams.MainTex, mat.GetTexture(ShaderParams.MainTex));
}
cmd.DrawRenderer(renderer, overrideMaterial);
}
}
}
}
if (settings.transparentLayerMask != 0) {
SortingCriteria sortingCriteria = SortingCriteria.CommonTransparent;
var drawSettings = CreateDrawingSettings(shaderTagIdList, ref renderingData, sortingCriteria);
drawSettings.perObjectData = PerObjectData.None;
if (depthOnlyMaterial == null) {
Shader depthOnly = Shader.Find(m_DepthOnlyShader);
depthOnlyMaterial = new Material(depthOnly);
}
drawSettings.overrideMaterial = depthOnlyMaterial;
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filterSettings);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
#if UNITY_2023_3_OR_NEWER
class PassData {
public RendererListHandle rendererListHandle;
public UniversalCameraData cameraData;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
if (settings.transparentLayerMask == 0 && settings.alphaCutoutLayerMask == 0) {
SetupKeywords();
return;
}
using (var builder = renderGraph.AddUnsafePass<PassData>(m_ProfilerTag, out var passData)) {
builder.AllowPassCulling(false);
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
UniversalRenderingData renderingData = frameData.Get<UniversalRenderingData>();
UniversalLightData lightData = frameData.Get<UniversalLightData>();
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
passData.cameraData = cameraData;
SortingCriteria sortingCriteria = SortingCriteria.CommonTransparent;
var drawingSettings = CreateDrawingSettings(shaderTagIdList, renderingData, cameraData, lightData, sortingCriteria);
drawingSettings.perObjectData = PerObjectData.None;
if (depthOnlyMaterial == null) {
Shader depthOnly = Shader.Find(m_DepthOnlyShader);
depthOnlyMaterial = new Material(depthOnly);
}
drawingSettings.overrideMaterial = depthOnlyMaterial;
RendererListParams listParams = new RendererListParams(renderingData.cullResults, drawingSettings, filterSettings);
passData.rendererListHandle = renderGraph.CreateRendererList(listParams);
builder.UseRendererList(passData.rendererListHandle);
builder.SetRenderFunc((PassData passData, UnsafeGraphContext context) => {
CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);
if (settings.transparentLayerMask != filterSettings.layerMask || settings.alphaCutoutLayerMask != currentCutoutLayerMask) {
filterSettings = new FilteringSettings(RenderQueueRange.transparent, settings.transparentLayerMask);
if (settings.alphaCutoutLayerMask != currentCutoutLayerMask) {
FindAlphaClippingRenderers();
}
currentCutoutLayerMask = settings.alphaCutoutLayerMask;
SetupKeywords();
}
RenderTextureDescriptor depthDesc = passData.cameraData.cameraTargetDescriptor;
depthDesc.colorFormat = RenderTextureFormat.Depth;
depthDesc.depthBufferBits = 24;
depthDesc.msaaSamples = 1;
cmd.GetTemporaryRT(ShaderParams.CustomDepthTexture, depthDesc, FilterMode.Point);
cmd.SetGlobalTexture(ShaderParams.CustomDepthTexture, m_Depth);
RenderTargetIdentifier rti = new RenderTargetIdentifier(ShaderParams.CustomDepthTexture, 0, CubemapFace.Unknown, -1);
cmd.SetRenderTarget(rti);
cmd.ClearRenderTarget(true, true, Color.black);
if (settings.alphaCutoutLayerMask != 0) {
if (depthOnlyMaterialCutOff == null) {
Shader depthOnlyCutOff = Shader.Find(m_DepthOnlyShader);
depthOnlyMaterialCutOff = new Material(depthOnlyCutOff);
}
int renderersCount = cutOutRenderers.Count;
if (depthOverrideMaterials == null || depthOverrideMaterials.Length < renderersCount) {
depthOverrideMaterials = new Material[renderersCount];
}
for (int k = 0; k < renderersCount; k++) {
Renderer renderer = cutOutRenderers[k];
if (renderer != null && renderer.isVisible) {
Material mat = renderer.sharedMaterial;
if (mat != null) {
if (depthOverrideMaterials[k] == null) {
depthOverrideMaterials[k] = Instantiate(depthOnlyMaterialCutOff);
depthOverrideMaterials[k].EnableKeyword(ShaderParams.SKW_CUSTOM_DEPTH_ALPHA_TEST);
}
Material overrideMaterial = depthOverrideMaterials[k];
overrideMaterial.SetFloat(ShaderParams.CustomDepthAlphaCutoff, settings.alphaCutOff);
if (mat.HasProperty(ShaderParams.CustomDepthBaseMap)) {
overrideMaterial.SetTexture(ShaderParams.MainTex, mat.GetTexture(ShaderParams.CustomDepthBaseMap));
} else if (mat.HasProperty(ShaderParams.MainTex)) {
overrideMaterial.SetTexture(ShaderParams.MainTex, mat.GetTexture(ShaderParams.MainTex));
}
cmd.DrawRenderer(renderer, overrideMaterial);
}
}
}
}
if (settings.transparentLayerMask != 0) {
cmd.DrawRendererList(passData.rendererListHandle);
}
});
}
}
#endif
/// Cleanup any allocated resources that were created during the execution of this render pass.
public override void FrameCleanup(CommandBuffer cmd) {
if (cmd == null) return;
cmd.ReleaseTemporaryRT(ShaderParams.CustomDepthTexture);
}
public void CleanUp() {
RTHandles.Release(m_Depth);
}
}
[Tooltip("Optionally specify which transparent layers must be included in the depth prepass. Use only to avoid fog clipping with certain transparent objects.")]
public LayerMask transparentLayerMask;
[Tooltip("Optionally specify which semi-transparent (materials using alpha clipping or cut-off) must be included in the depth prepass. Use only to avoid fog clipping with certain transparent objects.")]
public LayerMask alphaCutoutLayerMask;
[Tooltip("Optionally determines the alpha cut off for semitransparent objects.")]
[Range(0, 1)]
public float alphaCutOff;
[Tooltip("If this depth pre-pass render feature can execute on reflection probes.")]
public bool ignoreReflectionProbes = true;
[Tooltip("If this depth pre-pass render feature can execute on overlay cameras.")]
public bool ignoreOverlayCamera = true;
DepthRenderPass m_ScriptablePass;
public static bool installed;
public override void Create() {
m_ScriptablePass = new DepthRenderPass(this);
}
void OnDestroy() {
installed = false;
if (m_ScriptablePass != null) {
m_ScriptablePass.CleanUp();
}
Shader.DisableKeyword(ShaderParams.SKW_DEPTH_PREPASS);
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
if (ignoreOverlayCamera && renderingData.cameraData.renderType == CameraRenderType.Overlay) return;
Camera cam = renderingData.cameraData.camera;
if (cam.targetTexture != null && cam.targetTexture.format == RenderTextureFormat.Depth) return; // ignore occlusion cams!
if (ignoreReflectionProbes && cam.cameraType == CameraType.Reflection) return;
installed = true;
renderer.EnqueuePass(m_ScriptablePass);
}
}
}