// Minimal Mandelbrot with slow timed zoom to a preset boundary location. // --- Presets --- const vec2 ZOOM_TARGET = vec2(-0.743643887, 0.131825904); // Seahorse Valley const float ZOOM_DURATION = 60.0; // seconds to complete zoom (iTime=0..duration) const float ZOOM_FACTOR_END = 1e-3; // final scale relative to full-view (smaller => deeper) const int MAX_ITER_START = 200; // iterations at start (full view) const int MAX_ITER_END = 1000; // iterations at end (deep zoom) // HSV to RGB, h in [0,1], s,v in [0,1] vec3 hsv2rgb(vec3 c) { vec3 p = abs(fract(c.x + vec3(0.0, 1.0/3.0, 2.0/3.0)) * 6.0 - 3.0); return c.z * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), c.y); } // ROYGBIV palette: hue sweep at full saturation/value vec3 rainbow(float t) { return vec3(fract(t), 1.0, 1.0); // HSV } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // Normalized pixel coordinates (0..1) vec2 uv = fragCoord / iResolution.xy; // --- View mapping (full-set rectangle) --- // Initial full view bounds (classic): x∈[-2.5, 1.0], y∈[-1.0, 1.0] const vec2 INIT_MIN = vec2(-2.5, -1.0); const vec2 INIT_MAX = vec2( 1.0, 1.0); const vec2 INIT_CENTER = 0.5 * (INIT_MIN + INIT_MAX); const vec2 INIT_HALF = 0.5 * (INIT_MAX - INIT_MIN); // (1.75, 1.0) // --- Time-based zoom/pan --- float t = clamp(iTime / ZOOM_DURATION, 0.0, 1.0); // Geometric interpolation for scale (smooth visual zoom) float logEnd = log(ZOOM_FACTOR_END); float scale = exp(mix(0.0, logEnd, t)); // 1.0 -> ZOOM_FACTOR_END // Linear interpolation of center from initial to target vec2 center = mix(INIT_CENTER, ZOOM_TARGET, t); // Current bounds vec2 halfSpan = INIT_HALF * scale; vec2 minP = center - halfSpan; vec2 maxP = center + halfSpan; // Map uv to complex plane coordinate c vec2 c = mix(minP, maxP, uv); // Iteration budget interpolation int MAX_ITER = int(mix(float(MAX_ITER_START), float(MAX_ITER_END), t) + 0.5); // --- Mandelbrot iteration: z_{n+1} = z_n^2 + c --- vec2 z = vec2(0.0); int i; for (i = 0; i < MAX_ITER; ++i) { // z = (zx + i zy)^2 + c = (zx^2 - zy^2) + i(2 zx zy) + c vec2 z2 = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c; z = z2; if (dot(z, z) > 4.0) break; // escape radius^2 } // Color: inside = black, outside = rainbow by normalized iteration vec3 col = (i == MAX_ITER) ? vec3(0.0) : hsv2rgb(rainbow(float(i) / float(MAX_ITER))); fragColor = vec4(col, 1.0); }