1precision highp float;
2
3uniform float uTime;
4uniform vec2 uResolution;
5uniform float uStep;
6
7void main() {
8 vec2 uv = gl_FragCoord.xy / uResolution.xy;
9 // move 0, 0 to center of the canvas
10 uv = uv - 0.5;
11
12
13 // Iteration 1 — simple yellow to magenta radial gradient
14 if (uStep < 1.5) {
15 float dist = length(uv);
16 vec3 col = mix(vec3(1.0, 1.0, 0.5), vec3(1.0, 0.5, 1.0), dist);
17 gl_FragColor = vec4(col, 1.0);
18 return;
19 }
20
21 // Iteration 2 — Simple donut with hard edges
22 if (uStep < 2.5) {
23 // Stretch x to match y — otherwise length() draws an oval.
24 uv.x *= uResolution.x / uResolution.y;
25
26 float dist = length(uv);
27 // Adds an inverted circle to push the mix() function past 1.0, creating an extrapolated ring color.
28 float circle = 1.0 - step(dist, 0.3) + step(dist, 0.15);
29 vec3 col = mix(vec3(0.33, 0.33, 0.5), vec3(1.0, 0.66, 0.66), circle);
30 gl_FragColor = vec4(col, 1.0);
31 return;
32 }
33
34 // Iteration 3 — accidental experiement with multiple pulsating circles
35 if (uStep < 3.5) {
36 // Stretch x to match y — otherwise length() draws an oval.
37 uv.x *= uResolution.x / uResolution.y;
38
39 // dist is the distance from the center (0.0) to the current pixel
40 float dist = length(uv);
41
42 // Let's break down 'circle':
43 // 1.0 - step(...) creates a filled circle.
44 // 0.5 + 0.5 * sin(uTime) makes the radius pulse smoothly between 0.0 and 1.0 over time.
45 // + step(dist, 0.15) adds a solid shape back into the middle (a core), reversing the cutout!
46 float circle = 1.0 - step(dist, 0.5 + 0.5 * sin(uTime)) + step(dist, 0.15);
47
48 // 'circle2' pulses much larger (up to 1.5 radius) and has a wider solid core (0.45).
49 // Because sin() goes from -1 to 1, sometimes the radius is negative, making it disappear!
50 float circle2 = 1.0 - step(dist, 1.5 * sin(uTime)) + step(dist, 0.45);
51
52 // We use 'circle' (which is mostly 0.0 or 1.0) to choose between yellow and magenta.
53 vec3 col = mix(vec3(1.0, 1.0, 0.5), vec3(1.0, 0.5, 1.0), circle);
54
55 // The magic happens here: we use 'circle2' to mix between our ALREADY calculated 'col' and a new blue color.
56 // Think of it as painting the blue shape ON TOP of the first image!
57 col = mix(col, vec3(0.5, 0.5, 1.0), circle2);
58
59 gl_FragColor = vec4(col, 1.0);
60 return;
61 }
62
63 // Iteration 4 — Soft Halos and Extrapolated Rings
64 if (uStep < 4.5) {
65 // Stretch x to match y — otherwise length() draws an oval.
66 uv.x *= uResolution.x / uResolution.y;
67 float dist = length(uv);
68
69 // circle1: Uses addition to push the output past 1.0 in the outer regions,
70 // resulting in an extrapolated background color effect.
71 float circle1 = 1.0 - smoothstep(0.3, 0.5, dist) + smoothstep(0.35, 0.4, dist);
72
73 // circle2: Creates a soft glowing ring (donut) by subtracting a smaller
74 // smoothstep circle from a larger smoothstep circle.
75 float circle2 = 1.0 - smoothstep(0.15, 0.3, dist) - smoothstep(0.18, 0.28, dist);
76
77 // Base layer: mix yellow and magenta using circle1
78 vec3 col = mix(vec3(1.0, 1.0, 0.5), vec3(1.0, 0.5, 1.0), circle1);
79
80 // Top layer: paint the soft blue ring over the base layer
81 col = mix(col, vec3(0.5, 0.3, 1.0), circle2);
82
83 gl_FragColor = vec4(col, 1.0);
84 return;
85 }
86}
87