// Geometric family: two rotating line grids interfering. // // Moiré is a spatial-aliasing effect by nature, so this scene is the most likely // in the library to alias badly. Line width is held above a floor and scaled by // u_pixelScale, which is what keeps a 720p preview and a 4K export looking the // same rather than the preview shimmering. export const moireGrid = { name: 'Moiré Grid', family: 'geometric', kind: 'fragment', // Personality: see look/Personality.js. // Crisp line work: the track's surface grain would only fur the edges. texture: 0, consumes: ['ink'], traits: ['camera', 'style'], params: { // The subject: the song's protagonist standing in the field, with the // interference running at a different phase inside it. A window rather // than a shape laid on top — the pattern is still the picture, it just // has somewhere to be about, and the edge gives the eye a line to track. subject: { type: 'float', range: [0, 1], default: 0.7, uniform: 'u_subject' }, subjSize: { type: 'float', range: [0.2, 0.75], default: 0.42, uniform: 'u_subjSize' }, density: { type: 'float', range: [6, 60], default: 22, uniform: 'u_density', bias: 'density' }, offset: { type: 'float', range: [0.0, 0.5], default: 0.08, uniform: 'u_offset' }, rotate: { type: 'float', range: [0, 0.25], default: 0.04, uniform: 'u_rotate', bias: 'motion', rate: true }, // Named u_lineWidth, not u_width: the shader contract already declares // `uniform float u_width` for stereo width, and a colliding name is a // redefinition error that renders the scene as a black frame. width: { type: 'float', range: [0.06, 0.5], default: 0.2, uniform: 'u_lineWidth' , slowAxis: true }, warp: { type: 'float', range: [0, 1], default: 0.25, uniform: 'u_warp' }, palette: { type: 'palette', count: 4 }, }, reactive: { offset: { feature: 'bandLow', amount: 0.35 }, warp: { feature: 'flux', amount: 0.2, response: 'smooth' }, }, shader: ` // Anti-aliased line grid: the smoothstep edge is widened by the screen-space // derivative, so lines stay a consistent visual weight at any resolution. float grid(vec2 q, float density, float width) { vec2 g = q * density; vec2 f = abs(fract(g) - 0.5); float d = min(f.x, f.y); float aa = max(fwidth(d), 0.001); return smoothstep(width * 0.5 + aa, width * 0.5 - aa, d); } vec4 scene(vec2 uv, vec2 p) { float t = u_time * u_rotate + u_seed; p = sigFolded(sigCamera(p)); vec2 warp = vec2(fbm(p * 1.5 + t, 3), fbm(p * 1.5 - t, 3)) - 0.5; vec2 q = p + warp * u_warp; // Drawn in the track's hand: its line weight scales this scene's. float weight = u_lineWidth * (0.5 + u_sigLine); float a = grid(rot(t * 6.28318530718) * q, u_density, weight); float b = grid(rot(-t * 6.28318530718 + u_offset * 3.14159) * (q + u_offset), u_density, weight); // The subject does something TO the field, and which thing is the song's // decision rather than this scene's — the same form punching a hole, // bending the grid or running it at another rate are three different // videos. See Identity.IMPACTS. float d = subjectSDF(p, u_subjSize); float inside = smoothstep(0.01, -0.01, d) * u_subject; // WARP bends the pattern around the form instead of replacing it inside, // so it is applied to the coordinate everything below is drawn from. if (impactIs(1.0)) q = subjectWarp(q, u_subjSize, u_subject * 1.2); vec2 qi = q + vec2(u_offset * 0.7, -u_offset * 0.4); float ai = grid(rot(t * 6.28318530718 * 1.35) * qi, u_density * 1.18, weight); float bi = grid(rot(-t * 6.28318530718 * 0.7 + u_offset * 3.14159) * (qi + u_offset), u_density * 0.86, weight); // The interference term is the point: where both grids land, it peaks. float interference = a * b; float either = max(a, b); if (impactIs(0.0)) { // shift: a different beat inside interference = mix(interference, ai * bi, inside); either = mix(either, max(ai, bi), inside); } else if (impactIs(2.0)) { // punch: the field stops at the form interference *= 1.0 - inside; either *= 1.0 - inside; } else if (impactIs(3.0)) { // morph: one grid survives inside interference = mix(interference, a * 0.35, inside); either = mix(either, a, inside); } else if (impactIs(4.0)) { // overlay: the form reads as solid either = max(either, inside); interference = max(interference, inside * 0.6); } vec3 col = pal(0) * 0.05; col += pal(1) * either * 0.35; col += pal(2) * interference * (0.8 + 0.35); // The rim, so the form has an edge to follow rather than only a change of // texture. Drawn in the song's hand like everything else. col = mix(col, pal(3), inkStroke(d) * u_subject); col *= 0.6 + 0.4 * exp(-dot(p, p) * 0.3); return vec4(inkValue(col), 1.0); } `, }; export default moireGrid;