#version 100 precision highp float; uniform float u_time; uniform vec2 u_resolution; uniform float u_zoom; uniform vec2 u_center; // Unused if using perturbation? uniform sampler2D u_ref_orbit; // Stores Reference Z (Real=Luminance, Imag=Alpha) // Sliders uniform float u_exponent; // Perturbation usually assumes Z^2. uniform vec2 u_z_start; uniform vec2 u_c_offset; // Complex Math helpers vec2 complex_mul(vec2 a, vec2 b) { return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x); } vec2 complex_sq(vec2 a) { return vec2(a.x*a.x - a.y*a.y, 2.0*a.x*a.y); } void main() { // Current pixel coordinate relative to screen center vec2 p = (gl_FragCoord.xy - u_resolution.xy * 0.5) / u_resolution.y; // Delta C (Difference from Reference Point) vec2 dc = p / u_zoom; // Apply C Offset from sliders (as Delta C) dc += u_c_offset; // Initial Delta Z vec2 dz = vec2(0.0); float iter = 0.0; float max_iter = 1000.0; for (float i = 0.0; i < 1000.0; i++) { // Fetch Reference Z from Texture vec4 ref = texture2D(u_ref_orbit, vec2((i + 0.5) / 1024.0, 0.5)); // Decode Range [0, 1] -> [-4, 4] // Z = Val * 8 - 4 // Use R and G channels (was R and A) vec2 Zn = vec2(ref.r * 8.0 - 4.0, ref.g * 8.0 - 4.0); // dz = 2*Zn*dz + dz^2 + dc vec2 two_Zn_dz = complex_mul(2.0 * Zn, dz); vec2 dz_sq = complex_sq(dz); dz = two_Zn_dz + dz_sq + dc; // Perturbation formula // Check Escape: |Zn + dz|^2 > 4 vec2 current_z = Zn + dz; if (dot(current_z, current_z) > 4.0) { iter = i; break; } } // Coloring float t = iter / max_iter; // Standard Black Interior if (iter >= 999.0) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } else { // Original "Generic" Palette gl_FragColor = vec4(sqrt(t), t*t, sin(t * 3.14), 1.0); } }