summaryrefslogtreecommitdiff
path: root/mandelbrot.glsl
diff options
context:
space:
mode:
authorcitrons <citrons@mondecitronne.com>2025-08-01 21:08:00 -0500
committercitrons <citrons@mondecitronne.com>2025-08-01 21:08:00 -0500
commit97e0ca7f099fedfd7ee41c2f0ad4f5a443b70579 (patch)
tree45b5745c030c42999de198e3bc9300c237af4990 /mandelbrot.glsl
initial commitHEADmaster
Diffstat (limited to 'mandelbrot.glsl')
-rw-r--r--mandelbrot.glsl67
1 files changed, 67 insertions, 0 deletions
diff --git a/mandelbrot.glsl b/mandelbrot.glsl
new file mode 100644
index 0000000..42279bd
--- /dev/null
+++ b/mandelbrot.glsl
@@ -0,0 +1,67 @@
+uniform vec2 orbit[4096];
+uniform vec2 offset = vec2(0, 0);
+uniform float zoom = 300;
+uniform int iterations = 256;
+uniform int antialias = 0;
+
+vec2 mul(vec2 a, vec2 b) {
+ return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
+}
+
+vec2 sq(vec2 a) {
+ return vec2(a.x*a.x - a.y*a.y, 2 * a.x * a.y);
+}
+
+float abssq(vec2 a) {
+ return a.x*a.x + a.y*a.y;
+}
+
+int brot(vec2 c) {
+ vec2 dz = vec2(0, 0);
+ int ri = 0;
+ for (int i = 0; i < iterations; i++) {
+ dz = mul(mul(vec2(2, 0), dz), orbit[ri]) + sq(dz) + c;
+ ri++;
+ vec2 z = orbit[ri] + dz;
+ if (abssq(z) > 4) return i;
+ if (abssq(z) < abssq(dz) || abssq(orbit[ri]) > 4) {
+ dz = z;
+ ri = 0;
+ }
+ }
+ return -1;
+}
+
+vec3 hsv2rgb(vec3 c)
+{
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+vec3 color_at(vec2 screen_pos) {
+ vec2 pos = offset + screen_pos / zoom;
+ int i = brot(pos);
+ if (i >= 0) {
+ float it = i;
+ float ri = it / iterations;
+ float h = mod(0.4 + log(1 + it) / 12.0, 1.0);
+ float s = 0.6 + sin(it / 30) * 0.2;
+ float v = 0.1 + pow(ri, 1.01) * 2.0;
+ return hsv2rgb(vec3(h, s, v));
+ } else {
+ return vec3(0, 0, 0);
+ }
+}
+
+vec4 effect(vec4 color, Image t, vec2 img_pos, vec2 screen_pos) {
+ vec3 result = vec3(0, 0, 0);
+ for (float x = 0; x < antialias; x++) {
+ for (float y = 0; y < antialias; y++) {
+ vec2 pos = screen_pos - 0.5 + vec2(x, y) / antialias;
+ result += color_at(pos) / (antialias * antialias);
+ }
+ }
+ return vec4(result, 1);
+}
+