Files
com.misaki.hdrp-toon/Runtime/UTS Renderer/UTSPass.cs
Misaki 018300e046 Folder clean up;
Added Emissive;
2025-01-29 12:27:09 +09:00

335 lines
12 KiB
C#

using System;
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 UTSPass : CustomPass
{
private const int Adjustment_Curve_Precision = 128;
private const string Compensation_Prop_Name = "_ToonEvAdjustmentCompensation";
private const string Exposure_Adjustment_Prop_Name = "_ToonEvAdjustmentCurve";
private const string Exposure_Array_Prop_Name = "_ToonEvAdjustmentValueArray";
private const string Exposure_Min_Prop_Name = "_ToonEvAdjustmentValueMin";
private const string Exposure_Max_Prop_Name = "_ToonEvAdjustmentValueMax";
private const string Toon_Light_Filter_Prop_Name = "_ToonLightHiCutFilter";
private const string Ignore_Volume_Exposure_Prop_Name = "_ToonIgnoreExposureMultiplier";
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 Hair_Blending_RTHandle_Scale_Prop_Name = "_HairBlendingRTHandleScale";
private const string Output_RT_Prop_Name = "_HairShadowTex";
private const string Hair_Blending_Prop_Name = "_HairBlendingTex";
private float _max;
private float _min;
private float[] _exposureArray;
private RTHandle _hairShadowRTHandle;
private bool _needReallocateHairShadow;
private RTHandle _hairBlendingRTHandle;
private bool _needReallocateHairBlending;
private bool _enableHairShadow;
public bool EnableHairShadow
{
get => _enableHairShadow;
set
{
if (_enableHairShadow == value)
{
return;
}
_enableHairShadow = value;
if (_enableHairShadow)
{
Shader.EnableKeyword("ENABLE_UTS_HAIR_SHAOW");
}
else
{
Shader.DisableKeyword("ENABLE_UTS_HAIR_SHAOW");
_hairShadowRTHandle?.Release();
}
}
}
private bool _enableHairBlending;
public bool EnableHairBlending
{
get => _enableHairBlending;
set
{
if (_enableHairBlending == value)
{
return;
}
_enableHairBlending = value;
if (_enableHairBlending)
{
Shader.EnableKeyword("ENABLE_UTS_HAIR_BLENDING");
}
else
{
Shader.DisableKeyword("ENABLE_UTS_HAIR_BLENDING");
_hairBlendingRTHandle?.Release();
}
}
}
private BufferQuality _hairShadowQuality = BufferQuality.High;
internal BufferQuality HairShadowQuality
{
get => _hairShadowQuality;
set
{
if (_hairShadowQuality == value)
{
return;
}
_hairShadowQuality = value;
_needReallocateHairShadow = true;
}
}
private BufferQuality _hairBlendingQuality = BufferQuality.High;
internal BufferQuality HairBlendingQuality
{
get => _hairBlendingQuality;
set
{
if (_hairBlendingQuality == value)
{
return;
}
_hairBlendingQuality = value;
_needReallocateHairBlending = true;
}
}
private bool ShouldReallocateHairShadowBuffer()
{
return _hairShadowRTHandle == null || _hairShadowRTHandle.rt == null || !_hairShadowRTHandle.rt.IsCreated() || _needReallocateHairShadow;
}
private void ReallocateHairShadowBuffer()
{
#if UNITY_EDITOR
if (EditorApplication.isCompiling)
{
return;
}
#endif
var scale = _hairShadowQuality switch
{
BufferQuality.Low => new Vector2(0.5f, 0.5f),
BufferQuality.High => Vector2.one,
_ => Vector2.zero
};
var format = _hairShadowQuality switch
{
BufferQuality.Low => GraphicsFormat.D16_UNorm,
BufferQuality.High => GraphicsFormat.D32_SFloat,
_ => GraphicsFormat.D16_UNorm
};
_hairShadowRTHandle?.Release();
_hairShadowRTHandle = RTHandles.Alloc(scale, colorFormat: format, isShadowMap: true, useDynamicScale: true, name: Output_RT_Prop_Name);
Shader.SetGlobalTexture(Output_RT_Prop_Name, _hairShadowRTHandle);
_needReallocateHairShadow = false;
}
private bool ShouldReallocateHairBlendingBuffer()
{
return _hairBlendingRTHandle == null || _hairBlendingRTHandle.rt == null || !_hairBlendingRTHandle.rt.IsCreated() || _needReallocateHairBlending;
}
private void ReallocateHairBlendingBuffer()
{
#if UNITY_EDITOR
if (EditorApplication.isCompiling)
{
return;
}
#endif
var format = _hairBlendingQuality switch
{
BufferQuality.Low => GraphicsFormat.R8G8B8A8_SNorm,
BufferQuality.High => GraphicsFormat.R8G8B8A8_SRGB,
_ => GraphicsFormat.R8G8B8A8_SRGB
};
_hairBlendingRTHandle?.Release();
_hairBlendingRTHandle = RTHandles.Alloc(Vector2.one, colorFormat: format, useDynamicScale: true, name: Hair_Blending_Prop_Name);
Shader.SetGlobalTexture(Hair_Blending_Prop_Name, _hairBlendingRTHandle);
_needReallocateHairBlending = false;
}
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
_exposureArray = new float[Adjustment_Curve_Precision];
ReallocateHairShadowBuffer();
ReallocateHairBlendingBuffer();
}
protected override void Execute(CustomPassContext ctx)
{
var utsRenderer = ctx.hdCamera.volumeStack.GetComponent<UTSRenderer>();
UpdateSceneEV(utsRenderer);
RenderHairShadow(ref ctx, utsRenderer);
RenderHairBlending(ref ctx);
}
private void RenderHairShadow(ref CustomPassContext ctx, UTSRenderer utsRenderer)
{
if (!_enableHairShadow)
{
return;
}
if (ShouldReallocateHairShadowBuffer())
{
ReallocateHairShadowBuffer();
return;
}
CoreUtils.SetRenderTarget(ctx.cmd, _hairShadowRTHandle, ClearFlag.DepthStencil);
var shouldRender = utsRenderer != null && utsRenderer.enableHairShadow.value && utsRenderer.state.value;
if (!shouldRender)
{
return;
}
var result = new RendererListDesc(UtsShaderPassName.hairShadowCasterPassId, ctx.cullingResults, ctx.hdCamera.camera)
{
renderQueueRange = GetRenderQueueRange(RenderQueueType.All),
sortingCriteria = SortingCriteria.CommonOpaque,
excludeObjectMotionVectors = false,
};
CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, ctx.renderContext.CreateRendererList(result));
Shader.SetGlobalVector(Hair_Shadow_RTHandle_Scale_Prop_Name, _hairShadowRTHandle.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);
}
private void RenderHairBlending(ref CustomPassContext ctx)
{
if (!_enableHairBlending)
{
return;
}
if (ShouldReallocateHairBlendingBuffer())
{
ReallocateHairBlendingBuffer();
return;
}
CoreUtils.SetRenderTarget(ctx.cmd, _hairBlendingRTHandle, ctx.cameraDepthBuffer, ClearFlag.Color);
var result = new RendererListDesc(UtsShaderPassName.hairBlendingTargetPassId, ctx.cullingResults, ctx.hdCamera.camera)
{
renderQueueRange = GetRenderQueueRange(RenderQueueType.All),
sortingCriteria = SortingCriteria.CommonOpaque,
excludeObjectMotionVectors = false,
};
CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, ctx.renderContext.CreateRendererList(result));
Shader.SetGlobalVector(Hair_Blending_RTHandle_Scale_Prop_Name, _hairBlendingRTHandle.rtHandleProperties.rtHandleScale);
}
private void UpdateSceneEV(UTSRenderer utsRenderer)
{
if (utsRenderer == null)
{
return;
}
var toonEVAdjustment = utsRenderer.toonEVAdjustment.value ? 1 : 0;
var lightIntensityLimiter = utsRenderer.lightIntensityLimiter.value ? 1 : 0;
var ignoreVolumeExposure = utsRenderer.ignoreVolumeExposure.value ? 1 : 0;
var compensation = utsRenderer.compensation.value;
if (!utsRenderer.state.value)
{
_min = 0;
_max = 0;
_exposureArray.AsSpan().Fill(0);
toonEVAdjustment = 0;
lightIntensityLimiter = 0;
ignoreVolumeExposure = 0;
compensation = 0;
}
else
{
// Fail safe in case the curve is deleted / has 0 point
var curve = utsRenderer.adjustmentCurve.value;
if (curve == null || curve.length == 0)
{
_min = 0f;
_max = 0f;
_exposureArray.AsSpan().Fill(0);
}
else
{
_min = curve[0].time;
_max = curve[curve.length - 1].time;
var step = (_max - _min) / (Adjustment_Curve_Precision - 1f);
for (var i = 0; i < Adjustment_Curve_Precision; i++)
{
_exposureArray[i] = curve.Evaluate(_min + step * i);
}
}
}
Shader.SetGlobalFloatArray(Exposure_Array_Prop_Name, _exposureArray);
Shader.SetGlobalFloat(Exposure_Min_Prop_Name, _min);
Shader.SetGlobalFloat(Exposure_Max_Prop_Name, _max);
Shader.SetGlobalInt(Exposure_Adjustment_Prop_Name, toonEVAdjustment);
Shader.SetGlobalInt(Toon_Light_Filter_Prop_Name, lightIntensityLimiter);
Shader.SetGlobalInt(Ignore_Volume_Exposure_Prop_Name, ignoreVolumeExposure);
Shader.SetGlobalFloat(Compensation_Prop_Name, compensation);
}
protected override void Cleanup()
{
_exposureArray = null;
_hairShadowRTHandle?.Release();
_hairBlendingRTHandle?.Release();
}
}
}