1#version 300 es
 2precision highp float;
 3
 4uniform vec2 u_resolution;
 5uniform vec2 u_center;
 6uniform float u_zoom;
 7uniform vec2 u_c;
 8
 9out vec4 fragColor;
10
11vec3 palette(float t) {
12    // Attempt at a continuous, smooth coloring. For each color channel,
13    // the expression is: 0.5 + 0.5 * cos(2π * (t + offset))
14    return 0.5 + 0.5 * cos(6.28318 * (t + vec3(0.0, 0.1, 0.2)));
15}
16
17void main() {
18    // Map fragment coordinates to complex plane
19    vec2 uv = (gl_FragCoord.xy - u_resolution * 0.5) / min(u_resolution.x, u_resolution.y);
20    vec2 z = uv / u_zoom + u_center;
21
22    // Iterate z = z^2 + c
23    float i;
24    for(i = 0.0; i < 256.0; i++) {
25        if(dot(z, z) > 4.0) break;  // |z|^2 > 4 means escape
26        z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + u_c;
27    }
28
29    if(i >= 256.0) {
30        // Point is in the Julia set (didn't escape)
31        fragColor = vec4(0, 0, 0, 1);
32    } else {
33        // Smooth iteration count to avoid color banding
34        // smooth_i = i - log2(log2(|z|^2)) + 4
35        float smooth_i = i - log2(log2(dot(z, z))) + 4.0;
36        fragColor = vec4(palette(smooth_i * 0.02), 1);
37    }
38}

Mandelbrot Picker

 1#version 300 es
 2precision highp float;
 3
 4uniform vec2 u_resolution;
 5uniform vec2 u_c;  // Current c value to mark
 6
 7out vec4 fragColor;
 8
 9void main() {
10    vec2 uv = (gl_FragCoord.xy - u_resolution * 0.5) / min(u_resolution.x, u_resolution.y);
11
12    // Mandelbrot uses c as the varying parameter, z starts at 0
13    vec2 c = uv * 2.5 - vec2(0.5, 0.0);  // Shift to show main cardioid
14    vec2 z = vec2(0);
15
16    float i;
17    for(i = 0.0; i < 128.0; i++) {
18        if(dot(z, z) > 4.0) break;
19        z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c;
20    }
21
22    vec3 col;
23    if(i >= 128.0) {
24        col = vec3(0.1, 0.1, 0.15);  // Inside the set
25    } else {
26        col = vec3(0.2, 0.3, 0.4) * (i / 128.0);  // Outside
27    }
28
29    // Draw red marker for current c value
30    vec2 cPos = (u_c + vec2(0.5, 0.0)) / 2.5;
31    vec2 pixelC = (cPos + 0.5) * u_resolution;
32    if(length(gl_FragCoord.xy - pixelC) < 4.0) {
33        col = vec3(1, 0.3, 0.3);
34    }
35
36    fragColor = vec4(col, 1);
37}