Files
beyond/Assets/URP TAA/Shaders/TAA.shader
2024-11-20 15:21:28 +01:00

416 lines
17 KiB
GLSL

Shader "Hidden/GameOldBoy/TAA"
{
HLSLINCLUDE
#pragma multi_compile_local_fragment _ _TAA_AntiGhosting
#pragma multi_compile_local_fragment _ _TAA_UseMotionVector
#pragma multi_compile_local_fragment _ _TAA_UseBlurSharpenFilter
#pragma multi_compile_local_fragment _ _TAA_UseBicubicFilter
#pragma multi_compile_local_fragment _ _TAA_UseClipAABB
#pragma multi_compile_local_fragment _ _TAA_UseDilation
#pragma multi_compile_local_fragment _ _TAA_UseTonemap
#pragma multi_compile_local_fragment _ _TAA_UseVarianceClipping
#pragma multi_compile_local_fragment _ _TAA_UseYCoCgSpace
#pragma multi_compile_local_fragment _ _TAA_Use4Tap
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
float4 _CameraDepthTexture_TexelSize;
TEXTURE2D_X_FLOAT(_MotionVectorTexture);
TEXTURE2D_X(_SourceTex);
float4 _SourceTex_TexelSize;
TEXTURE2D_X(_TAA_Texture);
float4 _TAA_Texture_TexelSize;
float4x4 _TAA_PrevViewProj;
float2 _TAA_Offset;
float4 _TAA_Params0;
#define _TAA_Blend _TAA_Params0.x
#define _TAA_Gamma _TAA_Params0.y
#define _TAA_Sharp _TAA_Params0.z
#define _TAA_PrevSharp _TAA_Params0.w
struct VaryingsTAA
{
float4 positionCS : SV_POSITION;
float4 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
VaryingsTAA VertTAA(Attributes input)
{
VaryingsTAA output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv.xy = input.uv;
float4 projPos = output.positionCS * 0.5;
projPos.xy = projPos.xy + projPos.w;
output.uv.zw = projPos.xy;
return output;
}
#if _TAA_AntiGhosting
float3 clip_color(float3 min_color, float3 max_color, float3 color)
{
#if _TAA_UseClipAABB
float3 p_clip = 0.5 * (max_color + min_color);
float3 e_clip = 0.5 * (max_color - min_color) + FLT_EPS;
float3 v_clip = color - p_clip;
float3 v_unit = v_clip / e_clip;
float3 a_unit = abs(v_unit);
float ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z));
if (ma_unit > 1.0)
return p_clip + v_clip / ma_unit;
else
return color;
#else
return clamp(color, min_color, max_color);
#endif
}
void minmax(float3 samples[9], out float3 min_color, out float3 max_color)
{
float3 color[9];
#if _TAA_UseYCoCgSpace
color[0] = RGBToYCoCg(samples[0]);
color[1] = RGBToYCoCg(samples[1]);
color[2] = RGBToYCoCg(samples[2]);
color[3] = RGBToYCoCg(samples[3]);
color[4] = RGBToYCoCg(samples[4]);
color[5] = RGBToYCoCg(samples[5]);
color[6] = RGBToYCoCg(samples[6]);
color[7] = RGBToYCoCg(samples[7]);
color[8] = RGBToYCoCg(samples[8]);
#else
color[0] = samples[0];
color[1] = samples[1];
color[2] = samples[2];
color[3] = samples[3];
color[4] = samples[4];
color[5] = samples[5];
color[6] = samples[6];
color[7] = samples[7];
color[8] = samples[8];
#endif
#if _TAA_UseVarianceClipping
float3 m1 = color[0] + color[1] + color[2]
+ color[3] + color[4] + color[5]
+ color[6] + color[7] + color[8];
float3 m2 = color[0] * color[0] + color[1] * color[1] + color[2] * color[2]
+ color[3] * color[3] + color[4] * color[4] + color[5] * color[5]
+ color[6] * color[6] + color[7] * color[7] + color[8] * color[8];
float3 mu = m1 / 9;
float3 sigma = sqrt(abs(m2 / 9 - mu * mu));
min_color = mu - _TAA_Gamma * sigma;
max_color = mu + _TAA_Gamma * sigma;
#else
min_color = min(color[0], min(color[1], min(color[2], min(color[3], min(color[4], min(color[5], min(color[6], min(color[7], color[8]))))))));
max_color = max(color[0], max(color[1], max(color[2], max(color[3], max(color[4], max(color[5], max(color[6], max(color[7], color[8]))))))));
float3 min_color5 = min(color[1], min(color[3], min(color[4], min(color[5], color[7]))));
float3 max_color5 = max(color[1], max(color[3], max(color[4], max(color[5], color[7]))));
min_color = 0.5 * (min_color + min_color5);
max_color = 0.5 * (max_color + max_color5);
#endif
}
void minmax_4tap(float2 uv, float2 mv, float depth, out float3 min_color, out float3 max_color)
{
const float _SubpixelThreshold = 0.5;
const float _GatherBase = 0.5;
const float _GatherSubpixelMotion = 0.1666;
float2 texel_vel = mv / _SourceTex_TexelSize.xy;
float texel_vel_mag = length(texel_vel) * depth;
float k_subpixel_motion = saturate(_SubpixelThreshold / (FLT_EPS + texel_vel_mag));
float k_min_max_support = _GatherBase + _GatherSubpixelMotion * k_subpixel_motion;
float2 ss_offset01 = k_min_max_support * float2(-_SourceTex_TexelSize.x, _SourceTex_TexelSize.y);
float2 ss_offset11 = k_min_max_support * float2(_SourceTex_TexelSize.x, _SourceTex_TexelSize.y);
float3 c00 = SAMPLE_TEXTURE2D_X(_SourceTex,sampler_LinearClamp, uv - ss_offset11).rgb;
float3 c10 = SAMPLE_TEXTURE2D_X(_SourceTex,sampler_LinearClamp, uv - ss_offset01).rgb;
float3 c01 = SAMPLE_TEXTURE2D_X(_SourceTex,sampler_LinearClamp, uv + ss_offset01).rgb;
float3 c11 = SAMPLE_TEXTURE2D_X(_SourceTex,sampler_LinearClamp, uv + ss_offset11).rgb;
#if _TAA_UseYCoCgSpace
c00 = RGBToYCoCg(c00);
c10 = RGBToYCoCg(c10);
c01 = RGBToYCoCg(c01);
c11 = RGBToYCoCg(c11);
#endif
min_color = min(c00, min(c10, min(c01, c11)));
max_color = max(c00, max(c10, max(c01, c11)));
}
#endif
float3 filter(float3 _sample)
{
return _sample;
}
float3 filter(float3 samples[9])
{
#if _TAA_UseBlurSharpenFilter
const float k_blur0 = 0.6915221;
const float k_blur1 = 0.07002799;
const float k_blur2 = 0.007091487;
float3 blur_color = (samples[0] + samples[2] + samples[6] + samples[8]) * k_blur2 +
(samples[1] + samples[3] + samples[5] + samples[7]) * k_blur1 +
samples[4] * k_blur0;
float3 avg_color = (samples[0] + samples[1] + samples[2]
+ samples[3] + samples[4] + samples[5]
+ samples[6] + samples[7] + samples[8]) / 9;
float3 sharp_color = blur_color + (blur_color - avg_color) * _TAA_Sharp * 3;
return clamp(sharp_color, 0, 65472.0);
#else
return samples[4];
#endif
}
void get_samples(float2 uv, out float3 _sample)
{
_sample = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv).rgb;
}
void get_samples(float2 uv, out float3 samples[9])
{
samples[0] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2(-1, -1)).rgb;
samples[1] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2( 0, -1)).rgb;
samples[2] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2( 1, -1)).rgb;
samples[3] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2(-1, 0)).rgb;
get_samples(uv, samples[4]);
samples[5] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2( 1, 0)).rgb;
samples[6] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2(-1, 1)).rgb;
samples[7] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2( 0, 1)).rgb;
samples[8] = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv + _SourceTex_TexelSize.xy * float2( 1, 1)).rgb;
}
float3 sample_taa_tex(float2 uv)
{
#if _TAA_UseBicubicFilter
float2 samplePos = uv * _TAA_Texture_TexelSize.zw;
float2 tc1 = floor(samplePos - 0.5) + 0.5;
float2 f = samplePos - tc1;
float2 f2 = f * f;
float2 f3 = f * f2;
const float c = _TAA_PrevSharp;
float2 w0 = -c * f3 + 2.0 * c * f2 - c * f;
float2 w1 = (2.0 - c) * f3 - (3.0 - c) * f2 + 1.0;
float2 w2 = -(2.0 - c) * f3 + (3.0 - 2.0 * c) * f2 + c * f;
float2 w3 = c * f3 - c * f2;
float2 w12 = w1 + w2;
float2 tc0 = _TAA_Texture_TexelSize.xy * (tc1 - 1.0);
float2 tc3 = _TAA_Texture_TexelSize.xy * (tc1 + 2.0);
float2 tc12 = _TAA_Texture_TexelSize.xy * (tc1 + w2 / w12);
float3 s0 = SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, float2(tc12.x, tc0.y)).rgb;
float3 s1 = SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, float2(tc0.x, tc12.y)).rgb;
float3 s2 = SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, float2(tc12.x, tc12.y)).rgb;
float3 s3 = SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, float2(tc3.x, tc0.y)).rgb;
float3 s4 = SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, float2(tc12.x, tc3.y)).rgb;
float cw0 = (w12.x * w0.y);
float cw1 = (w0.x * w12.y);
float cw2 = (w12.x * w12.y);
float cw3 = (w3.x * w12.y);
float cw4 = (w12.x * w3.y);
float3 min_color = min(s0, min(s1, s2));
min_color = min(min_color, min(s3, s4));
float3 max_color = max(s0, max(s1, s2));
max_color = max(max_color, max(s3, s4));
s0 *= cw0;
s1 *= cw1;
s2 *= cw2;
s3 *= cw3;
s4 *= cw4;
float3 historyFiltered = s0 + s1 + s2 + s3 + s4;
float weightSum = cw0 + cw1 + cw2 + cw3 + cw4;
float3 filteredVal = historyFiltered * rcp(weightSum);
return clamp(filteredVal, min_color, max_color);
#else
return SAMPLE_TEXTURE2D_X(_TAA_Texture, sampler_LinearClamp, uv).rgb;
#endif
}
float3 ReinhardToneMap(float3 c)
{
return c * rcp(Luminance(c) + 1.0);
}
float3 InverseReinhardToneMap(float3 c)
{
return c * rcp(1.0 - Luminance(c));
}
#if UNITY_REVERSED_Z
#define ZCMP_GT(a, b) (a < b)
#else
#define ZCMP_GT(a, b) (a > b)
#endif
float2 find_closest_uv(float depth, float2 uv)
{
float2 dd = _CameraDepthTexture_TexelSize.xy;
float2 du = float2(dd.x, 0.0);
float2 dv = float2(0.0, dd.y);
float3 dtl = float3(-1, -1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv - dv - du).r);
float3 dtc = float3( 0, -1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv - dv).r);
float3 dtr = float3( 1, -1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv - dv + du).r);
float3 dml = float3(-1, 0, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv - du).r);
float3 dmc = float3( 0, 0, depth);
float3 dmr = float3( 1, 0, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv + du).r);
float3 dbl = float3(-1, 1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv + dv - du).r);
float3 dbc = float3( 0, 1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv + dv).r);
float3 dbr = float3( 1, 1, SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv + dv + du).r);
float3 dmin = dtl;
if (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc;
if (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr;
if (ZCMP_GT(dmin.z, dml.z)) dmin = dml;
if (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc;
if (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr;
if (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl;
if (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc;
if (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr;
return uv + dd.xy * dmin.xy;
}
float2 reprojection(float depth, float2 uv)
{
#if UNITY_REVERSED_Z
depth = 1.0 - depth;
#endif
depth = 2.0 * depth - 1.0;
float3 viewPos = ComputeViewSpacePosition(uv, depth, unity_CameraInvProjection);
float4 worldPos = float4(mul(unity_CameraToWorld, float4(viewPos, 1.0)).xyz, 1.0);
float4 prevClipPos = mul(_TAA_PrevViewProj, worldPos);
float2 prevPosCS = prevClipPos.xy / prevClipPos.w;
return prevPosCS * 0.5 + 0.5;
}
float4 Frag(VaryingsTAA input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float2 uv = UnityStereoTransformScreenSpaceTex(input.uv.xy);
float depth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv).r;
#if _TAA_UseMotionVector
#if _TAA_UseDilation
float2 mv = SAMPLE_TEXTURE2D_X(_MotionVectorTexture, sampler_LinearClamp, find_closest_uv(depth, uv)).rg;
#else
float2 mv = SAMPLE_TEXTURE2D_X(_MotionVectorTexture, sampler_LinearClamp, uv).rg;
#endif
float2 prev_uv = uv - mv - _TAA_Offset;
mv = uv - prev_uv;
#else
float2 prev_uv = reprojection(depth, input.uv.zw);
float2 mv = uv - prev_uv;
#endif
#if _TAA_Use4Tap
float3 samples;
#else
float3 samples[9];
#endif
get_samples(uv, samples);
if (prev_uv.x > 1.0 || prev_uv.y > 1.0 || prev_uv.x < 0.0 || prev_uv.y < 0.0)
{
return float4(max(float3(0.0, 0.0, 0.0), filter(samples)), 1.0);
}
float3 prev_color = sample_taa_tex(prev_uv);
#if _TAA_AntiGhosting
float3 min_color, max_color;
#if _TAA_Use4Tap
minmax_4tap(uv, mv, depth, min_color, max_color);
#else
minmax(samples, min_color, max_color);
#endif
#if _TAA_UseYCoCgSpace
prev_color = YCoCgToRGB(clip_color(min_color, max_color, RGBToYCoCg(prev_color)));
#else
prev_color = clip_color(min_color, max_color, prev_color);
#endif
#endif
float final_blend = lerp(_TAA_Blend, 0.2, saturate(length(mv) * 20.0));
#if _TAA_UseTonemap
float3 color = ReinhardToneMap(filter(samples));
prev_color = ReinhardToneMap(prev_color);
float3 final_color = InverseReinhardToneMap(lerp(color, prev_color, final_blend));
#else
float3 color = filter(samples);
float3 final_color = lerp(color, prev_color, final_blend);
#endif
return float4(max(float3(0.0, 0.0, 0.0), final_color), 1.0);
}
Varyings VertBlit(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = input.uv;
return output;
}
half4 FragBlit(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float2 uv = UnityStereoTransformScreenSpaceTex(input.uv);
return half4(SAMPLE_TEXTURE2D_X(_SourceTex, sampler_PointClamp, uv).rgb, 1.0);
}
ENDHLSL
SubShader
{
Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
LOD 100
ZTest Always ZWrite Off Cull Off
Pass // Index 0
{
Name "TAA"
HLSLPROGRAM
#pragma vertex VertTAA
#pragma fragment Frag
ENDHLSL
}
Pass // Index 1
{
Name "Blit"
HLSLPROGRAM
#pragma vertex VertBlit
#pragma fragment FragBlit
ENDHLSL
}
}
}