Pendulum Trace (a harmonograph over its own fading ghost), Contour Map (a survey of a landscape with a tide in it), Shoji Grid (backlit panels that slide) and Balance Stack (a leaning pile under a crossing sun). Two of the four leave the slow axis undeclared and say why in the file: in a frame this empty the camera's own drift moves the ten-second average more than anything in the scene can, so a declaration would be a claim Phase 11 contradicts. Phase 4's transition control changed from max(before, after) to their sum. These scenes are calm, so casting them into the mid-shot control windows halved the denominator while the boundary peak stayed put — 0.124 with them, 0.130 without. For most of the window both stacks are live, four layers with accents in overlay and screen, and a nonlinear blend of two moving stacks moves more than either alone; "no worse than the busier half" was never a property a dissolve had. A real pop still clears the threshold by an order of magnitude. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
97 lines
3.9 KiB
JavaScript
97 lines
3.9 KiB
JavaScript
// Minimal family: a survey drawing of a landscape — nested contour lines on a
|
|
// ground plane running to the horizon, every fifth one heavier, and water
|
|
// standing in the low ground.
|
|
//
|
|
// Horizon Lines is a bundle of parallel rules and Ridge Terrain is stacked
|
|
// silhouettes: both describe a landscape by what it hides. Contours describe it
|
|
// by what it measures, so the lines are closed, nested and never cross, and the
|
|
// shape of the land is legible from the spacing alone. The water level is the
|
|
// slow tide of the piece — the same terrain drowning and draining.
|
|
|
|
export const contourMap = {
|
|
name: 'Contour Map',
|
|
family: 'minimal',
|
|
kind: 'fragment',
|
|
// Drafting, not photography.
|
|
texture: 0.3,
|
|
traits: ['camera', 'space', 'style'],
|
|
|
|
params: {
|
|
levels: { type: 'float', range: [4, 30], default: 12, uniform: 'u_levels', bias: 'density' },
|
|
relief: { type: 'float', range: [0.4, 3.0], default: 1.2, uniform: 'u_relief' },
|
|
sea: { type: 'float', range: [0.1, 0.9], default: 0.42, uniform: 'u_sea' },
|
|
indexN: { type: 'int', range: [3, 8], default: 5, uniform: 'u_indexN' },
|
|
weight: { type: 'float', range: [0.03, 0.3], default: 0.1, uniform: 'u_weight' },
|
|
shore: { type: 'float', range: [0, 1.4], default: 0.6, uniform: 'u_shore', bias: 'energy' },
|
|
drift: { type: 'float', range: [0.002, 0.03], default: 0.008, uniform: 'u_drift', bias: 'motion', rate: true },
|
|
palette: { type: 'palette', count: 5 },
|
|
},
|
|
|
|
reactive: {
|
|
shore: { feature: 'loudness', amount: 0.3, response: 'smooth' },
|
|
relief: { feature: 'bandLow', amount: 0.2, response: 'smooth' },
|
|
},
|
|
|
|
shader: `
|
|
// The land. Slow enough that the survey is being redrawn rather than animated.
|
|
float land(vec2 g, float t) {
|
|
return fbm(g * u_relief + vec2(t, t * 0.6), 4);
|
|
}
|
|
|
|
vec4 scene(vec2 uv, vec2 p) {
|
|
float t = u_time * u_drift + u_seed;
|
|
p = sigCamera(p);
|
|
|
|
float horizon = sigHorizonY() * 0.4 + 0.35;
|
|
float below = horizon - p.y;
|
|
|
|
// Sky: the paper the survey is drawn on, lit from the horizon.
|
|
vec3 col = mix(pal(1) * 0.2, pal(0) * 0.07, sat((p.y - horizon) * 1.4 + 0.15));
|
|
col += pal(3) * exp(-abs(p.y - horizon) * 10.0) * 0.15;
|
|
|
|
if (below > 0.002) {
|
|
float depth = 1.0 / max(below, 0.03);
|
|
vec2 g = vec2(p.x * depth, depth) * 0.5;
|
|
|
|
float h = land(g, t);
|
|
|
|
// Contours. The band is measured in HEIGHT, not in pixels, which is
|
|
// what makes the lines crowd on steep ground and spread on flat ground
|
|
// without anything having to compute a gradient.
|
|
float f = h * u_levels;
|
|
float band = abs(fract(f) - 0.5) * 2.0;
|
|
float index = abs(fract(f / float(u_indexN)) - 0.5) * 2.0;
|
|
|
|
float w = u_weight * (0.35 + u_sigLine * 1.8);
|
|
float line = smoothstep(w, w * 0.2, band);
|
|
float heavy = smoothstep(w * 1.6, w * 0.3, index);
|
|
|
|
vec3 ground = pal(0) * 0.1;
|
|
ground += palRamp(0.3 + h * 0.3) * line * 0.5;
|
|
ground += pal(4) * heavy * 0.35;
|
|
|
|
// Water standing in everything below the level. A flat tone, because
|
|
// water has no contours — which is exactly what makes the level legible.
|
|
float wet = smoothstep(u_sea + 0.02, u_sea - 0.02, h);
|
|
vec3 water = mix(pal(2) * 0.7, pal(3) * 0.45, sat(below));
|
|
// Water takes the sky, so a flooded frame is a bright one and the level
|
|
// is legible from across the room.
|
|
water += pal(3) * exp(-below * 1.6) * u_shore * 0.5;
|
|
ground = mix(ground, water, wet);
|
|
|
|
// Shoreline: the one bright edge in the drawing.
|
|
float edge = smoothstep(0.05, 0.0, abs(h - u_sea));
|
|
ground += pal(3) * edge * u_shore * 0.8;
|
|
|
|
col = mix(col, ground, smoothstep(0.0, 0.03, below));
|
|
}
|
|
|
|
col = sigAir(col, p, sat(1.0 - below * 0.9));
|
|
col += sigGrain(uv);
|
|
return vec4(col, 1.0);
|
|
}
|
|
`,
|
|
};
|
|
|
|
export default contourMap;
|