// Geometric family: the interference of several plane waves at irrational // angles — a pattern with local symmetry that never actually repeats. // // Distinct from Moiré Grid (two periodic grids beating against each other), // Truchet Fold (a tiling, so a cell structure you can see) and Prism Bloom // (radial geometry around a centre): with five or seven waves the sum is // quasiperiodic. There is no tile, no cell and no centre, and the eye keeps // finding order that does not survive being looked at twice. That is a texture // the library could not previously make. // // Scaffolded by tools/new-scene.js. See HOWTO-visualizers.md. export const quasicrystal = { name: 'Quasicrystal', family: 'geometric', kind: 'fragment', traits: ['camera', 'style'], params: { waves: { type: 'int', range: [3, 11], default: 5, uniform: 'u_waves', bias: 'density' }, frequency: { type: 'float', range: [2, 26], default: 9, uniform: 'u_frequency', bias: 'density' }, speed: { type: 'float', range: [0.02, 0.7], default: 0.15, uniform: 'u_speed', bias: 'motion', rate: true }, contrast: { type: 'float', range: [0.5, 6], default: 2.0, uniform: 'u_contrast' }, threshold: { type: 'float', range: [0, 0.9], default: 0.35, uniform: 'u_threshold' }, glow: { type: 'float', range: [0, 1.5], default: 0.5, uniform: 'u_glow', bias: 'energy' }, breathe: { type: 'float', range: [0, 0.5], default: 0.15, uniform: 'u_breathe' }, palette: { type: 'palette', count: 5 }, }, reactive: { glow: { feature: 'bandHigh', amount: 0.35, response: 'smooth' }, threshold: { feature: 'bandLow', amount: 0.2, response: 'smooth' }, }, shader: ` vec4 scene(vec2 uv, vec2 p) { float t = u_time * u_speed + u_seed; p = sigFolded(sigCamera(p)); // Sum of N plane waves, each rotated by pi/N. When N is odd the angles are // incommensurate with any lattice, which is exactly why the result never // tiles — and why an even N looks disappointingly like a grid. float sum = 0.0; float n = max(float(u_waves), 1.0); float freq = u_frequency * (1.0 + sin(t * 0.5) * u_breathe); for (int i = 0; i < 11; i++) { if (i >= u_waves) break; float a = 3.14159265 * float(i) / n + t * 0.08; vec2 dir = vec2(cos(a), sin(a)); sum += cos(dot(p, dir) * freq + t * 1.7 + float(i) * 0.6); } float field = sum / n; // Contrast shapes the sum into either soft blobs or hard cells; the // threshold cuts it into the flat-topped plateaus that read as a lattice of // rosettes rather than as a ripple. float shaped = tanh(field * u_contrast); float plateau = smoothstep(u_threshold - 0.12, u_threshold + 0.12, shaped); vec3 col = mix(pal(0) * 0.08, palRamp(0.15 + field * 0.35), 0.5 + shaped * 0.5); col = mix(col, pal(2), plateau * 0.55); // Ridges: where the sum crosses zero, which is the aperiodic skeleton. float ridge = 1.0 - abs(shaped); col += pal(4) * pow(sat(ridge), 6.0) * u_glow; col += pal(3) * sigEdge(shaped) * u_glow * 0.3; col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.22); col += sigGrain(uv); return vec4(col, 1.0); } `, }; export default quasicrystal;