diff options
| author | yum <yum.food.vr@gmail.com> | 2025-02-01 19:15:58 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-02-01 19:15:58 -0800 |
| commit | fb26b02a20ef751cdd1832abc925b5e57bb2234b (patch) | |
| tree | 265f343a4b57e6345468ff5c37902fdd66a3764e /tooner_lighting.cginc | |
| parent | 4bd9c2ba494013f292ddc14d793bc2b362aff365 (diff) | |
Implement surface stable fractal dithering
Diffstat (limited to 'tooner_lighting.cginc')
| -rw-r--r-- | tooner_lighting.cginc | 59 |
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) |
