summaryrefslogtreecommitdiffstats
path: root/tooner_lighting.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-02-01 19:15:58 -0800
committeryum <yum.food.vr@gmail.com>2025-02-01 19:15:58 -0800
commitfb26b02a20ef751cdd1832abc925b5e57bb2234b (patch)
tree265f343a4b57e6345468ff5c37902fdd66a3764e /tooner_lighting.cginc
parent4bd9c2ba494013f292ddc14d793bc2b362aff365 (diff)
Implement surface stable fractal dithering
Diffstat (limited to 'tooner_lighting.cginc')
-rw-r--r--tooner_lighting.cginc59
1 files changed, 59 insertions, 0 deletions
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index 3241394..ab885e6 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -1069,6 +1069,65 @@ float4 effect(inout v2f i, out float depth)
const float frame = 0;
#endif // _FRAME_COUNTER
+#if defined(_SURFACE_STABLE_FRACTAL_DITHERING)
+ {
+ float2 duv = i.uv0;
+
+ //float duv_fw = fwidth(duv.x) + fwidth(duv.y);
+ // Original paper uses SVD instead of fwidth.
+ float2x2 M = float2x2(ddx(duv), ddy(duv));
+ float2x2 MtM = mul(transpose(M), M);
+ float trace = MtM[0][0] + MtM[1][1];
+ float det = determinant(MtM);
+ // Calculate eigenvalues using quadratic formula.
+ float tmp = sqrt(trace * trace - 4 * det);
+ float e1 = (trace + tmp) * 0.5;
+ float e2 = (trace - tmp) * 0.5;
+ float2 singular_values = sqrt(float2(e1, e2));
+ // Logic from original paper: the smaller eigenvalue corresponds to the
+ // largest amount of stretching, so we use it to determine when to
+ // subdivide.
+ float duv_fw = singular_values.y;
+
+ // Suppose Max_Fwidth is 1.
+ // duv_fw is 16. That means UV is changing a lot per pixel. That means we want to shrink the scale of the UV.
+ // Factor is 16.
+ // log_2(factor) is 4.
+ // Divide original by 16.
+ float fw_factor = duv_fw / _Surface_Stable_Fractal_Dithering_Max_Fwidth;
+ float fractal_level = log2(fw_factor);
+ float fractal_level_floor = floor(fractal_level);
+ float fractal_remainder = fractal_level - fractal_level_floor;
+ duv /= pow(2, fractal_level_floor);
+ duv *= _Surface_Stable_Fractal_Dithering_Scale;
+
+ //float subdivisions = 4;
+ //float fractal_remainder_subd = fractal_remainder * subdivisions;
+
+#if 1
+ // Four layers -> coarsest at 0.125, finest at 0.875.
+ uint width, height, depth;
+ _Surface_Stable_Fractal_Dithering_Noise.GetDimensions(width, height, depth);
+ float n_layers = depth;
+ float not_used_lo = 1/(n_layers*2);
+ float not_used_hi = 1 - not_used_lo;
+ float uvw = (not_used_hi - not_used_lo) * (1 - fractal_remainder) + not_used_lo;
+
+ float3 duv_3d = float3(duv, uvw);
+#else
+ float3 duv_3d = float3(duv, 0);
+#endif
+ float noise = _Surface_Stable_Fractal_Dithering_Noise.SampleLevel(bilinear_repeat_s, duv_3d, 0);
+ noise = (noise > 0.5) ? 1 : 0;
+
+ albedo.rgb = noise;
+#if 0
+ float hue = 0;
+ hue += glsl_mod(fractal_level_floor*.1, 1);
+ albedo.rgb *= HSVtoRGB(float3(hue, 1, 1));
+#endif
+ }
+#endif
#if defined(_GIMMICK_GERSTNER_WATER)
#if defined(_EXPLODE)