diff --git a/main.cpp b/main.cpp index 3b80d60..f7e8c7a 100644 --- a/main.cpp +++ b/main.cpp @@ -435,6 +435,7 @@ void init_shaders() { add_shader("TUNNEL", "shaders/tunnel.frag", 0.2f, 0.8f, 0.2f); add_shader("FRACTAL", "shaders/fractal.frag", 0.2f, 0.2f, 0.8f); add_shader("MANDEL", "shaders/mandelbrot.frag", 0.5f, 0.0f, 0.5f); + add_shader("DBL PEND", "shaders/pendulum.frag", 0.7f, 0.7f, 0.1f); } int main() { diff --git a/main.o b/main.o index 1ff4c84..8f42373 100644 Binary files a/main.o and b/main.o differ diff --git a/shader-demo b/shader-demo index f9f8b8f..1d58304 100755 Binary files a/shader-demo and b/shader-demo differ diff --git a/shaders/pendulum.frag b/shaders/pendulum.frag new file mode 100644 index 0000000..3fe670b --- /dev/null +++ b/shaders/pendulum.frag @@ -0,0 +1,74 @@ +#version 100 +precision mediump float; + +uniform float u_time; +uniform vec2 u_resolution; + +// Constants +#define PI 3.14159265359 +#define G 9.81 +#define L1 1.0 +#define L2 1.0 +#define M1 1.0 +#define M2 1.0 +#define DT 0.05 +#define ITERATIONS 100 + +void main() { + // Map pixel to initial angles (-PI to PI) + vec2 uv = (gl_FragCoord.xy / u_resolution.xy) * 2.0 - 1.0; + float t1 = uv.x * PI; + float t2 = uv.y * PI; + + // Initial velocities + float v1 = 0.0; + float v2 = 0.0; + + // Previous angles for Verlet or just simple Euler/RK4 + // Using semi-implicit Euler for stability/simplicity in shader + + float flip_time = -1.0; + + // Animate gravity to make it breathe? Or length? + float g = G + sin(u_time * 0.5) * 2.0; + + for (int i = 0; i < ITERATIONS; i++) { + float num1 = -g * (2.0 * M1 + M2) * sin(t1); + float num2 = -M2 * g * sin(t1 - 2.0 * t2); + float num3 = -2.0 * sin(t1 - t2) * M2; + float num4 = v2 * v2 * L2 + v1 * v1 * L1 * cos(t1 - t2); + float den = L1 * (2.0 * M1 + M2 - M2 * cos(2.0 * t1 - 2.0 * t2)); + float a1 = (num1 + num2 + num3 * num4) / den; + + num1 = 2.0 * sin(t1 - t2); + num2 = (v1 * v1 * L1 * (M1 + M2)); + num3 = g * (M1 + M2) * cos(t1); + num4 = v2 * v2 * L2 * M2 * cos(t1 - t2); + den = L2 * (2.0 * M1 + M2 - M2 * cos(2.0 * t1 - 2.0 * t2)); + float a2 = (num1 * (num2 + num3 + num4)) / den; + + v1 += a1 * DT; + v2 += a2 * DT; + t1 += v1 * DT; + t2 += v2 * DT; + + // Dampening? No, chaotic system usually conservative (or we want to see chaos) + + // Check for flip (crossing PI) + if (abs(t1) > PI || abs(t2) > PI) { + flip_time = float(i) / float(ITERATIONS); + break; + } + } + + vec3 col = vec3(0.0); + if (flip_time > 0.0) { + // Did flip + col = vec3(0.2 + 0.8 * flip_time, 0.5 * flip_time, 1.0 - flip_time); + } else { + // Did not flip (stableish) + col = vec3(0.1, 0.1, 0.2); + } + + gl_FragColor = vec4(col, 1.0); +}