Skip to main content

rae/
shader.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum ShaderUniformKind {
3    Float1,
4    Float2,
5}
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct ShaderUniform {
9    pub name: &'static str,
10    pub kind: ShaderUniformKind,
11}
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub struct ShaderSource {
15    pub name: &'static str,
16    pub vertex: &'static str,
17    pub fragment: &'static str,
18    pub uniforms: &'static [ShaderUniform],
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum ShaderFamily {
23    Background,
24    Panel,
25    Prompt,
26    Interaction,
27    Code,
28    Flow,
29    Data,
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub struct ShaderDescriptor {
34    pub source: ShaderSource,
35    pub family: ShaderFamily,
36    pub description: &'static str,
37    pub complexity: u8,
38    pub animated: bool,
39}
40
41pub const COMMON_UNIFORMS: &[ShaderUniform] = &[
42    ShaderUniform {
43        name: "u_time",
44        kind: ShaderUniformKind::Float1,
45    },
46    ShaderUniform {
47        name: "u_resolution",
48        kind: ShaderUniformKind::Float2,
49    },
50    ShaderUniform {
51        name: "u_intensity",
52        kind: ShaderUniformKind::Float1,
53    },
54];
55
56pub const VERTEX: &str = r#"#version 100
57attribute vec3 position;
58attribute vec2 texcoord;
59attribute vec4 color0;
60varying lowp vec2 uv;
61varying lowp vec4 color;
62uniform mat4 Model;
63uniform mat4 Projection;
64void main() {
65    gl_Position = Projection * Model * vec4(position, 1.0);
66    uv = texcoord;
67    color = color0;
68}
69"#;
70
71pub const BACKGROUND_FRAGMENT: &str = r#"#version 100
72precision mediump float;
73varying lowp vec2 uv;
74varying lowp vec4 color;
75uniform sampler2D Texture;
76uniform float u_time;
77uniform vec2 u_resolution;
78uniform float u_intensity;
79
80float hash(vec2 p) {
81    p = fract(p * vec2(123.34, 456.21));
82    p += dot(p, p + 45.32);
83    return fract(p.x * p.y);
84}
85
86float noise(vec2 p) {
87    vec2 i = floor(p);
88    vec2 f = fract(p);
89    vec2 u = f * f * (3.0 - 2.0 * f);
90    return mix(
91        mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x),
92        mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),
93        u.y
94    );
95}
96
97float fbm(vec2 p) {
98    float value = 0.0;
99    float amplitude = 0.5;
100    mat2 warp = mat2(1.62, 1.18, -1.18, 1.62);
101    for (int i = 0; i < 6; i++) {
102        value += amplitude * noise(p);
103        p = warp * p + vec2(0.17, 0.31);
104        amplitude *= 0.53;
105    }
106    return value;
107}
108
109vec2 curl(vec2 p) {
110    float e = 0.035;
111    float n1 = fbm(p + vec2(0.0, e));
112    float n2 = fbm(p - vec2(0.0, e));
113    float n3 = fbm(p + vec2(e, 0.0));
114    float n4 = fbm(p - vec2(e, 0.0));
115    return vec2(n1 - n2, n4 - n3) / (2.0 * e);
116}
117
118float rings(vec2 p, float t) {
119    float d = length(p);
120    float wave = sin(34.0 * d - t * 3.5 + fbm(p * 4.0) * 2.5);
121    return smoothstep(0.84, 1.0, wave) * smoothstep(1.2, 0.12, d);
122}
123
124void main() {
125    vec2 p = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / max(u_resolution.x, u_resolution.y);
126    float t = u_time * 0.18;
127    vec2 flow = curl(p * 2.0 + t);
128    vec2 q = p + flow * 0.22 + vec2(sin(t * 1.7), cos(t * 1.3)) * 0.08;
129    float nebula = fbm(q * 2.6 + t * 0.7);
130    float veins = fbm(q * 9.0 - flow * 1.4);
131    float halo = rings(p - vec2(0.38, -0.2), u_time);
132    float vignette = smoothstep(1.36, 0.18, length(p));
133    vec3 ink = vec3(0.010, 0.014, 0.034);
134    vec3 blue = vec3(0.09, 0.32, 0.78);
135    vec3 cyan = vec3(0.12, 0.82, 1.0);
136    vec3 violet = vec3(0.56, 0.14, 0.96);
137    vec3 gold = vec3(1.0, 0.55, 0.17);
138    vec3 col = ink;
139    col += blue * nebula * 0.34;
140    col += cyan * smoothstep(0.52, 0.96, veins) * 0.24;
141    col += violet * pow(max(nebula, 0.0), 2.2) * 0.32;
142    col += gold * halo * 0.36;
143    col *= 0.55 + vignette * 0.75;
144    col += vec3(hash(gl_FragCoord.xy + u_time) * 0.025);
145    gl_FragColor = vec4(col * (0.72 + u_intensity * 0.42), 1.0) * color;
146}
147"#;
148
149pub const PANE_FRAGMENT: &str = r#"#version 100
150precision mediump float;
151varying lowp vec2 uv;
152varying lowp vec4 color;
153uniform sampler2D Texture;
154uniform float u_time;
155uniform vec2 u_resolution;
156uniform float u_intensity;
157
158float hex(vec2 p) {
159    p.x *= 0.57735 * 2.0;
160    p.y += mod(floor(p.x), 2.0) * 0.5;
161    p = abs(fract(p) - 0.5);
162    return abs(max(p.x * 1.5 + p.y, p.y * 2.0) - 1.0);
163}
164
165float hash(vec2 p) {
166    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
167}
168
169float grid(vec2 p, float t) {
170    vec2 id = floor(p);
171    float h = hash(id);
172    float cell = smoothstep(0.035, 0.0, hex(p));
173    float sweep = smoothstep(0.98, 0.4, abs(fract(h + t * 0.08) - 0.5));
174    return cell * sweep;
175}
176
177void main() {
178    vec2 p = uv;
179    vec2 centered = p - 0.5;
180    float edge = smoothstep(0.5, 0.47, max(abs(centered.x), abs(centered.y)));
181    float border = 1.0 - smoothstep(0.0, 0.018, min(min(p.x, p.y), min(1.0 - p.x, 1.0 - p.y)));
182    float lattice = grid((p + vec2(u_time * 0.018, -u_time * 0.012)) * 18.0, u_time);
183    float scan = sin((p.y + u_time * 0.11) * 420.0) * 0.5 + 0.5;
184    vec3 base = vec3(0.018, 0.032, 0.070);
185    vec3 glow = vec3(0.10, 0.54, 0.95) * lattice * 0.22;
186    vec3 rim = vec3(0.36, 0.76, 1.0) * border * (0.32 + 0.22 * sin(u_time * 1.9));
187    vec3 col = base + glow + rim + vec3(scan * 0.018 * u_intensity);
188    gl_FragColor = vec4(col, 0.82 * edge) * color;
189}
190"#;
191
192pub const PROMPT_FRAGMENT: &str = r#"#version 100
193precision mediump float;
194varying lowp vec2 uv;
195varying lowp vec4 color;
196uniform sampler2D Texture;
197uniform float u_time;
198uniform vec2 u_resolution;
199uniform float u_intensity;
200
201float line(vec2 p, float offset, float width) {
202    return smoothstep(width, 0.0, abs(p.y - offset));
203}
204
205void main() {
206    vec2 p = uv;
207    float t = u_time;
208    float beam = line(p, 0.5 + sin(t * 1.4 + p.x * 7.0) * 0.08, 0.018);
209    float beam2 = line(p, 0.34 + cos(t * 1.1 + p.x * 9.0) * 0.05, 0.012);
210    float edge = 1.0 - smoothstep(0.0, 0.026, min(min(p.x, p.y), min(1.0 - p.x, 1.0 - p.y)));
211    float caret = smoothstep(0.015, 0.0, abs(fract(p.x * 34.0 - t * 0.9) - 0.5));
212    vec3 base = vec3(0.020, 0.030, 0.070);
213    vec3 cyan = vec3(0.16, 0.86, 1.0);
214    vec3 violet = vec3(0.75, 0.24, 1.0);
215    vec3 col = base + cyan * beam * 0.28 + violet * beam2 * 0.18;
216    col += cyan * edge * 0.32;
217    col += vec3(0.35, 0.85, 1.0) * caret * 0.035 * u_intensity;
218    gl_FragColor = vec4(col, 0.90) * color;
219}
220"#;
221
222pub const AURORA_FRAGMENT: &str = r#"#version 100
223precision mediump float;
224varying lowp vec2 uv;
225varying lowp vec4 color;
226uniform sampler2D Texture;
227uniform float u_time;
228uniform vec2 u_resolution;
229uniform float u_intensity;
230
231float hash(vec2 p) {
232    return fract(sin(dot(p, vec2(41.0, 289.0))) * 45758.5453);
233}
234
235float noise(vec2 p) {
236    vec2 i = floor(p);
237    vec2 f = fract(p);
238    f = f * f * (3.0 - 2.0 * f);
239    float a = hash(i);
240    float b = hash(i + vec2(1.0, 0.0));
241    float c = hash(i + vec2(0.0, 1.0));
242    float d = hash(i + vec2(1.0, 1.0));
243    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
244}
245
246float ridge(float v) {
247    return 1.0 - abs(v * 2.0 - 1.0);
248}
249
250void main() {
251    vec2 p = (gl_FragCoord.xy / u_resolution.xy);
252    float t = u_time * 0.12;
253    float curtain = 0.0;
254    for (int i = 0; i < 5; i++) {
255        float fi = float(i);
256        vec2 q = vec2(p.x * (2.0 + fi * 0.65) + t * (0.7 + fi * 0.13), p.y * (7.0 + fi));
257        float band = ridge(noise(q + vec2(fi * 8.7, -t * 2.0)));
258        curtain += smoothstep(0.44, 1.0, band) * (0.18 + fi * 0.035);
259    }
260    float horizon = smoothstep(0.98, 0.16, p.y);
261    float stars = step(0.996, hash(gl_FragCoord.xy + floor(u_time * 8.0))) * smoothstep(0.8, 0.05, p.y);
262    vec3 deep = vec3(0.005, 0.015, 0.042);
263    vec3 green = vec3(0.18, 1.00, 0.70);
264    vec3 blue = vec3(0.10, 0.42, 1.00);
265    vec3 magenta = vec3(0.85, 0.16, 1.00);
266    vec3 col = deep + mix(blue, green, p.y) * curtain * horizon * u_intensity;
267    col += magenta * pow(curtain, 3.0) * 0.18;
268    col += vec3(stars) * 0.75;
269    gl_FragColor = vec4(col, 1.0) * color;
270}
271"#;
272
273pub const KNOT_FIELD_FRAGMENT: &str = r#"#version 100
274precision mediump float;
275varying lowp vec2 uv;
276varying lowp vec4 color;
277uniform sampler2D Texture;
278uniform float u_time;
279uniform vec2 u_resolution;
280uniform float u_intensity;
281
282float sdTorus(vec3 p, vec2 t) {
283    vec2 q = vec2(length(p.xz) - t.x, p.y);
284    return length(q) - t.y;
285}
286
287mat2 rot(float a) {
288    float s = sin(a);
289    float c = cos(a);
290    return mat2(c, -s, s, c);
291}
292
293float field(vec3 p) {
294    p.xz *= rot(u_time * 0.23);
295    p.xy *= rot(sin(u_time * 0.17) * 0.6);
296    float d = sdTorus(p, vec2(0.62, 0.055));
297    vec3 q = p;
298    q.xy *= rot(2.094);
299    float d2 = sdTorus(q, vec2(0.62, 0.055));
300    q = p;
301    q.xy *= rot(-2.094);
302    float d3 = sdTorus(q, vec2(0.62, 0.055));
303    return min(d, min(d2, d3));
304}
305
306void main() {
307    vec2 p = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / max(u_resolution.x, u_resolution.y);
308    vec3 ro = vec3(0.0, 0.0, 2.1);
309    vec3 rd = normalize(vec3(p, -1.65));
310    float t = 0.0;
311    float glow = 0.0;
312    float hit = 0.0;
313    for (int i = 0; i < 58; i++) {
314        vec3 pos = ro + rd * t;
315        float d = field(pos);
316        glow += 0.006 / (0.018 + abs(d));
317        if (d < 0.003) {
318            hit = 1.0;
319            break;
320        }
321        t += max(d * 0.58, 0.012);
322        if (t > 4.0) {
323            break;
324        }
325    }
326    vec3 base = vec3(0.005, 0.010, 0.025);
327    vec3 cyan = vec3(0.10, 0.78, 1.00);
328    vec3 violet = vec3(0.65, 0.14, 1.00);
329    vec3 gold = vec3(1.00, 0.48, 0.10);
330    vec3 col = base + cyan * glow * 0.24 + violet * pow(glow, 1.4) * 0.08 + gold * hit * 0.35;
331    col *= 0.74 + u_intensity * 0.34;
332    gl_FragColor = vec4(col, 0.96) * color;
333}
334"#;
335
336pub const TERMINAL_RAIN_FRAGMENT: &str = r#"#version 100
337precision mediump float;
338varying lowp vec2 uv;
339varying lowp vec4 color;
340uniform sampler2D Texture;
341uniform float u_time;
342uniform vec2 u_resolution;
343uniform float u_intensity;
344
345float hash(vec2 p) {
346    return fract(sin(dot(p, vec2(13.13, 91.77))) * 43758.5453);
347}
348
349void main() {
350    vec2 cell = floor(gl_FragCoord.xy / vec2(10.0, 18.0));
351    float column = hash(vec2(cell.x, 2.0));
352    float speed = mix(0.8, 3.4, column);
353    float trail = fract(cell.y * 0.071 - u_time * speed + column * 9.0);
354    float glyph = hash(cell + floor(u_time * speed));
355    float on = smoothstep(0.92, 1.0, trail) * step(0.22, glyph);
356    float tail = smoothstep(0.45, 0.0, trail) * step(0.65, column);
357    vec3 base = vec3(0.0, 0.012, 0.025);
358    vec3 green = vec3(0.18, 1.0, 0.56);
359    vec3 blue = vec3(0.1, 0.68, 1.0);
360    vec3 col = base + green * on * u_intensity + blue * tail * 0.18;
361    col += vec3(hash(gl_FragCoord.xy) * 0.018);
362    gl_FragColor = vec4(col, 0.72) * color;
363}
364"#;
365
366pub const FLOW_BEAMS_FRAGMENT: &str = r#"#version 100
367precision mediump float;
368varying lowp vec2 uv;
369varying lowp vec4 color;
370uniform sampler2D Texture;
371uniform float u_time;
372uniform vec2 u_resolution;
373uniform float u_intensity;
374
375float capsule(vec2 p, vec2 a, vec2 b, float r) {
376    vec2 pa = p - a;
377    vec2 ba = b - a;
378    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
379    return length(pa - ba * h) - r;
380}
381
382void main() {
383    vec2 p = uv;
384    float glow = 0.0;
385    for (int i = 0; i < 7; i++) {
386        float fi = float(i);
387        vec2 a = vec2(0.08, 0.16 + fi * 0.115);
388        vec2 b = vec2(0.92, 0.22 + sin(u_time * 0.7 + fi) * 0.24 + fi * 0.08);
389        float d = capsule(p, a, b, 0.006 + 0.002 * sin(u_time + fi));
390        float pulse = smoothstep(0.05, 0.0, abs(fract(u_time * 0.22 + fi * 0.17) - p.x));
391        glow += smoothstep(0.028, 0.0, d) * (0.28 + pulse * 0.72);
392    }
393    float node = 0.0;
394    for (int j = 0; j < 5; j++) {
395        float fj = float(j);
396        vec2 c = vec2(0.16 + fj * 0.18, 0.5 + sin(u_time * 0.5 + fj * 1.7) * 0.28);
397        node += smoothstep(0.06, 0.0, length(p - c));
398    }
399    vec3 base = vec3(0.014, 0.020, 0.050);
400    vec3 cyan = vec3(0.08, 0.80, 1.00);
401    vec3 violet = vec3(0.62, 0.16, 1.00);
402    vec3 col = base + cyan * glow * 0.45 * u_intensity + violet * node * 0.20;
403    gl_FragColor = vec4(col, 0.86) * color;
404}
405"#;
406
407pub const RIPPLE_FRAGMENT: &str = r#"#version 100
408precision mediump float;
409varying lowp vec2 uv;
410varying lowp vec4 color;
411uniform sampler2D Texture;
412uniform float u_time;
413uniform vec2 u_resolution;
414uniform float u_intensity;
415
416float ring(vec2 p, vec2 c, float radius, float width) {
417    float d = length(p - c);
418    return smoothstep(width, 0.0, abs(d - radius));
419}
420
421float disk(vec2 p, vec2 c, float radius) {
422    return smoothstep(radius, 0.0, length(p - c));
423}
424
425void main() {
426    vec2 p = uv;
427    float t = fract(u_time * 0.62);
428    vec2 c1 = vec2(0.30 + sin(u_time * 0.37) * 0.09, 0.50 + cos(u_time * 0.41) * 0.08);
429    vec2 c2 = vec2(0.70 + cos(u_time * 0.29) * 0.11, 0.46 + sin(u_time * 0.53) * 0.10);
430    float r1 = ring(p, c1, t * 0.72, 0.026) * (1.0 - t);
431    float r2 = ring(p, c2, fract(t + 0.38) * 0.66, 0.020) * (1.0 - fract(t + 0.38));
432    float ink = disk(p, c1, 0.12 + t * 0.5) * 0.055 + disk(p, c2, 0.10 + fract(t + 0.38) * 0.45) * 0.045;
433    float border = 1.0 - smoothstep(0.0, 0.018, min(min(p.x, p.y), min(1.0 - p.x, 1.0 - p.y)));
434    vec3 base = vec3(0.018, 0.026, 0.055);
435    vec3 cyan = vec3(0.12, 0.82, 1.0);
436    vec3 violet = vec3(0.72, 0.20, 1.0);
437    vec3 col = base + cyan * r1 * u_intensity + violet * r2 * 0.72 * u_intensity + cyan * border * 0.22 + vec3(ink);
438    gl_FragColor = vec4(col, 0.82) * color;
439}
440"#;
441
442pub const BLOOM_GLOW_FRAGMENT: &str = r#"#version 100
443precision mediump float;
444varying lowp vec2 uv;
445varying lowp vec4 color;
446uniform sampler2D Texture;
447uniform float u_time;
448uniform vec2 u_resolution;
449uniform float u_intensity;
450
451float blob(vec2 p, vec2 c, float radius) {
452    float d = length(p - c);
453    return radius * radius / max(d * d, 0.001);
454}
455
456void main() {
457    vec2 p = uv;
458    float t = u_time;
459    float glow = 0.0;
460    glow += blob(p, vec2(0.22 + sin(t * 0.7) * 0.12, 0.34 + cos(t * 0.6) * 0.08), 0.045);
461    glow += blob(p, vec2(0.76 + cos(t * 0.5) * 0.10, 0.52 + sin(t * 0.9) * 0.12), 0.060);
462    glow += blob(p, vec2(0.50 + sin(t * 0.4) * 0.18, 0.78 + cos(t * 0.8) * 0.05), 0.038);
463    glow = min(glow, 3.0);
464    float scan = sin((p.y + t * 0.11) * 540.0) * 0.5 + 0.5;
465    float vignette = smoothstep(0.82, 0.12, length(p - 0.5));
466    vec3 base = vec3(0.010, 0.014, 0.030);
467    vec3 hot = mix(vec3(0.10, 0.55, 1.0), vec3(0.95, 0.18, 1.0), p.x);
468    vec3 col = base + hot * glow * 0.23 * u_intensity + vec3(scan * 0.018);
469    col *= 0.62 + vignette * 0.72;
470    gl_FragColor = vec4(col, 0.78) * color;
471}
472"#;
473
474pub const CODE_LENS_FRAGMENT: &str = r#"#version 100
475precision mediump float;
476varying lowp vec2 uv;
477varying lowp vec4 color;
478uniform sampler2D Texture;
479uniform float u_time;
480uniform vec2 u_resolution;
481uniform float u_intensity;
482
483float hash(vec2 p) {
484    return fract(sin(dot(p, vec2(101.7, 203.3))) * 43758.5453);
485}
486
487float line_y(float y, float target, float width) {
488    return smoothstep(width, 0.0, abs(y - target));
489}
490
491void main() {
492    vec2 p = uv;
493    float lens = smoothstep(0.38, 0.0, length((p - vec2(0.5, 0.52)) * vec2(1.0, 1.8)));
494    float code = 0.0;
495    for (int i = 0; i < 18; i++) {
496        float fi = float(i);
497        float y = 0.08 + fi * 0.048;
498        float len = 0.2 + hash(vec2(fi, 1.0)) * 0.58;
499        float start = 0.08 + hash(vec2(fi, 2.0)) * 0.18;
500        float seg = smoothstep(start, start + 0.018, p.x) * smoothstep(start + len, start + len - 0.018, p.x);
501        code += line_y(p.y, y + sin(u_time * 0.9 + fi) * 0.003, 0.004 + lens * 0.006) * seg;
502    }
503    float cursor = smoothstep(0.015, 0.0, abs(p.x - (0.16 + fract(u_time * 0.11) * 0.68))) * line_y(p.y, 0.52, 0.022);
504    vec3 base = vec3(0.012, 0.017, 0.034);
505    vec3 text = vec3(0.52, 0.85, 1.0);
506    vec3 lens_col = vec3(0.18, 0.58, 1.0) * lens * 0.18;
507    vec3 col = base + text * code * (0.22 + lens * 0.50) * u_intensity + lens_col + vec3(0.9, 0.6, 0.2) * cursor * 0.6;
508    gl_FragColor = vec4(col, 0.86) * color;
509}
510"#;
511
512pub const REACTION_DIFFUSION_FRAGMENT: &str = r#"#version 100
513precision mediump float;
514varying lowp vec2 uv;
515varying lowp vec4 color;
516uniform sampler2D Texture;
517uniform float u_time;
518uniform vec2 u_resolution;
519uniform float u_intensity;
520
521float hash(vec2 p) {
522    return fract(sin(dot(p, vec2(17.17, 313.13))) * 43758.5453);
523}
524
525float n(vec2 p) {
526    vec2 i = floor(p);
527    vec2 f = fract(p);
528    f = f * f * (3.0 - 2.0 * f);
529    return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x), f.y);
530}
531
532void main() {
533    vec2 p = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / max(u_resolution.x, u_resolution.y);
534    float t = u_time * 0.12;
535    float a = n(p * 4.0 + t);
536    float b = n(p * 9.0 - t * 1.7 + a);
537    float c = n(p * 19.0 + vec2(a, b) * 3.0 - t);
538    float cells = smoothstep(0.48, 0.54, abs(a - b) + c * 0.14);
539    float veins = smoothstep(0.72, 0.98, sin((a - b + c) * 18.0 + u_time));
540    vec3 base = vec3(0.008, 0.014, 0.028);
541    vec3 acid = vec3(0.30, 1.0, 0.58);
542    vec3 plasma = vec3(0.45, 0.18, 1.0);
543    vec3 col = base + acid * cells * 0.32 * u_intensity + plasma * veins * 0.26;
544    gl_FragColor = vec4(col, 0.80) * color;
545}
546"#;
547
548pub const VORONOI_CRYSTAL_FRAGMENT: &str = r#"#version 100
549precision mediump float;
550varying lowp vec2 uv;
551varying lowp vec4 color;
552uniform sampler2D Texture;
553uniform float u_time;
554uniform vec2 u_resolution;
555uniform float u_intensity;
556
557vec2 hash2(vec2 p) {
558    p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
559    return fract(sin(p) * 43758.5453);
560}
561
562void main() {
563    vec2 p = uv * vec2(u_resolution.x / max(u_resolution.y, 1.0), 1.0) * 8.0;
564    vec2 i = floor(p);
565    vec2 f = fract(p);
566    float min_d = 8.0;
567    float second_d = 8.0;
568    for (int y = -1; y <= 1; y++) {
569        for (int x = -1; x <= 1; x++) {
570            vec2 g = vec2(float(x), float(y));
571            vec2 o = hash2(i + g);
572            o = 0.5 + 0.5 * sin(u_time * 0.35 + 6.2831 * o);
573            float d = length(g + o - f);
574            if (d < min_d) {
575                second_d = min_d;
576                min_d = d;
577            } else if (d < second_d) {
578                second_d = d;
579            }
580        }
581    }
582    float edge = smoothstep(0.045, 0.0, second_d - min_d);
583    float facet = smoothstep(0.9, 0.0, min_d);
584    vec3 base = vec3(0.010, 0.012, 0.032);
585    vec3 cyan = vec3(0.18, 0.82, 1.0);
586    vec3 rose = vec3(1.0, 0.20, 0.62);
587    vec3 col = base + cyan * edge * 0.58 * u_intensity + rose * facet * 0.10;
588    gl_FragColor = vec4(col, 0.78) * color;
589}
590"#;
591
592pub const PLASMA_GRAPH_FRAGMENT: &str = r#"#version 100
593precision mediump float;
594varying lowp vec2 uv;
595varying lowp vec4 color;
596uniform sampler2D Texture;
597uniform float u_time;
598uniform vec2 u_resolution;
599uniform float u_intensity;
600
601float line(vec2 p, vec2 a, vec2 b, float w) {
602    vec2 pa = p - a;
603    vec2 ba = b - a;
604    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
605    return smoothstep(w, 0.0, length(pa - ba * h));
606}
607
608void main() {
609    vec2 p = uv;
610    vec2 nodes[6];
611    nodes[0] = vec2(0.14, 0.25 + sin(u_time * 0.8) * 0.06);
612    nodes[1] = vec2(0.32, 0.68 + cos(u_time * 0.5) * 0.07);
613    nodes[2] = vec2(0.48, 0.36 + sin(u_time * 0.6 + 1.0) * 0.08);
614    nodes[3] = vec2(0.64, 0.72 + cos(u_time * 0.7 + 2.0) * 0.06);
615    nodes[4] = vec2(0.82, 0.30 + sin(u_time * 0.55 + 3.0) * 0.07);
616    nodes[5] = vec2(0.90, 0.82 + cos(u_time * 0.45 + 4.0) * 0.05);
617    float network = 0.0;
618    float sparks = 0.0;
619    for (int i = 0; i < 5; i++) {
620        vec2 a = nodes[i];
621        vec2 b = nodes[i + 1];
622        network += line(p, a, b, 0.010);
623        float pulse = fract(u_time * 0.22 + float(i) * 0.19);
624        sparks += smoothstep(0.045, 0.0, length(p - mix(a, b, pulse)));
625    }
626    for (int j = 0; j < 6; j++) {
627        network += smoothstep(0.055, 0.0, length(p - nodes[j])) * 0.9;
628    }
629    vec3 base = vec3(0.007, 0.010, 0.028);
630    vec3 blue = vec3(0.10, 0.58, 1.0);
631    vec3 hot = vec3(1.0, 0.36, 0.12);
632    vec3 col = base + blue * network * 0.34 * u_intensity + hot * sparks * 0.42;
633    gl_FragColor = vec4(col, 0.84) * color;
634}
635"#;
636
637pub const SDF_CARD_MORPH_FRAGMENT: &str = r#"#version 100
638precision mediump float;
639varying lowp vec2 uv;
640varying lowp vec4 color;
641uniform sampler2D Texture;
642uniform float u_time;
643uniform vec2 u_resolution;
644uniform float u_intensity;
645
646float sdRoundBox(vec2 p, vec2 b, float r) {
647    vec2 q = abs(p) - b + r;
648    return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;
649}
650
651float sdCapsuleBox(vec2 p, vec2 b) {
652    float r = min(b.x, b.y);
653    return sdRoundBox(p, b, r);
654}
655
656float blobWarp(vec2 p, float t) {
657    float a = atan(p.y, p.x);
658    return sin(a * 3.0 + t * 1.7) * 0.035 + sin(a * 7.0 - t * 1.2) * 0.018;
659}
660
661float sdTicket(vec2 p, vec2 b, float r) {
662    float box = sdRoundBox(p, b, r);
663    float left = length(p - vec2(-b.x, 0.0)) - 0.115;
664    float right = length(p - vec2(b.x, 0.0)) - 0.115;
665    return max(box, -min(left, right));
666}
667
668void main() {
669    vec2 p = uv * 2.0 - 1.0;
670    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
671    float t = u_time;
672    float morph = 0.5 + 0.5 * sin(t * 0.55);
673    float morph2 = 0.5 + 0.5 * sin(t * 0.37 + 1.8);
674    vec2 b = mix(vec2(0.72, 0.38), vec2(0.58, 0.58), morph2);
675    float card = sdRoundBox(p, b, mix(0.08, 0.24, morph));
676    float capsule = sdCapsuleBox(p, b * vec2(1.08, 0.72));
677    vec2 warped = p * (1.0 + blobWarp(p, t) * mix(0.0, 2.6, morph));
678    float blob = sdRoundBox(warped, b * vec2(0.96, 0.94), 0.34);
679    float ticket = sdTicket(p, b, 0.08);
680    float d = mix(card, capsule, smoothstep(0.0, 0.36, morph));
681    d = mix(d, blob, smoothstep(0.26, 0.76, morph));
682    d = mix(d, ticket, smoothstep(0.70, 1.0, morph2) * 0.45);
683    float fill = smoothstep(0.012, -0.006, d);
684    float edge = smoothstep(0.018, 0.0, abs(d));
685    float outer = smoothstep(0.18, 0.0, d) * smoothstep(-0.02, 0.08, d);
686    float grid = (sin((p.x + t * 0.05) * 42.0) * sin((p.y - t * 0.04) * 34.0)) * 0.5 + 0.5;
687    vec3 base = vec3(0.015, 0.020, 0.045);
688    vec3 fill_col = mix(vec3(0.05, 0.18, 0.45), vec3(0.22, 0.08, 0.45), morph);
689    vec3 rim = mix(vec3(0.10, 0.72, 1.0), vec3(0.95, 0.24, 1.0), morph2);
690    vec3 col = base + fill_col * fill * 0.92 + rim * edge * u_intensity + rim * outer * 0.22;
691    col += vec3(grid * fill * 0.025);
692    gl_FragColor = vec4(col, 0.92 * max(fill, outer)) * color;
693}
694"#;
695
696pub const METABALL_CARD_FRAGMENT: &str = r#"#version 100
697precision mediump float;
698varying lowp vec2 uv;
699varying lowp vec4 color;
700uniform sampler2D Texture;
701uniform float u_time;
702uniform vec2 u_resolution;
703uniform float u_intensity;
704
705float ball(vec2 p, vec2 c, float r) {
706    float d = length(p - c);
707    return r * r / max(d * d, 0.002);
708}
709
710void main() {
711    vec2 p = uv * 2.0 - 1.0;
712    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
713    float t = u_time;
714    float f = 0.0;
715    f += ball(p, vec2(-0.48 + sin(t * 0.7) * 0.18, -0.20 + cos(t * 0.5) * 0.14), 0.34);
716    f += ball(p, vec2(0.30 + cos(t * 0.6) * 0.20, -0.04 + sin(t * 0.9) * 0.12), 0.38);
717    f += ball(p, vec2(-0.08 + sin(t * 0.4 + 2.0) * 0.16, 0.32 + cos(t * 0.8) * 0.12), 0.32);
718    f += ball(p, vec2(0.58 + sin(t * 0.55 + 1.1) * 0.10, 0.20 + cos(t * 0.45) * 0.14), 0.24);
719    float surface = smoothstep(1.08, 1.16, f);
720    float edge = smoothstep(1.05, 1.22, f) - smoothstep(1.24, 1.42, f);
721    float core = smoothstep(1.8, 3.0, f);
722    vec3 base = vec3(0.005, 0.010, 0.026);
723    vec3 cyan = vec3(0.08, 0.82, 1.0);
724    vec3 pink = vec3(1.0, 0.16, 0.72);
725    vec3 amber = vec3(1.0, 0.58, 0.08);
726    vec3 col = base + mix(cyan, pink, uv.x) * surface * 0.54 * u_intensity + amber * edge * 0.45 + vec3(core * 0.18);
727    gl_FragColor = vec4(col, 0.88 * max(surface, edge)) * color;
728}
729"#;
730
731pub const GOOGLE_AURA_FRAGMENT: &str = r#"#version 100
732precision mediump float;
733varying lowp vec2 uv;
734varying lowp vec4 color;
735uniform sampler2D Texture;
736uniform float u_time;
737uniform vec2 u_resolution;
738uniform float u_intensity;
739
740float hash(vec2 p) { return fract(sin(dot(p, vec2(37.2, 171.9))) * 43758.5453); }
741float noise(vec2 p) {
742    vec2 i = floor(p);
743    vec2 f = fract(p);
744    f = f * f * (3.0 - 2.0 * f);
745    return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x), f.y);
746}
747
748void main() {
749    vec2 p = uv - 0.5;
750    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
751    float t = u_time * 0.16;
752    float n = noise(p * 3.0 + t) * 0.5 + noise(p * 7.0 - t * 1.7) * 0.3 + noise(p * 15.0 + t * 2.1) * 0.2;
753    float angle = atan(p.y, p.x) / 6.2831853 + 0.5 + n * 0.18 + t * 0.25;
754    vec3 blue = vec3(0.10, 0.42, 1.0);
755    vec3 red = vec3(1.0, 0.20, 0.12);
756    vec3 yellow = vec3(1.0, 0.74, 0.08);
757    vec3 green = vec3(0.10, 0.72, 0.28);
758    vec3 a = mix(blue, red, smoothstep(0.0, 0.35, fract(angle)));
759    vec3 b = mix(yellow, green, smoothstep(0.35, 1.0, fract(angle)));
760    vec3 hue = mix(a, b, smoothstep(0.25, 0.8, n));
761    float d = length(p);
762    float aura = smoothstep(0.72, 0.08, d + n * 0.12);
763    float ring = smoothstep(0.018, 0.0, abs(d - (0.26 + sin(u_time * 0.8) * 0.035 + n * 0.06)));
764    vec3 col = hue * aura * (0.36 + u_intensity * 0.44) + vec3(ring) * 0.32;
765    gl_FragColor = vec4(col, 0.78 * aura) * color;
766}
767"#;
768
769pub const ORBITAL_MESH_FRAGMENT: &str = r#"#version 100
770precision mediump float;
771varying lowp vec2 uv;
772varying lowp vec4 color;
773uniform sampler2D Texture;
774uniform float u_time;
775uniform vec2 u_resolution;
776uniform float u_intensity;
777
778float seg(vec2 p, vec2 a, vec2 b, float w) {
779    vec2 pa = p - a;
780    vec2 ba = b - a;
781    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
782    return smoothstep(w, 0.0, length(pa - ba * h));
783}
784
785vec2 orbit(float i, float t, float r) {
786    return vec2(cos(t + i * 1.047), sin(t * 0.83 + i * 1.618)) * r;
787}
788
789void main() {
790    vec2 p = uv * 2.0 - 1.0;
791    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
792    float t = u_time * 0.55;
793    vec2 n0 = orbit(0.0, t, 0.52);
794    vec2 n1 = orbit(1.0, t, 0.48);
795    vec2 n2 = orbit(2.0, t, 0.56);
796    vec2 n3 = orbit(3.0, t, 0.42);
797    vec2 n4 = orbit(4.0, t, 0.50);
798    float network = 0.0;
799    network += seg(p, n0, n1, 0.009);
800    network += seg(p, n1, n2, 0.009);
801    network += seg(p, n2, n3, 0.009);
802    network += seg(p, n3, n4, 0.009);
803    network += seg(p, n4, n0, 0.009);
804    network += smoothstep(0.055, 0.0, length(p - n0));
805    network += smoothstep(0.055, 0.0, length(p - n1));
806    network += smoothstep(0.055, 0.0, length(p - n2));
807    network += smoothstep(0.055, 0.0, length(p - n3));
808    network += smoothstep(0.055, 0.0, length(p - n4));
809    float halo = smoothstep(0.75, 0.10, length(p));
810    vec3 col = vec3(0.006, 0.012, 0.032) + vec3(0.10, 0.72, 1.0) * network * 0.38 * u_intensity + vec3(0.75, 0.2, 1.0) * halo * 0.08;
811    gl_FragColor = vec4(col, 0.84) * color;
812}
813"#;
814
815pub const GLASS_CAUSTIC_FRAGMENT: &str = r#"#version 100
816precision mediump float;
817varying lowp vec2 uv;
818varying lowp vec4 color;
819uniform sampler2D Texture;
820uniform float u_time;
821uniform vec2 u_resolution;
822uniform float u_intensity;
823
824float wave(vec2 p, float t) {
825    return sin(p.x * 18.0 + t) + sin(p.y * 21.0 - t * 1.2) + sin((p.x + p.y) * 15.0 + t * 0.7);
826}
827
828void main() {
829    vec2 p = uv;
830    float t = u_time * 0.7;
831    float c = wave(p, t);
832    float c2 = wave(p + vec2(c * 0.018, -c * 0.014), -t * 0.8);
833    float caustic = smoothstep(1.7, 2.7, c2);
834    float edge = 1.0 - smoothstep(0.0, 0.018, min(min(p.x, p.y), min(1.0 - p.x, 1.0 - p.y)));
835    float glare = smoothstep(0.02, 0.0, abs(p.y - (0.22 + sin(t) * 0.04))) * smoothstep(0.15, 0.75, p.x) * smoothstep(0.95, 0.45, p.x);
836    vec3 glass = vec3(0.040, 0.070, 0.120);
837    vec3 cyan = vec3(0.34, 0.88, 1.0);
838    vec3 col = glass + cyan * caustic * 0.22 * u_intensity + vec3(glare * 0.22) + cyan * edge * 0.24;
839    gl_FragColor = vec4(col, 0.62) * color;
840}
841"#;
842
843pub const LIQUID_CHROME_FRAGMENT: &str = r#"#version 100
844precision mediump float;
845varying lowp vec2 uv;
846varying lowp vec4 color;
847uniform sampler2D Texture;
848uniform float u_time;
849uniform vec2 u_resolution;
850uniform float u_intensity;
851
852float hash(vec2 p) { return fract(sin(dot(p, vec2(93.1, 67.7))) * 43758.5453); }
853float noise(vec2 p) {
854    vec2 i = floor(p);
855    vec2 f = fract(p);
856    f = f * f * (3.0 - 2.0 * f);
857    return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x), f.y);
858}
859
860void main() {
861    vec2 p = uv * 2.0 - 1.0;
862    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
863    float t = u_time * 0.18;
864    vec2 q = p;
865    q += vec2(noise(p * 2.0 + t), noise(p * 2.0 - t)) * 0.22;
866    float bands = sin(q.x * 12.0 + noise(q * 5.0) * 5.0 + u_time) * 0.5 + 0.5;
867    float spec = pow(smoothstep(0.62, 1.0, bands), 5.0);
868    float body = smoothstep(0.72, 0.12, length(p));
869    vec3 cold = vec3(0.18, 0.42, 0.88);
870    vec3 warm = vec3(1.0, 0.55, 0.22);
871    vec3 chrome = mix(cold, warm, bands);
872    vec3 col = chrome * body * (0.22 + u_intensity * 0.30) + vec3(spec * 0.52);
873    gl_FragColor = vec4(col, 0.82 * body) * color;
874}
875"#;
876
877pub const AISLING_BLACKHOLE_FRAGMENT: &str = r#"#version 100
878precision mediump float;
879varying lowp vec2 uv;
880varying lowp vec4 color;
881uniform sampler2D Texture;
882uniform float u_time;
883uniform vec2 u_resolution;
884uniform float u_intensity;
885
886float hash(vec2 p) {
887    p = fract(p * vec2(123.34, 345.45));
888    p += dot(p, p + 34.23);
889    return fract(p.x * p.y);
890}
891
892void main() {
893    vec2 p = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / max(u_resolution.x, u_resolution.y);
894    float t = u_time * 0.42;
895    float d = length(p);
896    float a = atan(p.y, p.x);
897    float swirl = sin(a * 4.0 - t * 4.0 + 1.0 / max(d, 0.035));
898    float accretion = smoothstep(0.030, 0.0, abs(d - (0.34 + swirl * 0.030))) * smoothstep(0.95, 0.10, d);
899    accretion += smoothstep(0.018, 0.0, abs(d - (0.54 + sin(a * 2.0 + t) * 0.045))) * 0.62;
900    float horizon = smoothstep(0.155, 0.115, d);
901    float lens = (smoothstep(0.80, 0.16, d) - smoothstep(0.24, 0.10, d)) * (0.42 + 0.58 * abs(swirl));
902    float stars = step(0.992, hash(floor(gl_FragCoord.xy / 2.0) + floor(u_time * 8.0))) * smoothstep(0.18, 1.10, d);
903    vec3 base = vec3(0.004, 0.006, 0.018);
904    vec3 violet = vec3(0.46, 0.28, 1.0);
905    vec3 cyan = vec3(0.08, 0.88, 1.0);
906    vec3 amber = vec3(1.0, 0.48, 0.12);
907    vec3 col = base + violet * lens * 0.30 + cyan * accretion * 0.60 * u_intensity;
908    col += amber * pow(accretion, 2.0) * 0.34 + vec3(stars) * 0.72;
909    col = mix(col, vec3(0.0), horizon * 0.92);
910    gl_FragColor = vec4(col, 0.96) * color;
911}
912"#;
913
914pub const AISLING_RINGS_FRAGMENT: &str = r#"#version 100
915precision mediump float;
916varying lowp vec2 uv;
917varying lowp vec4 color;
918uniform sampler2D Texture;
919uniform float u_time;
920uniform vec2 u_resolution;
921uniform float u_intensity;
922
923float hash(float n) {
924    return fract(sin(n * 91.17) * 43758.5453);
925}
926
927void main() {
928    vec2 p = uv * 2.0 - 1.0;
929    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
930    float t = u_time * 0.48;
931    float d = length(p * vec2(1.0, 1.85));
932    float bands = 0.0;
933    for (int i = 0; i < 6; i++) {
934        float fi = float(i);
935        float radius = 0.15 + fi * 0.115 + sin(t * 1.7 + fi) * 0.014;
936        bands += smoothstep(0.018, 0.0, abs(d - radius)) * (0.75 - fi * 0.075);
937    }
938    float orbit = 0.0;
939    for (int j = 0; j < 12; j++) {
940        float fj = float(j);
941        float angle = t * (0.8 + hash(fj) * 1.5) + fj * 0.5236;
942        float radius = 0.20 + hash(fj + 4.0) * 0.50;
943        vec2 node = vec2(cos(angle) * radius, sin(angle) * radius * 0.45);
944        orbit += smoothstep(0.038, 0.0, length(p - node));
945    }
946    float core = smoothstep(0.12, 0.0, length(p));
947    vec3 base = vec3(0.006, 0.010, 0.028);
948    vec3 violet = vec3(0.68, 0.30, 1.0);
949    vec3 mint = vec3(0.18, 1.0, 0.78);
950    vec3 col = base + violet * bands * 0.48 * u_intensity + mint * orbit * 0.24 + vec3(core * 0.18);
951    gl_FragColor = vec4(col, 0.88) * color;
952}
953"#;
954
955pub const AISLING_FIREWORKS_FRAGMENT: &str = r#"#version 100
956precision mediump float;
957varying lowp vec2 uv;
958varying lowp vec4 color;
959uniform sampler2D Texture;
960uniform float u_time;
961uniform vec2 u_resolution;
962uniform float u_intensity;
963
964float hash(vec2 p) {
965    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
966}
967
968float segment(vec2 p, vec2 a, vec2 b, float w) {
969    vec2 pa = p - a;
970    vec2 ba = b - a;
971    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
972    return smoothstep(w, 0.0, length(pa - ba * h));
973}
974
975void main() {
976    vec2 p = uv * 2.0 - 1.0;
977    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
978    float t = u_time * 0.22;
979    float fire = 0.0;
980    vec3 sparks = vec3(0.0);
981    vec2 launcher = vec2(0.0, -1.05);
982    for (int i = 0; i < 7; i++) {
983        float fi = float(i);
984        float phase = fract(t + hash(vec2(fi, 3.0)));
985        vec2 center = vec2(mix(-0.72, 0.72, hash(vec2(fi, 4.0))), mix(-0.18, 0.68, hash(vec2(fi, 5.0))));
986        float lift = (1.0 - smoothstep(0.18, 0.38, phase)) * smoothstep(0.0, 0.20, phase);
987        fire += segment(p, launcher, mix(launcher, center, smoothstep(0.0, 0.35, phase)), 0.010) * lift;
988        float radius = max(phase - 0.32, 0.0) * 1.25;
989        float d = length(p - center);
990        float ring = smoothstep(0.028, 0.0, abs(d - radius)) * (1.0 - smoothstep(0.72, 1.0, phase));
991        float angle = atan(p.y - center.y, p.x - center.x);
992        float spoke = step(0.55, sin(angle * (10.0 + hash(vec2(fi, 6.0)) * 10.0) + fi) * 0.5 + 0.5);
993        float glitter = step(0.955, hash(floor((p - center) * 44.0) + fi + floor(u_time * 10.0)));
994        vec3 hue = mix(vec3(1.0, 0.42, 0.10), vec3(0.18, 0.86, 1.0), hash(vec2(fi, 7.0)));
995        sparks += hue * (ring * (0.35 + spoke * 0.75) + glitter * ring * 1.4);
996    }
997    vec3 base = vec3(0.004, 0.007, 0.020);
998    vec3 col = base + vec3(1.0, 0.70, 0.18) * fire * 0.55 + sparks * u_intensity;
999    gl_FragColor = vec4(col, 0.90) * color;
1000}
1001"#;
1002
1003pub const AISLING_LASER_ETCH_FRAGMENT: &str = r#"#version 100
1004precision mediump float;
1005varying lowp vec2 uv;
1006varying lowp vec4 color;
1007uniform sampler2D Texture;
1008uniform float u_time;
1009uniform vec2 u_resolution;
1010uniform float u_intensity;
1011
1012float hash(vec2 p) {
1013    return fract(sin(dot(p, vec2(83.7, 217.3))) * 43758.5453);
1014}
1015
1016void main() {
1017    vec2 p = uv;
1018    float scan = fract(u_time * 0.18) * 2.35 - 0.20;
1019    float diag = p.x + p.y;
1020    float beam = smoothstep(0.032, 0.0, abs(diag - scan));
1021    float trail = smoothstep(0.28, 0.0, scan - diag) * step(diag, scan);
1022    float vertical = smoothstep(0.020, 0.0, abs(p.x - fract(u_time * 0.32)));
1023    float etched = smoothstep(0.010, 0.0, abs(fract((p.x + p.y) * 36.0) - 0.5)) * trail;
1024    float spark = step(0.972, hash(floor(p * vec2(64.0, 32.0)) + floor(u_time * 18.0))) * smoothstep(0.075, 0.0, abs(diag - scan));
1025    float heat = smoothstep(0.0, 0.18, trail) * (1.0 - smoothstep(0.20, 0.62, trail));
1026    vec3 base = vec3(0.014, 0.012, 0.024);
1027    vec3 red = vec3(1.0, 0.14, 0.06);
1028    vec3 gold = vec3(1.0, 0.78, 0.18);
1029    vec3 green = vec3(0.24, 1.0, 0.62);
1030    vec3 col = base + red * beam * 0.92 * u_intensity + gold * spark * 0.85;
1031    col += mix(red, green, trail) * etched * 0.34 + green * vertical * 0.16 + red * heat * 0.16;
1032    gl_FragColor = vec4(col, 0.88) * color;
1033}
1034"#;
1035
1036pub const AISLING_BEAMS_FRAGMENT: &str = r#"#version 100
1037precision mediump float;
1038varying lowp vec2 uv;
1039varying lowp vec4 color;
1040uniform sampler2D Texture;
1041uniform float u_time;
1042uniform vec2 u_resolution;
1043uniform float u_intensity;
1044
1045float line(vec2 p, vec2 a, vec2 b, float w) {
1046    vec2 pa = p - a;
1047    vec2 ba = b - a;
1048    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
1049    return smoothstep(w, 0.0, length(pa - ba * h));
1050}
1051
1052void main() {
1053    vec2 p = uv;
1054    float t = u_time;
1055    float vx = fract(t * 0.18);
1056    float hy = fract(t * 0.13 + 0.31);
1057    float beam = smoothstep(0.020, 0.0, abs(p.x - vx));
1058    beam += smoothstep(0.018, 0.0, abs(p.y - hy));
1059    for (int i = 0; i < 4; i++) {
1060        float fi = float(i);
1061        float shift = fract(t * (0.07 + fi * 0.015) + fi * 0.23) * 1.45 - 0.22;
1062        beam += line(p, vec2(-0.08, shift), vec2(1.08, shift - 0.58 + fi * 0.18), 0.010) * 0.62;
1063    }
1064    float cross = smoothstep(0.065, 0.0, length(p - vec2(vx, hy)));
1065    float scan = sin((p.y + t * 0.10) * 480.0) * 0.5 + 0.5;
1066    vec3 base = vec3(0.010, 0.018, 0.042);
1067    vec3 cyan = vec3(0.10, 0.78, 1.0);
1068    vec3 amber = vec3(1.0, 0.72, 0.18);
1069    vec3 col = base + cyan * beam * 0.38 * u_intensity + amber * cross * 0.45 + vec3(scan * 0.012);
1070    gl_FragColor = vec4(col, 0.86) * color;
1071}
1072"#;
1073
1074pub const AISLING_SYNTH_GRID_FRAGMENT: &str = r#"#version 100
1075precision mediump float;
1076varying lowp vec2 uv;
1077varying lowp vec4 color;
1078uniform sampler2D Texture;
1079uniform float u_time;
1080uniform vec2 u_resolution;
1081uniform float u_intensity;
1082
1083float grid_line(float value, float width) {
1084    return smoothstep(width, 0.0, abs(fract(value) - 0.5));
1085}
1086
1087void main() {
1088    vec2 p = uv * 2.0 - 1.0;
1089    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
1090    float t = u_time * 0.28;
1091    float depth = max(0.04, p.y + 0.92);
1092    float perspective = 1.0 / depth;
1093    float horizon = smoothstep(0.08, 0.0, abs(p.y + 0.18));
1094    float verticals = grid_line(p.x * perspective * 3.5, 0.030) * smoothstep(-0.22, 0.85, p.y);
1095    float horizontals = grid_line(perspective * 1.65 - t * 2.2, 0.020) * smoothstep(-0.22, 0.90, p.y);
1096    float diagonal = grid_line((uv.x + uv.y) * 9.0 + t * 2.0, 0.018) * 0.32;
1097    float pulse = sin(length(p * vec2(1.0, 1.9)) * 13.0 - u_time * 4.0) * 0.5 + 0.5;
1098    float grid = (verticals + horizontals + diagonal) * (0.62 + pulse * 0.38);
1099    vec3 base = mix(vec3(0.010, 0.006, 0.030), vec3(0.025, 0.014, 0.060), uv.y);
1100    vec3 magenta = vec3(1.0, 0.18, 0.86);
1101    vec3 cyan = vec3(0.04, 0.94, 1.0);
1102    vec3 col = base + mix(magenta, cyan, uv.y) * grid * 0.44 * u_intensity + magenta * horizon * 0.25;
1103    gl_FragColor = vec4(col, 0.88) * color;
1104}
1105"#;
1106
1107pub const AISLING_SPOTLIGHTS_FRAGMENT: &str = r#"#version 100
1108precision mediump float;
1109varying lowp vec2 uv;
1110varying lowp vec4 color;
1111uniform sampler2D Texture;
1112uniform float u_time;
1113uniform vec2 u_resolution;
1114uniform float u_intensity;
1115
1116void main() {
1117    vec2 p = uv * 2.0 - 1.0;
1118    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
1119    float t = u_time * 0.55;
1120    float light = 0.0;
1121    for (int i = 0; i < 3; i++) {
1122        float fi = float(i);
1123        float angle = t + fi * 2.094;
1124        vec2 center = vec2(cos(angle) * (0.36 - fi * 0.03), sin(angle * 0.84) * (0.30 + fi * 0.04));
1125        float radius = 0.38 + 0.04 * sin(t * 1.7 + fi);
1126        light = max(light, smoothstep(radius, 0.0, length(p - center)));
1127    }
1128    float reveal = smoothstep(-0.12, 0.88, uv.x + sin(u_time * 0.25) * 0.12);
1129    float grain = sin((uv.y + u_time * 0.04) * 520.0) * 0.5 + 0.5;
1130    vec3 base = vec3(0.012, 0.014, 0.027);
1131    vec3 warm = vec3(1.0, 0.92, 0.58);
1132    vec3 blue = vec3(0.12, 0.54, 1.0);
1133    vec3 col = base + warm * light * (0.30 + u_intensity * 0.36) + blue * reveal * 0.07 + vec3(grain * light * 0.020);
1134    gl_FragColor = vec4(col, 0.86) * color;
1135}
1136"#;
1137
1138pub const AISLING_SWARM_FRAGMENT: &str = r#"#version 100
1139precision mediump float;
1140varying lowp vec2 uv;
1141varying lowp vec4 color;
1142uniform sampler2D Texture;
1143uniform float u_time;
1144uniform vec2 u_resolution;
1145uniform float u_intensity;
1146
1147float hash(float n) {
1148    return fract(sin(n * 113.7) * 43758.5453);
1149}
1150
1151void main() {
1152    vec2 p = uv;
1153    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
1154    float t = u_time;
1155    float glow = 0.0;
1156    float dots = 0.0;
1157    vec3 chroma = vec3(0.0);
1158    for (int i = 0; i < 44; i++) {
1159        float fi = float(i);
1160        float h = hash(fi);
1161        float cursor = fract(t * 0.055 + h);
1162        vec2 target = vec2(cursor * u_resolution.x / max(u_resolution.y, 1.0), 0.52 + sin(t * 0.55 + fi) * 0.11);
1163        float angle = t * (0.9 + h * 1.7) + fi * 0.61;
1164        float radius = 0.035 + hash(fi + 9.0) * 0.22;
1165        vec2 node = target + vec2(cos(angle) * radius, sin(angle) * radius * 0.52);
1166        float d = length(p - node);
1167        float particle = smoothstep(0.020, 0.0, d);
1168        glow += 0.0018 / (d * d + 0.0012);
1169        dots += particle;
1170        chroma += mix(vec3(0.10, 1.0, 0.64), vec3(1.0, 0.18, 0.86), h) * particle;
1171    }
1172    glow = min(glow, 3.0);
1173    vec3 base = vec3(0.006, 0.012, 0.028);
1174    vec3 col = base + chroma * 0.42 * u_intensity + vec3(0.06, 0.45, 1.0) * glow * 0.08;
1175    col += vec3(dots * 0.018);
1176    gl_FragColor = vec4(col, 0.86) * color;
1177}
1178"#;
1179
1180pub const AISLING_STORM_FRAGMENT: &str = r#"#version 100
1181precision mediump float;
1182varying lowp vec2 uv;
1183varying lowp vec4 color;
1184uniform sampler2D Texture;
1185uniform float u_time;
1186uniform vec2 u_resolution;
1187uniform float u_intensity;
1188
1189float hash(vec2 p) {
1190    return fract(sin(dot(p, vec2(29.1, 173.7))) * 43758.5453);
1191}
1192
1193void main() {
1194    vec2 cell = floor(gl_FragCoord.xy / vec2(7.0, 14.0));
1195    float column = hash(vec2(cell.x, 1.0));
1196    float speed = mix(0.7, 2.8, column);
1197    float fall = fract(cell.y * 0.12 - u_time * speed + column * 8.0);
1198    float rain = smoothstep(0.92, 1.0, fall) + smoothstep(0.35, 0.0, fall) * 0.35;
1199    float flash_seed = hash(vec2(floor(u_time * 1.4), 8.0));
1200    float flash = step(0.78, flash_seed) * smoothstep(0.42, 1.0, sin(fract(u_time * 1.4) * 3.14159));
1201    float bolt_x = 0.18 + 0.64 * hash(vec2(floor(u_time * 1.4), 4.0));
1202    float jag = sin(uv.y * 34.0 + floor(u_time * 1.4) * 2.7) * 0.030 + sin(uv.y * 79.0) * 0.014;
1203    float bolt = smoothstep(0.018, 0.0, abs(uv.x - bolt_x - jag)) * flash;
1204    float cloud = smoothstep(0.72, 0.18, uv.y) * (0.5 + 0.5 * sin(uv.x * 12.0 + u_time));
1205    vec3 base = vec3(0.007, 0.011, 0.026);
1206    vec3 rain_col = vec3(0.28, 0.62, 1.0);
1207    vec3 bolt_col = vec3(1.0, 0.96, 0.62);
1208    vec3 col = base + rain_col * rain * 0.24 * u_intensity + vec3(cloud * 0.035);
1209    col += bolt_col * bolt * (0.9 + u_intensity * 0.4) + vec3(flash * 0.10);
1210    gl_FragColor = vec4(col, 0.88) * color;
1211}
1212"#;
1213
1214pub const AISLING_VHS_FRAGMENT: &str = r#"#version 100
1215precision mediump float;
1216varying lowp vec2 uv;
1217varying lowp vec4 color;
1218uniform sampler2D Texture;
1219uniform float u_time;
1220uniform vec2 u_resolution;
1221uniform float u_intensity;
1222
1223float hash(vec2 p) {
1224    return fract(sin(dot(p, vec2(101.3, 241.9))) * 43758.5453);
1225}
1226
1227void main() {
1228    float row = floor(uv.y * 96.0);
1229    float tick = floor(u_time * 18.0);
1230    float row_noise = hash(vec2(row, tick)) - 0.5;
1231    float instability = 0.35 + 0.65 * (sin(u_time * 0.9) * 0.5 + 0.5);
1232    float offset = row_noise * 0.085 * instability;
1233    vec2 q = vec2(fract(uv.x + offset), uv.y);
1234    float scan = sin(q.y * 920.0) * 0.5 + 0.5;
1235    float tracking = step(0.972, hash(vec2(row, floor(u_time * 5.0)))) * smoothstep(0.02, 0.0, abs(fract(q.y * 12.0 + u_time * 0.4) - 0.5));
1236    float blocks = step(0.965, hash(floor(q * vec2(28.0, 18.0)) + tick));
1237    float signal = smoothstep(0.44, 0.0, abs(fract(q.x * 9.0 + floor(q.y * 14.0) * 0.11) - 0.5));
1238    vec3 base = vec3(0.013, 0.015, 0.032);
1239    vec3 col = base + vec3(0.12, 0.26, 0.46) * signal * 0.20;
1240    col.r += signal * 0.10 + blocks * 0.24;
1241    col.g += signal * 0.08;
1242    col.b += scan * 0.035 + tracking * 0.42 * u_intensity;
1243    col += vec3(blocks * 0.08 * u_intensity);
1244    gl_FragColor = vec4(col, 0.84) * color;
1245}
1246"#;
1247
1248pub const AISLING_WAVES_FRAGMENT: &str = r#"#version 100
1249precision mediump float;
1250varying lowp vec2 uv;
1251varying lowp vec4 color;
1252uniform sampler2D Texture;
1253uniform float u_time;
1254uniform vec2 u_resolution;
1255uniform float u_intensity;
1256
1257void main() {
1258    vec2 p = uv;
1259    float t = u_time * 0.62;
1260    float waves = 0.0;
1261    float foam = 0.0;
1262    for (int i = 0; i < 8; i++) {
1263        float fi = float(i);
1264        float y = 0.10 + fi * 0.105 + sin(p.x * (7.0 + fi * 0.55) + t * (1.0 + fi * 0.13) + fi) * 0.045;
1265        float line = smoothstep(0.018, 0.0, abs(p.y - y));
1266        waves += line * (1.0 - fi * 0.055);
1267        foam += line * smoothstep(0.70, 1.0, sin(p.x * 32.0 + t * 4.0 + fi) * 0.5 + 0.5);
1268    }
1269    float sweep = smoothstep(0.16, 0.0, abs(p.x - fract(u_time * 0.16))) * smoothstep(0.05, 0.85, p.y);
1270    vec3 base = vec3(0.004, 0.018, 0.036);
1271    vec3 deep = vec3(0.04, 0.30, 0.72);
1272    vec3 cyan = vec3(0.14, 0.88, 1.0);
1273    vec3 col = base + deep * waves * 0.22 * u_intensity + cyan * foam * 0.26 + cyan * sweep * 0.12;
1274    gl_FragColor = vec4(col, 0.84) * color;
1275}
1276"#;
1277
1278pub const AISLING_VORTEX_FRAGMENT: &str = r#"#version 100
1279precision mediump float;
1280varying lowp vec2 uv;
1281varying lowp vec4 color;
1282uniform sampler2D Texture;
1283uniform float u_time;
1284uniform vec2 u_resolution;
1285uniform float u_intensity;
1286
1287float hash(vec2 p) {
1288    return fract(sin(dot(p, vec2(59.7, 337.1))) * 43758.5453);
1289}
1290
1291void main() {
1292    vec2 p = uv * 2.0 - 1.0;
1293    p.x *= u_resolution.x / max(u_resolution.y, 1.0);
1294    float d = length(p);
1295    float a = atan(p.y, p.x);
1296    float t = u_time * 0.78;
1297    float arms = sin(a * 5.0 - d * 14.0 + t * 3.0) * 0.5 + 0.5;
1298    float spiral = smoothstep(0.66, 1.0, arms) * smoothstep(1.15, 0.08, d);
1299    float polar = step(0.86, hash(vec2(floor(a * 18.0), floor(d * 22.0 - t * 4.0)))) * smoothstep(0.96, 0.15, d);
1300    float core = smoothstep(0.11, 0.0, d);
1301    vec3 base = vec3(0.006, 0.009, 0.026);
1302    vec3 cyan = vec3(0.10, 0.95, 1.0);
1303    vec3 violet = vec3(0.75, 0.18, 1.0);
1304    vec3 col = base + mix(violet, cyan, arms) * spiral * 0.44 * u_intensity + cyan * polar * 0.28 + vec3(core * 0.16);
1305    gl_FragColor = vec4(col, 0.88) * color;
1306}
1307"#;
1308
1309pub const AISLING_CASCADE_FRAGMENT: &str = r#"#version 100
1310precision mediump float;
1311varying lowp vec2 uv;
1312varying lowp vec4 color;
1313uniform sampler2D Texture;
1314uniform float u_time;
1315uniform vec2 u_resolution;
1316uniform float u_intensity;
1317
1318float hash(vec2 p) {
1319    return fract(sin(dot(p, vec2(17.9, 211.3))) * 43758.5453);
1320}
1321
1322void main() {
1323    vec2 cell = floor(gl_FragCoord.xy / vec2(9.0, 16.0));
1324    vec2 local = fract(gl_FragCoord.xy / vec2(9.0, 16.0));
1325    float column = hash(vec2(cell.x, 0.0));
1326    float speed = mix(0.45, 1.55, column);
1327    float head = fract(cell.y * 0.075 - u_time * speed + column * 6.0);
1328    float drop = smoothstep(0.94, 1.0, head) * smoothstep(0.45, 0.0, length(local - 0.5));
1329    float trail = smoothstep(0.56, 0.08, head) * smoothstep(0.09, 0.0, abs(local.x - 0.5)) * 0.55;
1330    float surface = smoothstep(0.020, 0.0, abs(uv.y - (0.80 + sin(uv.x * 14.0 + u_time) * 0.025)));
1331    vec3 base = vec3(0.006, 0.014, 0.032);
1332    vec3 blue = vec3(0.18, 0.58, 1.0);
1333    vec3 mint = vec3(0.16, 1.0, 0.72);
1334    vec3 col = base + blue * trail * 0.28 + mint * drop * 0.72 * u_intensity + blue * surface * 0.22;
1335    gl_FragColor = vec4(col, 0.82) * color;
1336}
1337"#;
1338
1339pub const AISLING_GRID_PULSE_FRAGMENT: &str = r#"#version 100
1340precision mediump float;
1341varying lowp vec2 uv;
1342varying lowp vec4 color;
1343uniform sampler2D Texture;
1344uniform float u_time;
1345uniform vec2 u_resolution;
1346uniform float u_intensity;
1347
1348float hash(vec2 p) {
1349    return fract(sin(dot(p, vec2(43.1, 97.7))) * 43758.5453);
1350}
1351
1352void main() {
1353    vec2 scale = vec2(24.0, 14.0);
1354    vec2 g = uv * scale;
1355    vec2 id = floor(g);
1356    vec2 local = fract(g) - 0.5;
1357    vec2 center = scale * 0.5 + vec2(sin(u_time * 0.33), cos(u_time * 0.27)) * 2.2;
1358    float dist = length(id - center);
1359    float wave = sin(dist * 0.82 - u_time * 4.0 + hash(id) * 2.0) * 0.5 + 0.5;
1360    float dot = smoothstep(0.15, 0.0, length(local));
1361    float alive = step(0.22, hash(id + floor(u_time * 2.0)));
1362    float pulse = dot * alive * smoothstep(0.42, 1.0, wave);
1363    float grid = smoothstep(0.018, 0.0, min(abs(local.x), abs(local.y)));
1364    vec3 base = vec3(0.006, 0.010, 0.030);
1365    vec3 cyan = vec3(0.10, 0.86, 1.0);
1366    vec3 pink = vec3(1.0, 0.18, 0.76);
1367    vec3 col = base + mix(cyan, pink, uv.x) * pulse * 0.72 * u_intensity + cyan * grid * 0.045;
1368    gl_FragColor = vec4(col, 0.84) * color;
1369}
1370"#;
1371
1372pub fn background_shader() -> ShaderSource {
1373    ShaderSource {
1374        name: "rae-background-curl-nebula",
1375        vertex: VERTEX,
1376        fragment: BACKGROUND_FRAGMENT,
1377        uniforms: COMMON_UNIFORMS,
1378    }
1379}
1380
1381pub fn pane_shader() -> ShaderSource {
1382    ShaderSource {
1383        name: "rae-pane-hex-lattice",
1384        vertex: VERTEX,
1385        fragment: PANE_FRAGMENT,
1386        uniforms: COMMON_UNIFORMS,
1387    }
1388}
1389
1390pub fn prompt_shader() -> ShaderSource {
1391    ShaderSource {
1392        name: "rae-prompt-beam-field",
1393        vertex: VERTEX,
1394        fragment: PROMPT_FRAGMENT,
1395        uniforms: COMMON_UNIFORMS,
1396    }
1397}
1398
1399pub fn aurora_shader() -> ShaderSource {
1400    ShaderSource {
1401        name: "rae-background-aurora-curtains",
1402        vertex: VERTEX,
1403        fragment: AURORA_FRAGMENT,
1404        uniforms: COMMON_UNIFORMS,
1405    }
1406}
1407
1408pub fn knot_field_shader() -> ShaderSource {
1409    ShaderSource {
1410        name: "rae-knot-raymarch-field",
1411        vertex: VERTEX,
1412        fragment: KNOT_FIELD_FRAGMENT,
1413        uniforms: COMMON_UNIFORMS,
1414    }
1415}
1416
1417pub fn terminal_rain_shader() -> ShaderSource {
1418    ShaderSource {
1419        name: "rae-terminal-rain",
1420        vertex: VERTEX,
1421        fragment: TERMINAL_RAIN_FRAGMENT,
1422        uniforms: COMMON_UNIFORMS,
1423    }
1424}
1425
1426pub fn flow_beams_shader() -> ShaderSource {
1427    ShaderSource {
1428        name: "rae-flow-beams",
1429        vertex: VERTEX,
1430        fragment: FLOW_BEAMS_FRAGMENT,
1431        uniforms: COMMON_UNIFORMS,
1432    }
1433}
1434
1435pub fn ripple_shader() -> ShaderSource {
1436    ShaderSource {
1437        name: "rae-interaction-ripples",
1438        vertex: VERTEX,
1439        fragment: RIPPLE_FRAGMENT,
1440        uniforms: COMMON_UNIFORMS,
1441    }
1442}
1443
1444pub fn bloom_glow_shader() -> ShaderSource {
1445    ShaderSource {
1446        name: "rae-bloom-glow-field",
1447        vertex: VERTEX,
1448        fragment: BLOOM_GLOW_FRAGMENT,
1449        uniforms: COMMON_UNIFORMS,
1450    }
1451}
1452
1453pub fn code_lens_shader() -> ShaderSource {
1454    ShaderSource {
1455        name: "rae-code-lens-scan",
1456        vertex: VERTEX,
1457        fragment: CODE_LENS_FRAGMENT,
1458        uniforms: COMMON_UNIFORMS,
1459    }
1460}
1461
1462pub fn reaction_diffusion_shader() -> ShaderSource {
1463    ShaderSource {
1464        name: "rae-reaction-diffusion",
1465        vertex: VERTEX,
1466        fragment: REACTION_DIFFUSION_FRAGMENT,
1467        uniforms: COMMON_UNIFORMS,
1468    }
1469}
1470
1471pub fn voronoi_crystal_shader() -> ShaderSource {
1472    ShaderSource {
1473        name: "rae-voronoi-crystal",
1474        vertex: VERTEX,
1475        fragment: VORONOI_CRYSTAL_FRAGMENT,
1476        uniforms: COMMON_UNIFORMS,
1477    }
1478}
1479
1480pub fn plasma_graph_shader() -> ShaderSource {
1481    ShaderSource {
1482        name: "rae-plasma-graph",
1483        vertex: VERTEX,
1484        fragment: PLASMA_GRAPH_FRAGMENT,
1485        uniforms: COMMON_UNIFORMS,
1486    }
1487}
1488
1489pub fn sdf_card_morph_shader() -> ShaderSource {
1490    ShaderSource {
1491        name: "rae-sdf-card-morph",
1492        vertex: VERTEX,
1493        fragment: SDF_CARD_MORPH_FRAGMENT,
1494        uniforms: COMMON_UNIFORMS,
1495    }
1496}
1497
1498pub fn metaball_card_shader() -> ShaderSource {
1499    ShaderSource {
1500        name: "rae-metaball-card",
1501        vertex: VERTEX,
1502        fragment: METABALL_CARD_FRAGMENT,
1503        uniforms: COMMON_UNIFORMS,
1504    }
1505}
1506
1507pub fn google_aura_shader() -> ShaderSource {
1508    ShaderSource {
1509        name: "rae-google-aura",
1510        vertex: VERTEX,
1511        fragment: GOOGLE_AURA_FRAGMENT,
1512        uniforms: COMMON_UNIFORMS,
1513    }
1514}
1515
1516pub fn orbital_mesh_shader() -> ShaderSource {
1517    ShaderSource {
1518        name: "rae-orbital-mesh",
1519        vertex: VERTEX,
1520        fragment: ORBITAL_MESH_FRAGMENT,
1521        uniforms: COMMON_UNIFORMS,
1522    }
1523}
1524
1525pub fn glass_caustic_shader() -> ShaderSource {
1526    ShaderSource {
1527        name: "rae-glass-caustic",
1528        vertex: VERTEX,
1529        fragment: GLASS_CAUSTIC_FRAGMENT,
1530        uniforms: COMMON_UNIFORMS,
1531    }
1532}
1533
1534pub fn liquid_chrome_shader() -> ShaderSource {
1535    ShaderSource {
1536        name: "rae-liquid-chrome",
1537        vertex: VERTEX,
1538        fragment: LIQUID_CHROME_FRAGMENT,
1539        uniforms: COMMON_UNIFORMS,
1540    }
1541}
1542
1543pub fn aisling_blackhole_shader() -> ShaderSource {
1544    ShaderSource {
1545        name: "rae-aisling-blackhole",
1546        vertex: VERTEX,
1547        fragment: AISLING_BLACKHOLE_FRAGMENT,
1548        uniforms: COMMON_UNIFORMS,
1549    }
1550}
1551
1552pub fn aisling_rings_shader() -> ShaderSource {
1553    ShaderSource {
1554        name: "rae-aisling-rings",
1555        vertex: VERTEX,
1556        fragment: AISLING_RINGS_FRAGMENT,
1557        uniforms: COMMON_UNIFORMS,
1558    }
1559}
1560
1561pub fn aisling_fireworks_shader() -> ShaderSource {
1562    ShaderSource {
1563        name: "rae-aisling-fireworks",
1564        vertex: VERTEX,
1565        fragment: AISLING_FIREWORKS_FRAGMENT,
1566        uniforms: COMMON_UNIFORMS,
1567    }
1568}
1569
1570pub fn aisling_laser_etch_shader() -> ShaderSource {
1571    ShaderSource {
1572        name: "rae-aisling-laser-etch",
1573        vertex: VERTEX,
1574        fragment: AISLING_LASER_ETCH_FRAGMENT,
1575        uniforms: COMMON_UNIFORMS,
1576    }
1577}
1578
1579pub fn aisling_beams_shader() -> ShaderSource {
1580    ShaderSource {
1581        name: "rae-aisling-beams",
1582        vertex: VERTEX,
1583        fragment: AISLING_BEAMS_FRAGMENT,
1584        uniforms: COMMON_UNIFORMS,
1585    }
1586}
1587
1588pub fn aisling_synth_grid_shader() -> ShaderSource {
1589    ShaderSource {
1590        name: "rae-aisling-synth-grid",
1591        vertex: VERTEX,
1592        fragment: AISLING_SYNTH_GRID_FRAGMENT,
1593        uniforms: COMMON_UNIFORMS,
1594    }
1595}
1596
1597pub fn aisling_spotlights_shader() -> ShaderSource {
1598    ShaderSource {
1599        name: "rae-aisling-spotlights",
1600        vertex: VERTEX,
1601        fragment: AISLING_SPOTLIGHTS_FRAGMENT,
1602        uniforms: COMMON_UNIFORMS,
1603    }
1604}
1605
1606pub fn aisling_swarm_shader() -> ShaderSource {
1607    ShaderSource {
1608        name: "rae-aisling-swarm",
1609        vertex: VERTEX,
1610        fragment: AISLING_SWARM_FRAGMENT,
1611        uniforms: COMMON_UNIFORMS,
1612    }
1613}
1614
1615pub fn aisling_storm_shader() -> ShaderSource {
1616    ShaderSource {
1617        name: "rae-aisling-storm",
1618        vertex: VERTEX,
1619        fragment: AISLING_STORM_FRAGMENT,
1620        uniforms: COMMON_UNIFORMS,
1621    }
1622}
1623
1624pub fn aisling_vhs_shader() -> ShaderSource {
1625    ShaderSource {
1626        name: "rae-aisling-vhs",
1627        vertex: VERTEX,
1628        fragment: AISLING_VHS_FRAGMENT,
1629        uniforms: COMMON_UNIFORMS,
1630    }
1631}
1632
1633pub fn aisling_waves_shader() -> ShaderSource {
1634    ShaderSource {
1635        name: "rae-aisling-waves",
1636        vertex: VERTEX,
1637        fragment: AISLING_WAVES_FRAGMENT,
1638        uniforms: COMMON_UNIFORMS,
1639    }
1640}
1641
1642pub fn aisling_vortex_shader() -> ShaderSource {
1643    ShaderSource {
1644        name: "rae-aisling-vortex",
1645        vertex: VERTEX,
1646        fragment: AISLING_VORTEX_FRAGMENT,
1647        uniforms: COMMON_UNIFORMS,
1648    }
1649}
1650
1651pub fn aisling_cascade_shader() -> ShaderSource {
1652    ShaderSource {
1653        name: "rae-aisling-cascade",
1654        vertex: VERTEX,
1655        fragment: AISLING_CASCADE_FRAGMENT,
1656        uniforms: COMMON_UNIFORMS,
1657    }
1658}
1659
1660pub fn aisling_grid_pulse_shader() -> ShaderSource {
1661    ShaderSource {
1662        name: "rae-aisling-grid-pulse",
1663        vertex: VERTEX,
1664        fragment: AISLING_GRID_PULSE_FRAGMENT,
1665        uniforms: COMMON_UNIFORMS,
1666    }
1667}
1668
1669pub fn all_shaders() -> Vec<ShaderSource> {
1670    vec![
1671        background_shader(),
1672        pane_shader(),
1673        prompt_shader(),
1674        aurora_shader(),
1675        knot_field_shader(),
1676        terminal_rain_shader(),
1677        flow_beams_shader(),
1678        ripple_shader(),
1679        bloom_glow_shader(),
1680        code_lens_shader(),
1681        reaction_diffusion_shader(),
1682        voronoi_crystal_shader(),
1683        plasma_graph_shader(),
1684        sdf_card_morph_shader(),
1685        metaball_card_shader(),
1686        google_aura_shader(),
1687        orbital_mesh_shader(),
1688        glass_caustic_shader(),
1689        liquid_chrome_shader(),
1690        aisling_blackhole_shader(),
1691        aisling_rings_shader(),
1692        aisling_fireworks_shader(),
1693        aisling_laser_etch_shader(),
1694        aisling_beams_shader(),
1695        aisling_synth_grid_shader(),
1696        aisling_spotlights_shader(),
1697        aisling_swarm_shader(),
1698        aisling_storm_shader(),
1699        aisling_vhs_shader(),
1700        aisling_waves_shader(),
1701        aisling_vortex_shader(),
1702        aisling_cascade_shader(),
1703        aisling_grid_pulse_shader(),
1704    ]
1705}
1706
1707pub fn shader_catalog() -> Vec<ShaderDescriptor> {
1708    vec![
1709        ShaderDescriptor {
1710            source: background_shader(),
1711            family: ShaderFamily::Background,
1712            description: "Curl-noise nebula with ring interference for full-window depth.",
1713            complexity: 7,
1714            animated: true,
1715        },
1716        ShaderDescriptor {
1717            source: pane_shader(),
1718            family: ShaderFamily::Panel,
1719            description: "Hex lattice pane surface with scanning rim light.",
1720            complexity: 4,
1721            animated: true,
1722        },
1723        ShaderDescriptor {
1724            source: prompt_shader(),
1725            family: ShaderFamily::Prompt,
1726            description: "Prompt beam field with animated caret energy.",
1727            complexity: 3,
1728            animated: true,
1729        },
1730        ShaderDescriptor {
1731            source: aurora_shader(),
1732            family: ShaderFamily::Background,
1733            description: "Layered aurora curtains for context and reference views.",
1734            complexity: 5,
1735            animated: true,
1736        },
1737        ShaderDescriptor {
1738            source: knot_field_shader(),
1739            family: ShaderFamily::Data,
1740            description: "Raymarched torus-knot field for high-energy focus states.",
1741            complexity: 9,
1742            animated: true,
1743        },
1744        ShaderDescriptor {
1745            source: terminal_rain_shader(),
1746            family: ShaderFamily::Code,
1747            description: "Terminal rain data stream for run and log surfaces.",
1748            complexity: 3,
1749            animated: true,
1750        },
1751        ShaderDescriptor {
1752            source: flow_beams_shader(),
1753            family: ShaderFamily::Flow,
1754            description: "Animated routed beam network for flow and routing lanes.",
1755            complexity: 5,
1756            animated: true,
1757        },
1758        ShaderDescriptor {
1759            source: ripple_shader(),
1760            family: ShaderFamily::Interaction,
1761            description: "Material-style click ripple field with two animated origins.",
1762            complexity: 4,
1763            animated: true,
1764        },
1765        ShaderDescriptor {
1766            source: bloom_glow_shader(),
1767            family: ShaderFamily::Interaction,
1768            description: "Soft bloom blobs for hover, focus, and elevated surfaces.",
1769            complexity: 4,
1770            animated: true,
1771        },
1772        ShaderDescriptor {
1773            source: code_lens_shader(),
1774            family: ShaderFamily::Code,
1775            description: "Code-line lens shimmer for transcript/code panes.",
1776            complexity: 5,
1777            animated: true,
1778        },
1779        ShaderDescriptor {
1780            source: reaction_diffusion_shader(),
1781            family: ShaderFamily::Background,
1782            description: "Procedural reaction-diffusion cells for organic loading states.",
1783            complexity: 6,
1784            animated: true,
1785        },
1786        ShaderDescriptor {
1787            source: voronoi_crystal_shader(),
1788            family: ShaderFamily::Panel,
1789            description: "Voronoi crystal facets for glassy command-palette surfaces.",
1790            complexity: 6,
1791            animated: true,
1792        },
1793        ShaderDescriptor {
1794            source: plasma_graph_shader(),
1795            family: ShaderFamily::Flow,
1796            description: "Plasma graph nodes and sparks for runtime visualizers.",
1797            complexity: 6,
1798            animated: true,
1799        },
1800        ShaderDescriptor {
1801            source: sdf_card_morph_shader(),
1802            family: ShaderFamily::Panel,
1803            description:
1804                "SDF whole-card morph between rounded cards, capsules, blobs, and ticket notches.",
1805            complexity: 8,
1806            animated: true,
1807        },
1808        ShaderDescriptor {
1809            source: metaball_card_shader(),
1810            family: ShaderFamily::Panel,
1811            description: "Metaball card topology that merges moving lobes into one liquid surface.",
1812            complexity: 6,
1813            animated: true,
1814        },
1815        ShaderDescriptor {
1816            source: google_aura_shader(),
1817            family: ShaderFamily::Interaction,
1818            description: "Google-style multicolor aura for focus and assistant activity states.",
1819            complexity: 6,
1820            animated: true,
1821        },
1822        ShaderDescriptor {
1823            source: orbital_mesh_shader(),
1824            family: ShaderFamily::Flow,
1825            description: "Orbital node mesh for runtime flow maps.",
1826            complexity: 5,
1827            animated: true,
1828        },
1829        ShaderDescriptor {
1830            source: glass_caustic_shader(),
1831            family: ShaderFamily::Panel,
1832            description: "Glass caustic surface for translucent elevated cards.",
1833            complexity: 5,
1834            animated: true,
1835        },
1836        ShaderDescriptor {
1837            source: liquid_chrome_shader(),
1838            family: ShaderFamily::Data,
1839            description: "Liquid chrome spectral body for high-energy hero surfaces.",
1840            complexity: 6,
1841            animated: true,
1842        },
1843        ShaderDescriptor {
1844            source: aisling_blackhole_shader(),
1845            family: ShaderFamily::Data,
1846            description:
1847                "Aisling-inspired gravity well with accretion rings and deterministic stars.",
1848            complexity: 7,
1849            animated: true,
1850        },
1851        ShaderDescriptor {
1852            source: aisling_rings_shader(),
1853            family: ShaderFamily::Interaction,
1854            description:
1855                "Aisling rings translated into elliptical orbit bands and resolving nodes.",
1856            complexity: 5,
1857            animated: true,
1858        },
1859        ShaderDescriptor {
1860            source: aisling_fireworks_shader(),
1861            family: ShaderFamily::Interaction,
1862            description:
1863                "Firework launch trails and burst rings for celebratory task completion states.",
1864            complexity: 6,
1865            animated: true,
1866        },
1867        ShaderDescriptor {
1868            source: aisling_laser_etch_shader(),
1869            family: ShaderFamily::Prompt,
1870            description: "Laser etch and sweep loader translated into hot diagonal scan beams.",
1871            complexity: 5,
1872            animated: true,
1873        },
1874        ShaderDescriptor {
1875            source: aisling_beams_shader(),
1876            family: ShaderFamily::Flow,
1877            description: "Crossing beam scanner based on Aisling's beams loader/effect timing.",
1878            complexity: 4,
1879            animated: true,
1880        },
1881        ShaderDescriptor {
1882            source: aisling_synth_grid_shader(),
1883            family: ShaderFamily::Panel,
1884            description: "Neon synth grid with perspective pulses and diagonal loader traces.",
1885            complexity: 5,
1886            animated: true,
1887        },
1888        ShaderDescriptor {
1889            source: aisling_spotlights_shader(),
1890            family: ShaderFamily::Interaction,
1891            description: "Three moving spotlights for hover, selected, and reveal choreography.",
1892            complexity: 4,
1893            animated: true,
1894        },
1895        ShaderDescriptor {
1896            source: aisling_swarm_shader(),
1897            family: ShaderFamily::Flow,
1898            description: "Swarming particles following a progress cursor for busy flow states.",
1899            complexity: 7,
1900            animated: true,
1901        },
1902        ShaderDescriptor {
1903            source: aisling_storm_shader(),
1904            family: ShaderFamily::Background,
1905            description:
1906                "Thunderstorm rain, lightning, and storm-flicker field for alert surfaces.",
1907            complexity: 5,
1908            animated: true,
1909        },
1910        ShaderDescriptor {
1911            source: aisling_vhs_shader(),
1912            family: ShaderFamily::Code,
1913            description: "VHS tape row jitter, tracking bands, scanlines, and block glitches.",
1914            complexity: 5,
1915            animated: true,
1916        },
1917        ShaderDescriptor {
1918            source: aisling_waves_shader(),
1919            family: ShaderFamily::Panel,
1920            description: "Layered wavefronts and foam sweeps for calm loading and stream states.",
1921            complexity: 4,
1922            animated: true,
1923        },
1924        ShaderDescriptor {
1925            source: aisling_vortex_shader(),
1926            family: ShaderFamily::Background,
1927            description: "Vortex loader translated into polar spiral arms and seeded particles.",
1928            complexity: 6,
1929            animated: true,
1930        },
1931        ShaderDescriptor {
1932            source: aisling_cascade_shader(),
1933            family: ShaderFamily::Code,
1934            description: "Cascade loader as falling blue drops with short deterministic trails.",
1935            complexity: 4,
1936            animated: true,
1937        },
1938        ShaderDescriptor {
1939            source: aisling_grid_pulse_shader(),
1940            family: ShaderFamily::Data,
1941            description: "Grid pulse loader as radial cell waves over a seeded dot matrix.",
1942            complexity: 4,
1943            animated: true,
1944        },
1945    ]
1946}
1947
1948#[cfg(test)]
1949mod tests {
1950    use super::*;
1951
1952    #[test]
1953    fn shader_catalog_names_are_unique() {
1954        let shaders = all_shaders();
1955        let mut names = shaders.iter().map(|shader| shader.name).collect::<Vec<_>>();
1956        names.sort_unstable();
1957        names.dedup();
1958
1959        assert_eq!(names.len(), shaders.len());
1960    }
1961
1962    #[test]
1963    fn all_shaders_expose_common_uniforms() {
1964        for shader in all_shaders() {
1965            assert_eq!(shader.uniforms, COMMON_UNIFORMS);
1966        }
1967    }
1968
1969    #[test]
1970    fn descriptor_catalog_matches_sources() {
1971        let descriptors = shader_catalog();
1972        let sources = all_shaders();
1973
1974        assert_eq!(descriptors.len(), sources.len());
1975        assert!(descriptors
1976            .iter()
1977            .all(|descriptor| descriptor.complexity > 0));
1978    }
1979}