#version 100 precision highp float; uniform float u_time; uniform vec2 u_resolution; uniform float u_zoom; uniform vec2 u_center; // Sliders uniform float u_exponent; uniform vec2 u_z_start; uniform vec2 u_c_offset; void main() { // Current pixel coordinate in 0..1 vec2 st = gl_FragCoord.xy / u_resolution.xy; st.x *= u_resolution.x / u_resolution.y; // Aspect ratio correction // Center the coords: vec2 c_uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / u_resolution.y; // Apply Zoom and Pan vec2 c = (c_uv / u_zoom) + u_center; // Apply C Offset from sliders (allows Julia-like effects) c += u_c_offset; // Initial Z vec2 z = u_z_start; float iter = 0.0; float max_iter = 100.0 + log(u_zoom) * 20.0; for (float i = 0.0; i < 500.0; i++) { if (i > max_iter) break; // Generalized Z^n // Convert to Polar: r, theta float r = length(z); float theta = atan(z.y, z.x); // Z^n = r^n * (cos(n*theta) + i*sin(n*theta)) float rn = pow(r, u_exponent); float nt = theta * u_exponent; float x = rn * cos(nt) + c.x; float y = rn * sin(nt) + c.y; if ((x * x + y * y) > 4.0) { iter = i; break; } z.x = x; z.y = y; } // Coloring float t = iter / max_iter; if (iter == 0.0) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } else { // More colorful palette gl_FragColor = vec4( 0.5 + 0.5 * cos(3.0 + t * 10.0 + u_time), 0.5 + 0.5 * cos(3.0 + t * 10.0 + 2.0), 0.5 + 0.5 * cos(3.0 + t * 10.0 + 4.0), 1.0 ); } }