Files
Cielonos/Assets/PotaToon/Runtime/Scripts/TransparentShadowPass.cs
SoulliesOfficial f7af60351b 阶段性完成
2025-12-08 05:27:53 -05:00

208 lines
9.5 KiB
C#

/// NOTE)
/// This feature should be used only for character's cloth.
/// Otherwise, the shadow will cast to far object as well.
/// Limitations: Not will behave natural if more than 2 transparent clothes overlapped.
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering;
#if UNITY_6000_0_OR_NEWER
using UnityEngine.Rendering.RenderGraphModule;
#endif
namespace PotaToon
{
public class TransparentShadowPass : ScriptableRenderPass
{
/* Static Variables */
private static readonly ShaderTagId k_ShaderTagId = new ShaderTagId("TransparentShadow");
private static readonly ShaderTagId k_AlphaSumShaderTagId = new ShaderTagId("TransparentAlphaSum");
internal static int[] s_TextureSize = new int[2] { 1, 1 };
/* Member Variables */
private RTHandle m_TransparentShadowRT;
private RTHandle m_TransparentAlphaSumRT;
private ProfilingSampler m_ProfilingSampler;
public TransparentShadowPass(string featureName)
{
renderPassEvent = RenderPassEvent.BeforeRenderingOpaques;
m_ProfilingSampler = new ProfilingSampler(featureName);
}
public void Dispose()
{
m_TransparentShadowRT?.Release();
m_TransparentAlphaSumRT?.Release();
}
public void Setup(PotaToon volume)
{
var scale = (int)volume.transparentTextureScale.value;
s_TextureSize[0] = volume.transparentShadow.value ? 1024 * scale : 1;
s_TextureSize[1] = volume.transparentShadow.value ? 1024 * scale : 1;
}
private RenderTextureDescriptor GetRenderTextureDescriptor()
{
var descriptor = new RenderTextureDescriptor(s_TextureSize[0], s_TextureSize[1], RenderTextureFormat.R16, 0);
descriptor.dimension = TextureDimension.Tex2D;
descriptor.sRGB = false;
descriptor.depthStencilFormat = GraphicsFormat.None;
return descriptor;
}
private class PassData
{
#if UNITY_6000_0_OR_NEWER
// RenderGraph Path
public RendererListHandle rendererList;
#endif
}
#if UNITY_6000_0_OR_NEWER
[Obsolete]
#endif
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
// Depth
var descriptor = GetRenderTextureDescriptor();
RenderingUtils.ReAllocateIfNeeded(ref m_TransparentShadowRT, descriptor, FilterMode.Bilinear, name:"TransparentShadowMap");
cmd.SetGlobalTexture(ShaderIDs._TransparentShadowMap, m_TransparentShadowRT);
// Alpha Sum
descriptor.graphicsFormat = GraphicsFormat.R16_SFloat;
RenderingUtils.ReAllocateIfNeeded(ref m_TransparentAlphaSumRT, descriptor, FilterMode.Bilinear, name:"TransparentAlphaSum");
cmd.SetGlobalTexture(ShaderIDs._TransparentAlphaSum, m_TransparentAlphaSumRT);
}
#if !UNITY_2021_3
private static void ExecutePass(CommandBuffer cmd, RendererList rendererList)
{
cmd.DrawRendererList(rendererList);
}
#endif
#if UNITY_6000_0_OR_NEWER
[Obsolete]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var cmd = CommandBufferPool.Get();
var filteringSettings = new FilteringSettings(RenderQueueRange.transparent);
using (new ProfilingScope(cmd, m_ProfilingSampler))
{
cmd.SetGlobalFloat(ShaderIDs._CharShadowmapIndex, 0);
CoreUtils.SetRenderTarget(cmd, m_TransparentShadowRT, ClearFlag.Color, 0, CubemapFace.Unknown, 0);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
// Depth & Alpha Sum
var drawSettings = RenderingUtils.CreateDrawingSettings(k_ShaderTagId, ref renderingData, SortingCriteria.CommonTransparent);
#if UNITY_2021_3
var rendererListDesc = new UnityEngine.Rendering.RendererUtils.RendererListDesc(k_ShaderTagId, renderingData.cullResults, renderingData.cameraData.camera);
rendererListDesc.sortingCriteria = SortingCriteria.CommonTransparent;
rendererListDesc.renderQueueRange = RenderQueueRange.transparent;
cmd.DrawRendererList(context.CreateRendererList(rendererListDesc));
#else
var param = new RendererListParams(renderingData.cullResults, drawSettings, filteringSettings);
ExecutePass(cmd, context.CreateRendererList(ref param));
#endif
CoreUtils.SetRenderTarget(cmd, m_TransparentAlphaSumRT, ClearFlag.Color, 0, CubemapFace.Unknown, 0);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
var alphaDrawSettings = RenderingUtils.CreateDrawingSettings(k_AlphaSumShaderTagId, ref renderingData, SortingCriteria.CommonTransparent);
#if UNITY_2021_3
rendererListDesc = new UnityEngine.Rendering.RendererUtils.RendererListDesc(k_AlphaSumShaderTagId, renderingData.cullResults, renderingData.cameraData.camera);
rendererListDesc.sortingCriteria = SortingCriteria.CommonTransparent;
rendererListDesc.renderQueueRange = RenderQueueRange.transparent;
cmd.DrawRendererList(context.CreateRendererList(rendererListDesc));
#else
param = new RendererListParams(renderingData.cullResults, alphaDrawSettings, filteringSettings);
ExecutePass(cmd, context.CreateRendererList(ref param));
#endif
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
var renderer = renderingData.cameraData.renderer;
#if UNITY_2021_3
CoreUtils.SetRenderTarget(cmd, renderer.cameraColorTarget, renderer.cameraDepthTarget);
#else
CoreUtils.SetRenderTarget(cmd, renderer.cameraColorTargetHandle, renderer.cameraDepthTargetHandle);
#endif
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
#if UNITY_6000_0_OR_NEWER
#region RenderGraph
private static void ExecutePass(RasterCommandBuffer cmd, RendererList rendererList)
{
cmd.DrawRendererList(rendererList);
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var renderingData = frameData.Get<UniversalRenderingData>();
var lightData = frameData.Get<UniversalLightData>();
var cameraData = frameData.Get<UniversalCameraData>();
var filteringSettings = new FilteringSettings(RenderQueueRange.transparent);
// Depth
var descriptor = GetRenderTextureDescriptor();
TextureHandle transparentShadowMap = UniversalRenderer.CreateRenderGraphTexture(renderGraph, descriptor, "TransparentShadowMap", true, FilterMode.Bilinear);
// Alpha Sum
descriptor.graphicsFormat = GraphicsFormat.R16_SFloat;
TextureHandle transparentAlphaSum = UniversalRenderer.CreateRenderGraphTexture(renderGraph, descriptor, "TransparentAlphaSum", true, FilterMode.Bilinear);
using (var builder = renderGraph.AddRasterRenderPass<PassData>("[PotaToon] Character Transparent Shadow", out var passData, m_ProfilingSampler))
{
builder.AllowGlobalStateModification(true);
builder.SetRenderAttachment(transparentShadowMap, 0);
var drawSettings = RenderingUtils.CreateDrawingSettings(k_ShaderTagId, renderingData, cameraData, lightData, SortingCriteria.CommonTransparent);
var param = new RendererListParams(renderingData.cullResults, drawSettings, filteringSettings);
passData.rendererList = renderGraph.CreateRendererList(param);
builder.UseRendererList(passData.rendererList);
if (transparentShadowMap.IsValid())
builder.SetGlobalTextureAfterPass(transparentShadowMap, ShaderIDs._TransparentShadowMap);
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
context.cmd.SetGlobalFloat(ShaderIDs._CharShadowmapIndex, 0);
ExecutePass(context.cmd, data.rendererList);
});
}
using (var builder = renderGraph.AddRasterRenderPass<PassData>("[PotaToon] Character Transparent Alpha Sum", out var passData, m_ProfilingSampler))
{
builder.AllowGlobalStateModification(true);
builder.SetRenderAttachment(transparentAlphaSum, 0);
var drawSettings = RenderingUtils.CreateDrawingSettings(k_AlphaSumShaderTagId, renderingData, cameraData, lightData, SortingCriteria.CommonTransparent);
var param = new RendererListParams(renderingData.cullResults, drawSettings, filteringSettings);
passData.rendererList = renderGraph.CreateRendererList(param);
builder.UseRendererList(passData.rendererList);
if (transparentAlphaSum.IsValid())
builder.SetGlobalTextureAfterPass(transparentAlphaSum, ShaderIDs._TransparentAlphaSum);
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
ExecutePass(context.cmd, data.rendererList);
});
}
}
#endregion
#endif
}
}