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);
}