109 lines
3.6 KiB
Plaintext
109 lines
3.6 KiB
Plaintext
Shader "SLS/Postprocessing/AnimeACES"
|
||
{
|
||
SubShader
|
||
{
|
||
Tags
|
||
{
|
||
"RenderType" = "Opaque"
|
||
"RenderPipeline" = "UniversalPipeline"
|
||
}
|
||
ZWrite Off
|
||
Cull Off
|
||
ZTest Always
|
||
|
||
Pass
|
||
{
|
||
Name "Anime ACES Tonemapping"
|
||
Blend Off // 强制覆盖
|
||
|
||
HLSLPROGRAM
|
||
#pragma vertex Vert
|
||
#pragma fragment Frag
|
||
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||
|
||
// --- 参数定义 ---
|
||
float4 _TonemapParams;
|
||
// x: Exposure
|
||
// y: Contrast
|
||
// z: Saturation
|
||
// w: Hue Preservation (新增:色彩保留强度 0-1)
|
||
|
||
float4 _ACESCoeffs;
|
||
// x: A, y: B, z: C, w: D
|
||
|
||
float _ACES_E; // E
|
||
|
||
float4 _ColorFilter;
|
||
|
||
// Narkowicz ACES 曲线
|
||
float3 ACESCurve(float3 x)
|
||
{
|
||
float a = _ACESCoeffs.x;
|
||
float b = _ACESCoeffs.y;
|
||
float c = _ACESCoeffs.z;
|
||
float d = _ACESCoeffs.w;
|
||
float e = _ACES_E;
|
||
|
||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||
}
|
||
|
||
// 标量版本
|
||
float ACESCurve(float x)
|
||
{
|
||
float a = _ACESCoeffs.x;
|
||
float b = _ACESCoeffs.y;
|
||
float c = _ACESCoeffs.z;
|
||
float d = _ACESCoeffs.w;
|
||
float e = _ACES_E;
|
||
|
||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||
}
|
||
|
||
half4 Frag(Varyings input) : SV_Target
|
||
{
|
||
float2 uv = input.texcoord;
|
||
half4 sceneColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||
half3 color = sceneColor.rgb;
|
||
|
||
// 1. Exposure (曝光)
|
||
color *= _TonemapParams.x;
|
||
|
||
// 2. Contrast (对比度) - 【核心修正】
|
||
// Pivot 从 0.5 改为 0.18 (Linear Middle Gray)
|
||
// 这样增加对比度会压暗阴影,而不是提亮阴影
|
||
float midGray = 0.18;
|
||
color = (color - midGray) * _TonemapParams.y + midGray;
|
||
color = max(0, color);
|
||
|
||
// 3. ACES Tonemapping with Hue Preservation (色彩保留) - 【核心修正】
|
||
float huePreserve = _TonemapParams.w;
|
||
|
||
// A. 标准 ACES (会吃色,RGB 通道独立压缩)
|
||
float3 acesFit = ACESCurve(color);
|
||
|
||
// B. 亮度 ACES (不吃色,只压缩亮度)
|
||
float lum = Luminance(color);
|
||
float lumTonemapped = ACESCurve(lum);
|
||
// 重建颜色:保持原色相,只改变亮度
|
||
float3 colorPreserved = color * (lumTonemapped / max(lum, 1e-4));
|
||
|
||
// 混合两者:二次元通常希望皮肤保色(B),但场景光影有电影感(A)
|
||
// 建议 Hue Preservation 设为 0.5 左右
|
||
color = lerp(acesFit, colorPreserved, huePreserve);
|
||
|
||
// 4. Saturation (饱和度)
|
||
// 重新计算亮度进行饱和度调整
|
||
float finalLum = Luminance(color);
|
||
color = lerp(finalLum.xxx, color, _TonemapParams.z);
|
||
|
||
// 5. Color Filter
|
||
color *= _ColorFilter.rgb;
|
||
|
||
return half4(color, sceneColor.a);
|
||
}
|
||
ENDHLSL
|
||
}
|
||
}
|
||
} |