summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-02-01 19:26:29 -0800
committeryum <yum.food.vr@gmail.com>2025-02-01 19:26:29 -0800
commitff997cfb850ec42a977381a2becf0ccedb2035d9 (patch)
tree183c4a1d25bea43b985ba8308c65fa3c529f14db
parentfb26b02a20ef751cdd1832abc925b5e57bb2234b (diff)
Begin work on ssfd in lens shader
-rw-r--r--Editor/tooner.cs14
-rw-r--r--feature_macros.cginc2
-rw-r--r--globals.cginc6
-rw-r--r--tooner.shader3
-rw-r--r--tooner_lighting.cginc116
5 files changed, 83 insertions, 58 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index c7d89d4..01e30ed 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -3182,6 +3182,7 @@ public class ToonerGUI : ShaderGUI {
enum Lens00Mode {
Bayer,
InterleavedGradientNoise,
+ SurfaceStableFractalDithering,
}
void DoLens00() {
@@ -3232,6 +3233,19 @@ public class ToonerGUI : ShaderGUI {
bc.floatValue = (float) mode;
SetKeyword("_GIMMICK_LENS_00_BAYER", mode == Lens00Mode.Bayer);
SetKeyword("_GIMMICK_LENS_00_INTERLEAVED_GRADIENT_NOISE", mode == Lens00Mode.InterleavedGradientNoise);
+ SetKeyword("_GIMMICK_LENS_00_SSFD", mode == Lens00Mode.SurfaceStableFractalDithering);
+
+ if (mode == Lens00Mode.SurfaceStableFractalDithering) {
+ EditorGUI.indentLevel += 1;
+ bc = FindProperty("_Gimmick_Lens_00_SSFD_Scale");
+ FloatProperty(bc, "Scale");
+ bc = FindProperty("_Gimmick_Lens_00_SSFD_Max_Fwidth");
+ FloatProperty(bc, "Max fwidth");
+ bc = FindProperty("_Gimmick_Lens_00_SSFD_Noise");
+ TexturePropertySingleLine(MakeLabel(bc, "Noise"), bc);
+ EditorGUI.indentLevel -= 1;
+ }
+
EditorGUI.indentLevel -= 1;
}
diff --git a/feature_macros.cginc b/feature_macros.cginc
index 3f5d177..d870fb9 100644
--- a/feature_macros.cginc
+++ b/feature_macros.cginc
@@ -291,7 +291,9 @@
#pragma shader_feature_local _ _GIMMICK_LENS_00_GRABPASS
#pragma shader_feature_local _ _GIMMICK_LENS_00_BAYER
#pragma shader_feature_local _ _GIMMICK_LENS_00_INTERLEAVED_GRADIENT_NOISE
+#pragma shader_feature_local _ _GIMMICK_LENS_00_SSFD
#pragma shader_feature_local _ _SURFACE_STABLE_FRACTAL_DITHERING
+
#endif // __FEATURE_MACROS_INC
diff --git a/globals.cginc b/globals.cginc
index 88abb0f..578fb8e 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -1137,6 +1137,11 @@ float _Gimmick_Lens_00_Subdivisions;
#if defined(_GIMMICK_LENS_00_FRAME_COUNTER)
float _Gimmick_Lens_00_Frame_Counter_Speed;
#endif
+#if defined(_GIMMICK_LENS_00_SSFD)
+float _Gimmick_Lens_00_SSFD_Scale;
+float _Gimmick_Lens_00_SSFD_Max_Fwidth;
+texture3D _Gimmick_Lens_00_SSFD_Noise;
+#endif
#endif
#if defined(_SURFACE_STABLE_FRACTAL_DITHERING)
@@ -1145,5 +1150,6 @@ float _Surface_Stable_Fractal_Dithering_Scale;
float _Surface_Stable_Fractal_Dithering_Max_Fwidth;
#endif
+
#endif
diff --git a/tooner.shader b/tooner.shader
index 5632ce2..15386c7 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -1174,6 +1174,9 @@ Shader "yum_food/tooner"
_Gimmick_Lens_00_Subdivisions("Quantization subdivisions", Float) = 1
_Gimmick_Lens_00_Mode("Mode", Float) = 0 // 0 = Bayer, 1 = InterleavedGradientNoise
_Gimmick_Lens_00_Scale("Scale", Float) = 1
+ _Gimmick_Lens_00_SSFD_Scale("Scale", Float) = 1
+ _Gimmick_Lens_00_SSFD_Max_Fwidth("Max fwidth", Float) = 0.001
+ _Gimmick_Lens_00_SSFD_Noise("Noise", 3D) = "white" {}
_Surface_Stable_Fractal_Dithering_Enable_Static("Enable stable fractal dithering", Float) = 0
_Surface_Stable_Fractal_Dithering_Noise("Noise", 3D) = "white" {}
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index ab885e6..09043f5 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -985,6 +985,59 @@ float4 map_color_epilepsy(float4 color) {
#define FILTER_COLOR(color) color
#endif
+float ssfd(float2 uv, float scale, float max_fwidth, texture3D noise)
+{
+ float2 duv = uv;
+
+ //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 / 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 *= scale;
+
+#if 1
+ // Four layers -> coarsest at 0.125, finest at 0.875.
+ uint width, height, depth;
+ 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 dither = noise.SampleLevel(bilinear_repeat_s, duv_3d, 0);
+ dither = (dither > 0.5) ? 1 : 0;
+
+ return dither;
+}
+
float4 effect(inout v2f i, out float depth)
{
ToonerData tdata;
@@ -1070,63 +1123,7 @@ float4 effect(inout v2f i, out float depth)
#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
- }
+ albedo.rgb = ssfd(i.uv0, _Surface_Stable_Fractal_Dithering_Scale, _Surface_Stable_Fractal_Dithering_Max_Fwidth, _Surface_Stable_Fractal_Dithering_Noise);
#endif
#if defined(_GIMMICK_GERSTNER_WATER)
@@ -2353,14 +2350,17 @@ float4 effect(inout v2f i, out float depth)
float mask = BayerM8x8[bayer_idx.y * 8 + bayer_idx.x];
#elif defined(_GIMMICK_LENS_00_INTERLEAVED_GRADIENT_NOISE)
float mask = ign(glasses_uv_round);
+#elif defined(_GIMMICK_LENS_00_SSFD)
+ float mask = ssfd(glasses_uv_round, _Gimmick_Lens_00_SSFD_Scale, _Gimmick_Lens_00_SSFD_Max_Fwidth, _Gimmick_Lens_00_SSFD_Noise);
#endif
- mask = frac(mask + frame * PHI * _Gimmick_Lens_00_Frame_Counter_Speed);
+ //mask = frac(mask + frame * PHI * _Gimmick_Lens_00_Frame_Counter_Speed);
float2 grab_uv = i.grabPos.xy / i.grabPos.w;
//grab_uv = floor(grab_uv * _ScreenParams.xy * _Gimmick_Lens_00_Scale) / (_ScreenParams.xy * _Gimmick_Lens_00_Scale);
float3 grab_color = _Tooner_Grabpass.SampleLevel(linear_clamp_s, grab_uv, 0).rgb;
grab_color = round(grab_color * _Gimmick_Lens_00_Subdivisions) / _Gimmick_Lens_00_Subdivisions;
lit.rgb = (grab_color > mask);
+ lit.rgb = mask * .1;
}
#endif