2023-12-11 07:00:09 +00:00
|
|
|
#if HLSL
|
|
|
|
#define SAMPLE(texture, sampler, uv) SAMPLE_TEXTURE2D_X(texture, sampler, uv)
|
|
|
|
#else
|
|
|
|
#define SAMPLE(texture, sampler, uv) UNITY_SAMPLE_SCREENSPACE_TEXTURE(texture, uv)
|
|
|
|
#endif
|
2023-09-24 04:38:25 +00:00
|
|
|
|
|
|
|
//CAVITY V
|
|
|
|
#ifdef CAVITY_SAMPLES_6
|
|
|
|
#define CAVITY_SAMPLES 6
|
|
|
|
#endif
|
|
|
|
#ifdef CAVITY_SAMPLES_8
|
|
|
|
#define CAVITY_SAMPLES 8
|
|
|
|
#endif
|
|
|
|
#ifdef CAVITY_SAMPLES_12
|
|
|
|
#define CAVITY_SAMPLES 12
|
|
|
|
#endif
|
2023-12-11 07:00:09 +00:00
|
|
|
#ifdef CAVITY_SAMPLES_20
|
|
|
|
#define CAVITY_SAMPLES 20
|
|
|
|
#endif
|
2023-09-24 04:38:25 +00:00
|
|
|
#ifdef SSCC_HDRP
|
|
|
|
#define ACTUAL_CAVITY_SAMPLES (CAVITY_SAMPLES+2)
|
|
|
|
#else
|
|
|
|
#define ACTUAL_CAVITY_SAMPLES (CAVITY_SAMPLES)
|
|
|
|
#endif
|
|
|
|
float _InterleavedGradientNoise(float2 pixCoord, int frameCount)
|
|
|
|
{
|
|
|
|
const float3 magic = float3(0.06711056f, 0.00583715f, 52.9829189f);
|
|
|
|
float2 frameMagicScale = float2(2.083f, 4.867f);
|
|
|
|
pixCoord += frameCount * frameMagicScale;
|
|
|
|
return frac(magic.z * frac(dot(pixCoord, magic.xy)));
|
|
|
|
}
|
|
|
|
float3 PickSamplePoint(float2 uv, float randAddon, int index)
|
|
|
|
{
|
2023-12-11 07:00:09 +00:00
|
|
|
float2 positionSS = uv * _CavityTex_TexelSize.zw;
|
2023-09-24 04:38:25 +00:00
|
|
|
float gn = _InterleavedGradientNoise(positionSS, index);
|
|
|
|
float u = frac(gn) * 2.0 - 1.0;
|
|
|
|
float theta = gn * 6.28318530717958647693;
|
|
|
|
float sn, cs;
|
|
|
|
sincos(theta, sn, cs);
|
|
|
|
return float3(float2(cs, sn) * sqrt(1.0 - u * u), u);
|
|
|
|
}
|
|
|
|
float3x3 GetCoordinateConversionParameters(out float2 p11_22, out float2 p13_31)
|
|
|
|
{
|
|
|
|
float3x3 camProj = (float3x3)unity_CameraProjection;
|
|
|
|
//float3x3 camProj = (float3x3)/*UNITY_MATRIX_P*/_Projection;
|
|
|
|
p11_22 = rcp(float2(camProj._11, camProj._22));
|
|
|
|
p13_31 = float2(camProj._13, camProj._23);
|
|
|
|
return camProj;
|
|
|
|
}
|
|
|
|
float3 ReconstructViewPos(float2 uv, float depth, float2 p11_22, float2 p13_31)
|
|
|
|
{
|
|
|
|
#if ORTHOGRAPHIC_PROJECTION
|
|
|
|
float3 viewPos = float3(((uv.xy * 2.0 - 1.0 - p13_31) * p11_22), depth);
|
|
|
|
#else
|
|
|
|
float3 viewPos = float3(depth * ((uv.xy * 2.0 - 1.0 - p13_31) * p11_22), depth);
|
|
|
|
#endif
|
|
|
|
return viewPos;
|
|
|
|
}
|
|
|
|
void SampleDepthAndViewpos(float2 uv, float2 p11_22, float2 p13_31, out float depth, out float3 vpos)
|
|
|
|
{
|
|
|
|
depth = LinearizeDepth(FetchRawDepth(uv));
|
|
|
|
vpos = ReconstructViewPos(uv, depth, p11_22, p13_31);
|
|
|
|
}
|
|
|
|
void Cavity(float2 uv, float3 normal, out float cavity, out float edges)
|
|
|
|
{
|
|
|
|
cavity = edges = 0.0;
|
|
|
|
float2 p11_22, p13_31;
|
|
|
|
float3x3 camProj = GetCoordinateConversionParameters(p11_22, p13_31);
|
|
|
|
|
|
|
|
float depth;
|
|
|
|
float3 vpos;
|
|
|
|
SampleDepthAndViewpos(uv, p11_22, p13_31, depth, vpos);
|
|
|
|
|
|
|
|
float randAddon = uv.x * 1e-10;
|
|
|
|
float rcpSampleCount = rcp(ACTUAL_CAVITY_SAMPLES);
|
|
|
|
|
|
|
|
//UNITY_LOOP
|
|
|
|
UNITY_UNROLL
|
|
|
|
for (int i = 0; i < int(ACTUAL_CAVITY_SAMPLES); i++)
|
|
|
|
{
|
|
|
|
#if defined(SHADER_API_D3D11)
|
|
|
|
i = floor(1.0001 * i);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
float3 v_s1 = PickSamplePoint(uv.yx, randAddon, i);
|
|
|
|
#else
|
|
|
|
float3 v_s1 = PickSamplePoint(uv, randAddon, i);
|
|
|
|
#endif
|
|
|
|
v_s1 *= sqrt((i + 1.0) * rcpSampleCount) * _CavityWorldRadius * 0.5;
|
|
|
|
float3 vpos_s1 = vpos + v_s1;
|
|
|
|
|
|
|
|
float3 spos_s1 = mul(camProj, vpos_s1);
|
|
|
|
#if ORTHOGRAPHIC_PROJECTION
|
|
|
|
float2 uv_s1_01 = clamp((spos_s1.xy + 1.0) * 0.5, 0.0, 1.0);
|
|
|
|
#else
|
|
|
|
float2 uv_s1_01 = clamp((spos_s1.xy * rcp(vpos_s1.z) + 1.0) * 0.5, 0.0, 1.0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
float depth_s1 = LinearizeDepth(FetchRawDepth(uv_s1_01));
|
|
|
|
float3 vpos_s2 = ReconstructViewPos(uv_s1_01, depth_s1, p11_22, p13_31);
|
|
|
|
|
|
|
|
float3 dir = vpos_s2 - vpos;
|
|
|
|
float len = length(dir);
|
|
|
|
float f_dot = dot(dir, normal);
|
|
|
|
//float kBeta = 0.002;
|
|
|
|
float kBeta = 0.002 * 4;
|
|
|
|
float f_cavities = f_dot - kBeta * depth;
|
|
|
|
float f_edge = -f_dot - kBeta * depth;
|
|
|
|
float f_bias = 0.05 * len + 0.0001;
|
|
|
|
|
|
|
|
if (f_cavities > -f_bias)
|
|
|
|
{
|
|
|
|
float attenuation = 1.0 / (len * (1.0 + len * len * 3.));
|
|
|
|
cavity += f_cavities * attenuation;
|
|
|
|
}
|
|
|
|
if (f_edge > f_bias)
|
|
|
|
{
|
|
|
|
float attenuation = 1.0 / (len * (1.0 + len * len * 0.01));
|
|
|
|
edges += f_edge * attenuation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//cavity *= 1.0 / ACTUAL_CAVITY_SAMPLES;
|
|
|
|
//edges *= 1.0 / ACTUAL_CAVITY_SAMPLES;
|
|
|
|
cavity *= 1.0 * _CavityWorldRadius * 0.5;
|
|
|
|
edges *= 1.0 * _CavityWorldRadius * 0.5;
|
|
|
|
|
|
|
|
float kContrast = 0.6;
|
|
|
|
cavity = pow(abs(cavity * rcpSampleCount), kContrast);
|
|
|
|
edges = pow(abs(edges * rcpSampleCount), kContrast);
|
|
|
|
|
|
|
|
cavity = clamp(cavity * _CavityDarks, 0.0, 1.0);
|
|
|
|
edges = edges * _CavityBrights;
|
|
|
|
}
|
|
|
|
//CAVITY ^
|
|
|
|
|
|
|
|
//CURVATURE V
|
|
|
|
float CurvatureSoftClamp(float curvature, float control)
|
|
|
|
{
|
|
|
|
if (curvature < 0.5 / control)
|
|
|
|
return curvature * (1.0 - curvature * control);
|
|
|
|
return 0.25 / control;
|
|
|
|
}
|
|
|
|
float Curvature(float2 uv, float3 P)
|
|
|
|
{
|
|
|
|
float3 offset = float3(_Input_TexelSize.xy, 0.0) * (_CurvaturePixelRadius);
|
|
|
|
|
|
|
|
float normal_up = FetchViewNormals(P, uv + offset.zy).g;
|
|
|
|
float normal_down = FetchViewNormals(P, uv - offset.zy).g;
|
|
|
|
float normal_right = FetchViewNormals(P, uv + offset.xz).r;
|
|
|
|
float normal_left = FetchViewNormals(P, uv - offset.xz).r;
|
|
|
|
|
|
|
|
float normal_diff = (normal_up - normal_down) + (normal_right - normal_left);
|
|
|
|
|
2023-12-11 07:00:09 +00:00
|
|
|
//if (abs(normal_diff) <= 0.1) return 0; //slight low pass filter to remove noise from camera normals precision
|
|
|
|
//new and improved low pass filter:
|
|
|
|
//if (uv.x < 0.5)
|
|
|
|
{
|
|
|
|
if (normal_diff > 0.0) normal_diff = sign(normal_diff) * pow(normal_diff, 2.0);
|
|
|
|
_CavityBrights += 0.5;
|
|
|
|
}
|
2023-09-24 04:38:25 +00:00
|
|
|
|
|
|
|
if (normal_diff >= 0.0)
|
|
|
|
return 2.0 * CurvatureSoftClamp(normal_diff, _CurvatureBrights);
|
|
|
|
else
|
|
|
|
return -2.0 * CurvatureSoftClamp(-normal_diff, _CurvatureDarks);
|
|
|
|
}
|
|
|
|
//CURVATURE ^
|
|
|
|
|
|
|
|
float invLerp(float from, float to, float value) {
|
|
|
|
return (value - from) / (to - from);
|
|
|
|
}
|
|
|
|
float remap(float origFrom, float origTo, float targetFrom, float targetTo, float value) {
|
|
|
|
float rel = invLerp(origFrom, origTo, value);
|
|
|
|
return lerp(targetFrom, targetTo, rel);
|
|
|
|
}
|
2023-12-11 07:00:09 +00:00
|
|
|
|
|
|
|
float4 Cavity_Frag(Varyings input) : SV_Target
|
|
|
|
{
|
|
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
#ifdef UnityStereoTransformScreenSpaceTex
|
|
|
|
float2 uv = UnityStereoTransformScreenSpaceTex(input.uv);
|
|
|
|
#else
|
|
|
|
float2 uv = input.uv;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
float3 P = FetchViewPos(uv);
|
|
|
|
float3 N = FetchViewNormals(P, uv);
|
|
|
|
|
|
|
|
float cavity = 0.0, edges = 0.0;
|
|
|
|
Cavity(uv, N, cavity, edges);
|
|
|
|
return float4(cavity, edges, FetchRawDepth(uv), 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
float2 GaussianBlur(float2 uv, float2 pixelOffset)
|
|
|
|
{
|
|
|
|
const float gWeights[2] =
|
|
|
|
{
|
|
|
|
0.44908,
|
|
|
|
0.05092
|
|
|
|
};
|
|
|
|
const float gOffsets[2] =
|
|
|
|
{
|
|
|
|
0.53805,
|
|
|
|
2.06278
|
|
|
|
};
|
|
|
|
float2 colOut = 0.0;
|
|
|
|
UNITY_UNROLL
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
float2 texCoordOffset = pixelOffset * gOffsets[i];
|
|
|
|
float2 p1 = SAMPLE(_MainTex, sampler_LinearClamp, uv + texCoordOffset).xy;
|
|
|
|
float2 p2 = SAMPLE(_MainTex, sampler_LinearClamp, uv - texCoordOffset).xy;
|
|
|
|
colOut += gWeights[i] * (p1 + p2);
|
|
|
|
}
|
|
|
|
return colOut;
|
|
|
|
}
|
|
|
|
float4 HorizontalBlur_Frag(Varyings input) : SV_Target
|
|
|
|
{
|
|
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
|
|
|
|
return float4
|
|
|
|
(
|
|
|
|
GaussianBlur(input.uv, float2(_CavityTex_TexelSize.x, 0.0)),
|
|
|
|
SAMPLE(_MainTex, sampler_LinearClamp, input.uv).z,
|
|
|
|
1.0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
float4 VerticalBlur_Frag(Varyings input) : SV_Target
|
|
|
|
{
|
|
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
|
|
|
|
return float4
|
|
|
|
(
|
|
|
|
GaussianBlur(input.uv, float2(0.0, _CavityTex_TexelSize.y)),
|
|
|
|
SAMPLE(_MainTex, sampler_LinearClamp, input.uv).z,
|
|
|
|
1.0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-09-24 04:38:25 +00:00
|
|
|
float4 Composite_Frag(Varyings input) : SV_Target
|
|
|
|
{
|
|
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
#ifdef UnityStereoTransformScreenSpaceTex
|
|
|
|
float2 uv = UnityStereoTransformScreenSpaceTex(input.uv);
|
|
|
|
#else
|
|
|
|
float2 uv = input.uv;
|
|
|
|
#endif
|
2023-12-11 07:00:09 +00:00
|
|
|
|
2023-09-24 04:38:25 +00:00
|
|
|
float3 P = FetchViewPos(uv);
|
|
|
|
float3 N = FetchViewNormals(P, uv);
|
|
|
|
float4 col = FetchSceneColor(uv);
|
|
|
|
float4 untouchedCol = FetchSceneColor(uv);
|
|
|
|
//float depth01 = FetchRawDepth(uv);
|
|
|
|
//if (depth01 == 1.0 || depth01 == 0.0) return col;
|
|
|
|
|
|
|
|
float curvature = 0.0;
|
|
|
|
curvature = Curvature(uv, P);
|
2023-12-11 07:00:09 +00:00
|
|
|
|
|
|
|
//float cavity = 0.0, edges = 0.0;
|
|
|
|
//Cavity(uv, N, cavity, edges);
|
|
|
|
|
|
|
|
float2 cavityTex;
|
|
|
|
#if UPSCALE_CAVITY
|
|
|
|
float2 LowResTexelSize = _CavityTex_TexelSize.xy;
|
|
|
|
float2 LowResBufferSize = _CavityTex_TexelSize.zw;
|
|
|
|
float2 Corner00UV = floor(uv * LowResBufferSize - .5f) / LowResBufferSize + .5f * LowResTexelSize;
|
|
|
|
float2 BilinearWeights = (uv - Corner00UV) * LowResBufferSize;
|
|
|
|
|
|
|
|
//xy is signal, z is depth it used
|
|
|
|
float3 TextureValues00 = SAMPLE(_CavityTex, sampler_LinearClamp, Corner00UV).xyz;
|
|
|
|
float3 TextureValues10 = SAMPLE(_CavityTex, sampler_LinearClamp, Corner00UV + float2(LowResTexelSize.x, 0)).xyz;
|
|
|
|
float3 TextureValues01 = SAMPLE(_CavityTex, sampler_LinearClamp, Corner00UV + float2(0, LowResTexelSize.y)).xyz;
|
|
|
|
float3 TextureValues11 = SAMPLE(_CavityTex, sampler_LinearClamp, Corner00UV + LowResTexelSize).xyz;
|
|
|
|
|
|
|
|
float4 CornerWeights = float4(
|
|
|
|
(1 - BilinearWeights.y) * (1 - BilinearWeights.x),
|
|
|
|
(1 - BilinearWeights.y) * BilinearWeights.x,
|
|
|
|
BilinearWeights.y * (1 - BilinearWeights.x),
|
|
|
|
BilinearWeights.y * BilinearWeights.x);
|
|
|
|
|
|
|
|
float Epsilon = .0001f/*-.0001f*//*0.0f*/;
|
|
|
|
|
|
|
|
float4 CornerDepths = abs(float4(TextureValues00.z, TextureValues10.z, TextureValues01.z, TextureValues11.z));
|
|
|
|
float SceneDepth = FetchRawDepth(uv);
|
|
|
|
float4 DepthWeights = 1.0f / (abs(CornerDepths - SceneDepth.xxxx) + Epsilon);
|
|
|
|
float4 FinalWeights = CornerWeights * DepthWeights;
|
|
|
|
|
|
|
|
cavityTex = (FinalWeights.x*TextureValues00.xy + FinalWeights.y*TextureValues10.xy + FinalWeights.z*TextureValues01.xy + FinalWeights.w*TextureValues11.xy) / dot(FinalWeights, 1);
|
|
|
|
#else
|
|
|
|
cavityTex = SAMPLE(_CavityTex, sampler_LinearClamp, uv).xy;
|
|
|
|
#endif
|
|
|
|
float cavity = cavityTex.r, edges = cavityTex.g;
|
2023-09-24 04:38:25 +00:00
|
|
|
|
|
|
|
if (uv.x < _Input_TexelSize.x * 2 || uv.y < _Input_TexelSize.y * 2 || 1 - uv.x < _Input_TexelSize.x * 2 || 1 - uv.y < _Input_TexelSize.y * 2) { curvature = cavity = edges = 0; };
|
|
|
|
|
|
|
|
col.rgb += (curvature * 0.4);
|
|
|
|
|
|
|
|
#if SATURATE_CAVITY
|
2023-12-11 07:00:09 +00:00
|
|
|
//float3 extra = col.rgb - saturate(col.rgb);
|
2023-09-24 04:38:25 +00:00
|
|
|
col.rgb = pow(saturate(col.rgb), 1 - (edges * 0.5));
|
|
|
|
col.rgb = pow(saturate(col.rgb), 1 + (cavity * 1));
|
2023-12-11 07:00:09 +00:00
|
|
|
//col.rgb += extra;
|
2023-09-24 04:38:25 +00:00
|
|
|
#else
|
|
|
|
col.rgb += (edges * 0.2);
|
|
|
|
col.rgb -= (cavity * 0.2);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//Uncomment this block of code for on/off back and forth effect preview
|
|
|
|
//if (uv.x < sin(_Time.y+(3.1415/2)) * 0.5 + 0.5)
|
|
|
|
//{
|
|
|
|
// if (uv.x > (sin(_Time.y+(3.1415/2)) * 0.5 + 0.5) - 0.002) return 0;
|
|
|
|
// return untouchedCol;
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
#if DEBUG_EFFECT
|
|
|
|
return ((1.0 - cavity) * (1.0 + edges) * (1.0 + curvature)) * 0.25;
|
|
|
|
#elif DEBUG_NORMALS
|
|
|
|
return float4(N * 0.5 + 0.5, 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if OUTPUT_TO_TEXTURE
|
|
|
|
float r = curvature * 0.4;
|
|
|
|
float g = (edges * 0.2) - (cavity * 0.2);
|
|
|
|
return float4(r * rcp(max(1, P.z * _DistanceFade)) * _EffectIntensity, g * rcp(max(1, P.z * _DistanceFade)) * _EffectIntensity, 1, 1);
|
|
|
|
//Values rescaled so they're more consistent to work with, if you just +curvature+edges it should match 'screen' output
|
|
|
|
#else
|
|
|
|
return lerp(untouchedCol, col, rcp(max(1, P.z * _DistanceFade)) * _EffectIntensity);
|
|
|
|
#endif
|
|
|
|
}
|