From a8a03b94e188e89bb98147feab4843e07089a839 Mon Sep 17 00:00:00 2001 From: klemek Date: Sun, 9 Nov 2025 16:41:05 +0100 Subject: [PATCH] fx12: game of life --- DEVELOPMENT.md | 4 +- README.md | 10 ++--- default/inc_fx.glsl | 102 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index d3bf528..71bf374 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -93,8 +93,8 @@ make -f Makefile.dev release-arch - [ ] src 14 : ? - [ ] src 15 : ? - [x] fx 11 : spill - - [ ] fx 12 : colorize range (pretty color ranges) - - [ ] fx 13 : game of life + - [x] fx 12 : game of life + - [ ] fx 13 : colorize range (pretty color ranges) - [ ] fx 14 : ? - [ ] fx 15 : ? - [x] frag 10 : move debug screen here diff --git a/README.md b/README.md index c6798f1..9a98030 100644 --- a/README.md +++ b/README.md @@ -149,13 +149,13 @@ options: | **2** | **5** | Video In 1 + Thru | _Hue_ | _Saturation_ | _Light_ | Dithering | _Pixel Size_ | _Bit Depth_ | _Blur_ | | | **6** | CP437 | _Zoom_ | _Charset_ | _Char. Delta_ | TV | _Lens_ | _Horz. Noise_ | _Dezoom_ | | | **7** | Sentences | _Zoom_ | _Sentence_ | _Vertical repeat_ | Kaleidoscope | _Axes_ | _Rotation_ | _Horz. Scroll_ | -| | **8** | Sentences repeat | _X Shift_ | _Sentence_ | _Vertical repeat_ | CP437 | _Zoom_ | _Charset_ | _Char. Delta_ | -| | **9** | | | | | Lens | _Lens limit_ | _Lens power_ | _Pre Zoom_ | -| **3** | **A** | Video In 2 + Thru | _Hue_ | _Saturation_ | _Light_ | Spill | _Bottom limit_ | _Top Limit_ | _Rotation_ | -| | **B** | | | | | | | | | +| | **8** | Sentences repeat | _X Shift_ | _Sentence_ | _Vertical repeat_ | CP437 | _Zoom_ | _Charset_ | _Char. Delta_ | +| | **9** | Isometric grid | _Zoom_ | _Scroll_ | _Elevation_ | Lens | _Lens limit_ | _Lens power_ | _Pre Zoom_ | +| **3** | **A** | Video In 2 + Thru | _Hue_ | _Saturation_ | _Light_ | Spill | _Bottom limit_ | _Top Limit_ | _Rotation_ | +| | **B** | | | | | Game Of Life | _Pixel Size_ | _Ruleset/Threshold_ | _Feedback_ | | | **C** | | | | | | | | | | | **D** | | | | | | | | | -| | **E** | Calibration | _Circle size_ | _X scroll_ | _Grid size_ | | | | | +| | **E** | | | | | | | | | TODO update diff --git a/default/inc_fx.glsl b/default/inc_fx.glsl index 64c8fec..ac6388c 100644 --- a/default/inc_fx.glsl +++ b/default/inc_fx.glsl @@ -347,21 +347,115 @@ subroutine(fx_stage_sub) vec4 fx_11(vec2 vUV, sampler2D previous, sampler2D feed // TODO FX 12 subroutine(fx_stage_sub) vec4 fx_12(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) { - return fx_2(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); // start vec2 uv0 = vUV.st; float ratio = iResolution.x / iResolution.y; - vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + vec2 uv1 = (uv0 - 0.5) * vec2(ratio, 1); // controls + float pixel_size = magic(f1, b1, seed + 10); + bool pixel_size_trigger = magic_trigger(b1, seed + 10); + f2 = magic_f(f2, b2, seed + 20); + int rule = int(f2.x * 12); + float threshold = f2.y * 0.9 + 0.05; + float fb = magic(f3, b3, seed + 30); + // logic vec3 c0 = texture(previous, uv0).xyz; - vec3 c = c0; - return fx_master(c0, c, seed, m0); + vec2 uv2 = uv1; + float k1 = pow(2, 10 - floor(pixel_size * 6)); + float p = 1 / k1; + uv2 = round(uv2 * k1) / k1; + vec3 c1 = mix( + gauss(previous, (uv2 + vec2(0.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(0.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c2 = mix( + gauss(previous, (uv2 + vec2(1.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(1.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c3 = mix( + gauss(previous, (uv2 + vec2(1.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(1.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c4 = mix( + gauss(previous, (uv2 + vec2(0.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(0.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c5 = mix( + gauss(previous, (uv2 + vec2(-0.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(-0.5, 1.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c6 = mix( + gauss(previous, (uv2 + vec2(-0.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(-0.5, 0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c7 = mix( + gauss(previous, (uv2 + vec2(-0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(-0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c8 = mix( + gauss(previous, (uv2 + vec2(0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + vec3 c9 = mix( + gauss(previous, (uv2 + vec2(-0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + gauss(feedback, (uv2 + vec2(-0.5, -0.5) * p) * vec2(1 / ratio, 1) + .5, 1, 0.1).xyz, + fb + ); + bool alive = mean(c1) >= threshold; + int n = 0 + + (mean(c2) >= threshold ? 1 : 0) + + (mean(c3) >= threshold ? 1 : 0) + + (mean(c4) >= threshold ? 1 : 0) + + (mean(c5) >= threshold ? 1 : 0) + + (mean(c6) >= threshold ? 1 : 0) + + (mean(c7) >= threshold ? 1 : 0) + + (mean(c8) >= threshold ? 1 : 0) + + (mean(c9) >= threshold ? 1 : 0) + ; + + if (rule == 0) { // B3/S23 (life) + alive = alive && n == 2 || n == 3; + } else if (rule == 1) { // B1357/S1357 (replicator) + alive = n == 2 || n == 3 || n == 5 || n == 7; + } else if (rule == 2) { // B2/S (seeds) + alive = !alive && n == 2; + } else if (rule == 3) { // B25/S4 + alive = !alive && (n == 2 || n == 5) || alive && n == 4; + } else if (rule == 4) { // B3/S012345678 (life without death) + alive = alive || n == 3; + } else if (rule == 5) { // B34/S34 (34 life) + alive = n == 3 || n ==4; + } else if (rule == 6) { // B35678/S5678 (Diamoeba) + alive = n >= 5 || !alive && n == 3; + } else if (rule == 7) { // B36/S125 (2x2) + alive = !alive && (n == 3 || n == 6) || alive && (n == 1 || n == 2 || n == 5); + } else if (rule == 8) { // B36/S23 (HighLife) + alive = !alive && n == 6 || alive && n == 2 || n == 3; + } else if (rule == 9) { // B3678/S34678 (Day & Night) + alive = n == 3 || n >= 6 || alive && n == 4; + } else if (rule == 10) { // B368/S245 (Morley) + alive = !alive && (n == 3 || n == 6 || n == 8) || alive && (n == 2 || n == 4 || n == 5); + } else if (rule == 11) { // B4678/S35678 (Anneal) + alive = n >= 6 || !alive && n == 4 || alive && (n == 3 || n == 5); + } + + vec3 cout = vec3(alive ? 1 : 0); + + return fx_master(c0, cout, seed, m0); } // TODO FX 13