Files
com.misaki.hdrp-toon/Runtime/HDRP/UTS Renderer/UTSHairShadowPass.cs
2025-01-08 23:09:55 +09:00

145 lines
5.1 KiB
C#

using UnityEditor;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.RendererUtils;
namespace Misaki.HdrpToon
{
[HideInInspector]
internal class UTSHairShadowPass : DrawRenderersCustomPass
{
public enum ShadowQuality
{
Low,
High
}
private const string Hair_Shadow_RTHandle_Scale_Prop_Name = "_HairShadowRTHandleScale";
private const string Hair_Shadow_Distance_Prop_Name = "_HairShadowDistance";
private const string Hair_Shadow_Distance_Scale_Prop_Name = "_HairShadowDistanceScaleFactor";
private const string Hair_Shadow_Depth_Bias_Prop_Name = "_HairShadowDepthBias";
private const string Hair_Shadow_FadeIn_Prop_Name = "_HairShadowFadeInDistance";
private const string Hair_Shadow_Fade_Out_Prop_Name = "_HairShadowFadeOutDistance";
private const string Output_RT_Name = "_HairShadowTex";
private RTHandle _outputRTHandle;
private bool _needReallocate;
private ShadowQuality _shadowQuality = ShadowQuality.High;
internal ShadowQuality CurrentShadowQuality
{
get => _shadowQuality;
set
{
if (_shadowQuality == value)
{
return;
}
_shadowQuality = value;
_needReallocate = true;
}
}
private bool ShouldReallocateBuffer()
{
return _outputRTHandle == null || _outputRTHandle.rt == null || !_outputRTHandle.rt.IsCreated() || _needReallocate;
}
private void ReallocateBuffer()
{
#if UNITY_EDITOR
if (EditorApplication.isCompiling)
{
return;
}
#endif
var scale = _shadowQuality switch
{
ShadowQuality.Low => new Vector2(0.5f, 0.5f),
ShadowQuality.High => Vector2.one,
_ => Vector2.zero
};
var format = _shadowQuality switch
{
ShadowQuality.Low => GraphicsFormat.D16_UNorm,
ShadowQuality.High => GraphicsFormat.D32_SFloat,
_ => GraphicsFormat.D16_UNorm
};
_outputRTHandle?.Release();
_outputRTHandle = RTHandles.Alloc(scale, colorFormat: format, filterMode: FilterMode.Bilinear, wrapMode: TextureWrapMode.Clamp, isShadowMap: true, name: Output_RT_Name);
Shader.SetGlobalTexture(Output_RT_Name, _outputRTHandle);
_needReallocate = false;
}
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
ReallocateBuffer();
}
protected override void Execute(CustomPassContext ctx)
{
if (ShouldReallocateBuffer())
{
ReallocateBuffer();
return;
}
CoreUtils.SetRenderTarget(ctx.cmd, _outputRTHandle, ClearFlag.DepthStencil);
var utsRenderer = ctx.hdCamera.volumeStack.GetComponent<UTSRenderer>();
var shouldRender = utsRenderer != null && utsRenderer.enableHairShadow.value && utsRenderer.state.value;
if (!shouldRender)
{
CoreUtils.ClearRenderTarget(ctx.cmd, ClearFlag.DepthStencil, Color.black);
return;
}
var mask = RenderStateMask.Nothing;
var stateBlock = new RenderStateBlock(mask)
{
depthState = new DepthState(true, CompareFunction.LessEqual),
};
var result = new RendererListDesc(UtsShaderPassName.hairShadowCasterPassId, ctx.cullingResults, ctx.hdCamera.camera)
{
renderQueueRange = GetRenderQueueRange(RenderQueueType.All),
sortingCriteria = SortingCriteria.CommonOpaque,
excludeObjectMotionVectors = false,
stateBlock = stateBlock,
};
CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, ctx.renderContext.CreateRendererList(result));
Shader.SetGlobalVector(Hair_Shadow_RTHandle_Scale_Prop_Name, _outputRTHandle.rtHandleProperties.rtHandleScale);
Shader.SetGlobalFloat(Hair_Shadow_Distance_Prop_Name, utsRenderer.shadowDistance.value);
Shader.SetGlobalFloat(Hair_Shadow_Distance_Scale_Prop_Name, utsRenderer.shadowDistanceScale.value);
Shader.SetGlobalFloat(Hair_Shadow_Depth_Bias_Prop_Name, utsRenderer.shadowDepthBias.value);
Shader.SetGlobalFloat(Hair_Shadow_FadeIn_Prop_Name, utsRenderer.shadowFadeIn.value);
Shader.SetGlobalFloat(Hair_Shadow_Fade_Out_Prop_Name, utsRenderer.shadowFadeOut.value);
}
protected override void Cleanup()
{
Release();
}
public void Release()
{
#if UNITY_EDITOR
if (EditorApplication.isCompiling)
{
return;
}
#endif
_outputRTHandle?.Release();
}
}
}