brot/mandelbrot.glsl

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