Finish the migration: all 65 scenes on the identity artifacts
Two helpers made the bulk of it mechanical. `inkStroke` is a drop-in for
sigEdge — the same line at the identity's weight rather than the track's — and
`castForm` is a drop-in for sigForm, same signature so call sites do not change
shape. With those in place the substitution table is one-to-one:
sigForm( -> castForm( sigShape( -> castMain( sigEdge( -> inkStroke(
Forty-seven scenes went through that pass in one run: twenty-six take the cast
and the ink, twenty-one take the ink alone. Then the gate ran over all sixty-five
and found three the pass had broken, which is the entire reason it exists.
Spectrum Sculpture rendered pure black. It had been using sigShape as a RADIAL
METRIC rather than drawing it, and the cast carries notches and a hollow — an
annulus used as a radius turns a sculpture inside out. Reverted to sigShape and
dropped to ink only. The lesson generalises: a scene that reads a form as
geometry is not a scene that draws it, and the classifier cannot tell those
apart from the source.
Eclipse Field stopped honouring its `style` trait. It opts out of surface grain,
so sigEdge was its only style evidence, and the ink replaced it. The trait claim
is now dropped — and so is the lint change that had let inkMask count as style
evidence, which was wrong and was hiding exactly this. A trait is a property of
the track a scene may honour; an artifact is content it draws. Taking the ink
says nothing about whether a scene responds to u_sigLine.
Circuit Bloom went empty at the bottom of its `grown` range, where the pads were
carried by a hairline and the ink's stroke is thinner than the edge it replaced.
Now filled as well as stroked.
Also: the backtick check now covers every shader literal rather than only the
preamble, because a mechanical pass over sixty files reintroduced one
immediately. Three rounds lost to that typo is enough.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
e5bb7d77e0
commit
2d3ed8eb02
@ -452,6 +452,33 @@ float inkMask(float d, vec2 uv) {
|
|||||||
return clamp(max(fillA, line), 0.0, 1.0);
|
return clamp(max(fillA, line), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outline only, in the song's hand. The drop-in replacement for sigEdge.
|
||||||
|
*
|
||||||
|
* sigEdge draws a line at the track's line weight; this draws it at the
|
||||||
|
* identity's, which is the same idea one layer up. Kept separate from inkMask
|
||||||
|
* because a scene that only ever wanted an edge should not suddenly acquire a
|
||||||
|
* fill when it migrates.
|
||||||
|
*/
|
||||||
|
float inkStroke(float d) {
|
||||||
|
float soft = mix(0.03, 0.0015, clamp(u_inkEdge, 0.0, 1.0));
|
||||||
|
float w = 0.004 + u_inkWeight * 0.055;
|
||||||
|
return smoothstep(w + soft, w - soft, abs(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The protagonist as a filled, inked mask at a point. Replaces sigForm.
|
||||||
|
*
|
||||||
|
* Same signature as the thing it supersedes so the substitution is mechanical
|
||||||
|
* across the library — see MIGRATION.md. uv is recomputed here rather than
|
||||||
|
* passed, so the call site does not have to change shape.
|
||||||
|
*/
|
||||||
|
float castForm(vec2 p, vec2 centre, float size) {
|
||||||
|
float s = max(size, 1e-3);
|
||||||
|
vec2 uv = vec2(p.x / u_aspect, p.y) * 0.5 + 0.5;
|
||||||
|
return inkMask(castMain((p - centre) / s) * s, uv);
|
||||||
|
}
|
||||||
|
|
||||||
/** The track's value structure. Off unless the identity asked for it. */
|
/** The track's value structure. Off unless the identity asked for it. */
|
||||||
vec3 inkValue(vec3 col) {
|
vec3 inkValue(vec3 col) {
|
||||||
if (u_inkPosterize < 1.5) return col;
|
if (u_inkPosterize < 1.5) return col;
|
||||||
|
|||||||
@ -17,6 +17,7 @@ export const analogWow = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.9,
|
texture: 0.9,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -46,7 +47,7 @@ vec3 programme(vec2 q, float t) {
|
|||||||
col += pal(4) * smoothstep(0.85, 1.0, sat(0.5 + 0.5 * sin(q.x * 3.0 - t * 1.3))) * 0.25;
|
col += pal(4) * smoothstep(0.85, 1.0, sat(0.5 + 0.5 * sin(q.x * 3.0 - t * 1.3))) * 0.25;
|
||||||
// The boundary between bands is drawn in the track's weight, so even a
|
// The boundary between bands is drawn in the track's weight, so even a
|
||||||
// damaged signal is damaged in the video's own hand.
|
// damaged signal is damaged in the video's own hand.
|
||||||
col += pal(4) * sigEdge(fract(band) - 0.5) * (0.15 + u_sigLine * 0.9);
|
col += pal(4) * inkStroke(fract(band) - 0.5) * (0.15 + u_sigLine * 0.9);
|
||||||
return col * 0.7;
|
return col * 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, pal(2) * hash12(vec2(uv.x * 300.0, floor(t * 12.0))), sw * 0.6);
|
col = mix(col, pal(2) * hash12(vec2(uv.x * 300.0, floor(t * 12.0))), sw * 0.6);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const apollonianGasket = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Drawn geometry; grain only muddies the small discs.
|
// Drawn geometry; grain only muddies the small discs.
|
||||||
texture: 0.3,
|
texture: 0.3,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -88,14 +89,14 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
vec3 col = pal(0) * 0.06;
|
vec3 col = pal(0) * 0.06;
|
||||||
col += palRamp(gen) * edge * (0.55 + u_rim * 0.7);
|
col += palRamp(gen) * edge * (0.55 + u_rim * 0.7);
|
||||||
col += palRamp(gen + 0.25) * glow * u_rim * 0.4;
|
col += palRamp(gen + 0.25) * glow * u_rim * 0.4;
|
||||||
col += pal(4) * sigEdge(d) * 0.5;
|
col += pal(4) * inkStroke(d) * 0.5;
|
||||||
|
|
||||||
// Fill the interiors faintly so the discs are objects and not just outlines.
|
// Fill the interiors faintly so the discs are objects and not just outlines.
|
||||||
col += palRamp(gen + 0.5) * smoothstep(0.0, -0.06, d) * 0.12;
|
col += palRamp(gen + 0.5) * smoothstep(0.0, -0.06, d) * 0.12;
|
||||||
|
|
||||||
col *= 0.7 + 0.3 * exp(-dot(p, p) * 0.2);
|
col *= 0.7 + 0.3 * exp(-dot(p, p) * 0.2);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,6 +21,7 @@ export const aqueductMarch = {
|
|||||||
family: 'structural',
|
family: 'structural',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.9,
|
texture: 0.9,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -61,7 +62,7 @@ float tier(vec2 q, float bays, float top, float bottom, float shift) {
|
|||||||
|
|
||||||
// The opening sits low in the tier, leaving a solid band above it to carry
|
// The opening sits low in the tier, leaving a solid band above it to carry
|
||||||
// the next tier — which is the whole structural point of an aqueduct.
|
// the next tier — which is the whole structural point of an aqueduct.
|
||||||
float hole = sigShape(local) * min(cw, ch) * k;
|
float hole = castMain(local) * min(cw, ch) * k;
|
||||||
return smoothstep(-0.004, 0.004, hole);
|
return smoothstep(-0.004, 0.004, hole);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
vec3 masonry = mix(pal(2) * 0.35, pal(4) * 0.8, sat(q.x * 0.4 + 0.5));
|
vec3 masonry = mix(pal(2) * 0.35, pal(4) * 0.8, sat(q.x * 0.4 + 0.5));
|
||||||
masonry *= 0.7 + (0.15 + u_sigLine * 0.5) * course;
|
masonry *= 0.7 + (0.15 + u_sigLine * 0.5) * course;
|
||||||
masonry += pal(3) * u_sunlight * 0.22 * sat(q.x * 0.5 + 0.5);
|
masonry += pal(3) * u_sunlight * 0.22 * sat(q.x * 0.5 + 0.5);
|
||||||
masonry += pal(4) * sigEdge(0.5 - abs(fract(q.x * u_bays) - 0.5) - 0.03) * (0.1 + u_sigLine * 0.9);
|
masonry += pal(4) * inkStroke(0.5 - abs(fract(q.x * u_bays) - 0.5) - 0.03) * (0.1 + u_sigLine * 0.9);
|
||||||
|
|
||||||
float hazed = mix(1.0, 0.55, fk * u_recede);
|
float hazed = mix(1.0, 0.55, fk * u_recede);
|
||||||
col = mix(col, masonry * hazed, stone * base);
|
col = mix(col, masonry * hazed, stone * base);
|
||||||
@ -118,7 +119,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = sigAir(col, p, smoothstep(-0.2, 0.9, p.y - horizon));
|
col = sigAir(col, p, smoothstep(-0.2, 0.9, p.y - horizon));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const auroraVeil = {
|
|||||||
name: 'Aurora Veil',
|
name: 'Aurora Veil',
|
||||||
family: 'flow',
|
family: 'flow',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.x)));
|
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.x)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,6 +17,7 @@ export const balanceStack = {
|
|||||||
name: 'Balance Stack',
|
name: 'Balance Stack',
|
||||||
family: 'minimal',
|
family: 'minimal',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -102,7 +103,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
x += u_lean * size * 1.6 + sin(t * 1.3 + fi * 0.7) * 0.012 * fi;
|
x += u_lean * size * 1.6 + sin(t * 1.3 + fi * 0.7) * 0.012 * fi;
|
||||||
|
|
||||||
vec2 at = vec2(x, y);
|
vec2 at = vec2(x, y);
|
||||||
float d = sigShape((p - at) / size) * size;
|
float d = castMain((p - at) / size) * size;
|
||||||
|
|
||||||
// Body: shaded across the form, so it has a lit side and a dark side.
|
// Body: shaded across the form, so it has a lit side and a dark side.
|
||||||
float lit = sat(dot(normalize(p - at + 1e-4), lightDir) * 0.5 + 0.5);
|
float lit = sat(dot(normalize(p - at + 1e-4), lightDir) * 0.5 + 0.5);
|
||||||
@ -110,13 +111,13 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, body, smoothstep(0.004, -0.004, d));
|
col = mix(col, body, smoothstep(0.004, -0.004, d));
|
||||||
|
|
||||||
// Rim: the sun catching the edge, in the track's line weight.
|
// Rim: the sun catching the edge, in the track's line weight.
|
||||||
col += pal(4) * sigEdge(d) * (0.3 + u_rim * 0.9) * (0.4 + lit * 0.8);
|
col += pal(4) * inkStroke(d) * (0.3 + u_rim * 0.9) * (0.4 + lit * 0.8);
|
||||||
y += size;
|
y += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.1, 1.5, abs(p.x) * 0.7 + sat(above * 0.5)));
|
col = sigAir(col, p, smoothstep(0.1, 1.5, abs(p.x) * 0.7 + sat(above * 0.5)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const blockMosh = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -74,7 +75,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += pal(2) * u_burst * (0.5 + 0.5 * blk) * (0.5 + 0.5 * beat);
|
col += pal(2) * u_burst * (0.5 + 0.5 * blk) * (0.5 + 0.5 * beat);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const cargoBelt = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -65,11 +66,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
if (rnd > u_gap) {
|
if (rnd > u_gap) {
|
||||||
vec2 local = vec2((withinCell - 0.5) * 2.0, dy / max(span * 0.5, 1e-3));
|
vec2 local = vec2((withinCell - 0.5) * 2.0, dy / max(span * 0.5, 1e-3));
|
||||||
float size = u_crateSize * (0.7 + rnd * 0.5);
|
float size = u_crateSize * (0.7 + rnd * 0.5);
|
||||||
float d = sigShape(local / max(size, 1e-3)) * size;
|
float d = castMain(local / max(size, 1e-3)) * size;
|
||||||
|
|
||||||
vec3 crateColor = pal(int(mod(cell + fi, 4.0)) + 1);
|
vec3 crateColor = pal(int(mod(cell + fi, 4.0)) + 1);
|
||||||
col = mix(col, crateColor * (0.35 + rnd * 0.5), smoothstep(0.02, -0.02, d));
|
col = mix(col, crateColor * (0.35 + rnd * 0.5), smoothstep(0.02, -0.02, d));
|
||||||
col += crateColor * sigEdge(d) * (0.4 + u_lamp * 0.5);
|
col += crateColor * inkStroke(d) * (0.4 + u_lamp * 0.5);
|
||||||
|
|
||||||
// Lamp on a minority of crates, pulsing on the beat. Local, not
|
// Lamp on a minority of crates, pulsing on the beat. Local, not
|
||||||
// whole-frame: a per-crate blink is not a flash.
|
// whole-frame: a per-crate blink is not a flash.
|
||||||
@ -82,7 +83,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const cellDivide = {
|
|||||||
name: 'Cell Divide',
|
name: 'Cell Divide',
|
||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -95,13 +96,13 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Nucleus, in the track's signature form.
|
// Nucleus, in the track's signature form.
|
||||||
if (u_nucleus > 0.01) {
|
if (u_nucleus > 0.01) {
|
||||||
float size = u_nucleus * 0.35;
|
float size = u_nucleus * 0.35;
|
||||||
float d = sigShape((p - nearestAt) / max(size, 1e-3)) * size;
|
float d = castMain((p - nearestAt) / max(size, 1e-3)) * size;
|
||||||
col = mix(col, pal(1), smoothstep(0.008, -0.008, d) * 0.85);
|
col = mix(col, pal(1), smoothstep(0.008, -0.008, d) * 0.85);
|
||||||
col += pal(2) * sigEdge(d) * (0.35 + u_glow * 0.4);
|
col += pal(2) * inkStroke(d) * (0.35 + u_glow * 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const circuitBloom = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -91,13 +92,17 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
// Pads sit where both traces meet, stamped in the signature form.
|
// Pads sit where both traces meet, stamped in the signature form.
|
||||||
if (horizontal > 0.5 && vertical > 0.5 && rnd2 > 1.0 - u_pads) {
|
if (horizontal > 0.5 && vertical > 0.5 && rnd2 > 1.0 - u_pads) {
|
||||||
float d = sigShape(f / max(u_padSize, 1e-3)) * u_padSize;
|
float d = castMain(f / max(u_padSize, 1e-3)) * u_padSize;
|
||||||
col += pal(2) * smoothstep(0.01, -0.01, d) * reach * 0.7;
|
col += pal(2) * smoothstep(0.01, -0.01, d) * reach * 0.7;
|
||||||
col += pal(3) * sigEdge(d) * reach * (0.4 + u_pulse * 0.4);
|
// Filled as well as stroked. At the bottom of the 'grown' range the pads
|
||||||
|
// were a hairline and nothing else, and the ink's stroke can be thinner
|
||||||
|
// than the edge it replaced — which left the frame empty at grown=0.25.
|
||||||
|
col = mix(col, pal(3), inkMask(d, uv) * reach * 0.6);
|
||||||
|
col += pal(3) * inkStroke(d) * reach * (0.4 + u_pulse * 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export const classicWave = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// Smooth concentric colour: grain only mutes the ramp it is built on.
|
// Smooth concentric colour: grain only mutes the ramp it is built on.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -38,7 +39,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
p = sigCamera(p);
|
p = sigCamera(p);
|
||||||
// The rings take the track's signature form: round tracks get circles,
|
// The rings take the track's signature form: round tracks get circles,
|
||||||
// hexagonal tracks get hexagonal rings, and it costs one call.
|
// hexagonal tracks get hexagonal rings, and it costs one call.
|
||||||
float d = sigShape(p) + 1.0;
|
float d = castMain(p) + 1.0;
|
||||||
float angle = atan(p.y, p.x);
|
float angle = atan(p.y, p.x);
|
||||||
float t = u_time * u_speed + u_seed;
|
float t = u_time * u_speed + u_seed;
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col *= 0.6 + 0.4 * (1.0 - smoothstep(0.8, 1.8, d));
|
col *= 0.6 + 0.4 * (1.0 - smoothstep(0.8, 1.8, d));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
|
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export const curlFlow = {
|
|||||||
family: 'flow',
|
family: 'flow',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -81,7 +82,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col *= 0.6 + 0.4 * exp(-dot(p, p) * 0.35);
|
col *= 0.6 + 0.4 * exp(-dot(p, p) * 0.35);
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export const dataAisle = {
|
|||||||
family: 'structural',
|
family: 'structural',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.6,
|
texture: 0.6,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -62,7 +63,7 @@ vec3 wall(vec2 at, float side, float t, float lightAmount) {
|
|||||||
float bright = mix(0.25, 1.0, busy);
|
float bright = mix(0.25, 1.0, busy);
|
||||||
|
|
||||||
col += palRamp(0.55 + id * 0.35) * led * bright * lightAmount * 1.8;
|
col += palRamp(0.55 + id * 0.35) * led * bright * lightAmount * 1.8;
|
||||||
col += pal(4) * sigEdge(seam - seamW) * (0.15 + u_sigLine * 0.9);
|
col += pal(4) * inkStroke(seam - seamW) * (0.15 + u_sigLine * 0.9);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, pal(1) * 0.12, sat(far * u_haze));
|
col = mix(col, pal(1) * 0.12, sat(far * u_haze));
|
||||||
col = sigAir(col, p, far);
|
col = sigAir(col, p, far);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export const drosteFeedback = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.5,
|
texture: 0.5,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -54,7 +55,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
vec3 col = pal(0) * 0.05;
|
vec3 col = pal(0) * 0.05;
|
||||||
col += palRamp(0.2 + fbm(p * 2.0 + t, 3) * 0.2) * smoothstep(0.02, -0.02, ring) * (0.5 + u_bloom * 0.8);
|
col += palRamp(0.2 + fbm(p * 2.0 + t, 3) * 0.2) * smoothstep(0.02, -0.02, ring) * (0.5 + u_bloom * 0.8);
|
||||||
col += pal(4) * sigEdge(ring) * (0.3 + u_bloom * 0.9);
|
col += pal(4) * inkStroke(ring) * (0.3 + u_bloom * 0.9);
|
||||||
col += pal(3) * exp(-abs(d) * 9.0) * u_bloom * 0.35;
|
col += pal(3) * exp(-abs(d) * 9.0) * u_bloom * 0.35;
|
||||||
|
|
||||||
// The loop: read the previous frame from a slightly LARGER, slightly turned
|
// The loop: read the previous frame from a slightly LARGER, slightly turned
|
||||||
@ -77,7 +78,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Vignette, which also stops the corner content being recycled forever.
|
// Vignette, which also stops the corner content being recycled forever.
|
||||||
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.35);
|
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.35);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const dustChamber = {
|
|||||||
name: 'Dust Chamber',
|
name: 'Dust Chamber',
|
||||||
family: 'minimal',
|
family: 'minimal',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -77,13 +78,13 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
float lit = exp(-pow((at.x - axis) / max(halfWidth, 1e-3), 2.0) * 2.0);
|
float lit = exp(-pow((at.x - axis) / max(halfWidth, 1e-3), 2.0) * 2.0);
|
||||||
float pulse = 0.55 + 0.45 * sin(t * 2.0 + s * 3.0);
|
float pulse = 0.55 + 0.45 * sin(t * 2.0 + s * 3.0);
|
||||||
float m = sigForm(p, at, u_moteSize * (0.6 + hash11(s + 3.3)));
|
float m = castForm(p, at, u_moteSize * (0.6 + hash11(s + 3.3)));
|
||||||
col += pal(3) * m * lit * pulse * (0.5 + beam);
|
col += pal(3) * m * lit * pulse * (0.5 + beam);
|
||||||
}
|
}
|
||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.5, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.5, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,7 +18,12 @@ export const eclipseField = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Crisp line work: the track's surface grain would only fur the edges.
|
// Crisp line work: the track's surface grain would only fur the edges.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
consumes: ['cast', 'ink'],
|
||||||
|
// No `style`: this scene opts out of surface grain (texture: 0) and its only
|
||||||
|
// other style evidence was sigEdge, which the migration replaced with the
|
||||||
|
// ink. Traits and artifacts are different layers, so taking the ink does not
|
||||||
|
// earn the trait back. See MIGRATION.md.
|
||||||
|
traits: ['shape', 'camera', 'space'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
size: { type: 'float', range: [0.2, 0.85], default: 0.45, uniform: 'u_size' },
|
size: { type: 'float', range: [0.2, 0.85], default: 0.45, uniform: 'u_size' },
|
||||||
@ -47,7 +52,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
vec2 discAt = vec2(0.0, sigHorizonY() * 0.25);
|
vec2 discAt = vec2(0.0, sigHorizonY() * 0.25);
|
||||||
|
|
||||||
// Distance to the occluder's edge, in the track's form.
|
// Distance to the occluder's edge, in the track's form.
|
||||||
float d = sigShape((p - discAt) / max(u_size, 1e-3)) * u_size;
|
float d = castMain((p - discAt) / max(u_size, 1e-3)) * u_size;
|
||||||
|
|
||||||
// The source behind it.
|
// The source behind it.
|
||||||
float toLight = length(p - lightAt);
|
float toLight = length(p - lightAt);
|
||||||
@ -76,11 +81,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
// The occluder: not pure black, so it reads as an object rather than a hole.
|
// The occluder: not pure black, so it reads as an object rather than a hole.
|
||||||
col = mix(col, pal(0) * 0.12, smoothstep(0.004, -0.004, d));
|
col = mix(col, pal(0) * 0.12, smoothstep(0.004, -0.004, d));
|
||||||
col += pal(3) * sigEdge(d) * (0.4 + u_corona * 0.5);
|
col += pal(3) * inkStroke(d) * (0.4 + u_corona * 0.5);
|
||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export const flora = {
|
|||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -48,7 +49,7 @@ float petal(vec2 p, vec2 node, vec2 dir, float len, float width) {
|
|||||||
float across = dot(off, perp);
|
float across = dot(off, perp);
|
||||||
float taper = 0.6 + 0.4 * sat(along / max(len, 1e-3));
|
float taper = 0.6 + 0.4 * sat(along / max(len, 1e-3));
|
||||||
vec2 q = vec2(along / max(len, 1e-3), across / max(width * taper, 1e-3));
|
vec2 q = vec2(along / max(len, 1e-3), across / max(width * taper, 1e-3));
|
||||||
float form = sigForm(q * 0.5, vec2(0.0), 0.5);
|
float form = castForm(q * 0.5, vec2(0.0), 0.5);
|
||||||
float clip = smoothstep(0.0, -0.1, along) * smoothstep(len + 0.12, len * 0.72, along);
|
float clip = smoothstep(0.0, -0.1, along) * smoothstep(len + 0.12, len * 0.72, along);
|
||||||
return form * clip;
|
return form * clip;
|
||||||
}
|
}
|
||||||
@ -105,13 +106,13 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
for (int k = 0; k < 6; k++) {
|
for (int k = 0; k < 6; k++) {
|
||||||
float a = 6.2831853 * (float(k) + 0.5) / 6.0 + s;
|
float a = 6.2831853 * (float(k) + 0.5) / 6.0 + s;
|
||||||
vec2 off = vec2(cos(a), sin(a)) * u_leaf * (0.30 + 0.2 * beat);
|
vec2 off = vec2(cos(a), sin(a)) * u_leaf * (0.30 + 0.2 * beat);
|
||||||
bloom += sigForm(p - vec2(tipX, tipY), off, u_leaf * 0.5);
|
bloom += castForm(p - vec2(tipX, tipY), off, u_leaf * 0.5);
|
||||||
}
|
}
|
||||||
col = mix(col, pal(2), sat(bloom) * u_bud * (0.6 + 0.4 * beat));
|
col = mix(col, pal(2), sat(bloom) * u_bud * (0.6 + 0.4 * beat));
|
||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export const gateCorridor = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -62,7 +63,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
float phase = fract((fi / float(u_gates)) + t);
|
float phase = fract((fi / float(u_gates)) + t);
|
||||||
float scale = u_aperture * exp(phase * 3.2) * 0.35;
|
float scale = u_aperture * exp(phase * 3.2) * 0.35;
|
||||||
|
|
||||||
float d = abs(sigShape(q / max(scale, 1e-3)) * max(scale, 1e-3));
|
float d = abs(castMain(q / max(scale, 1e-3)) * max(scale, 1e-3));
|
||||||
|
|
||||||
// Near gates are drawn thicker and brighter: the only depth cue that
|
// Near gates are drawn thicker and brighter: the only depth cue that
|
||||||
// matters once the geometry is right.
|
// matters once the geometry is right.
|
||||||
@ -83,7 +84,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = sigAir(col, p, 1.0 - smoothstep(0.0, 1.2, length(q)));
|
col = sigAir(col, p, 1.0 - smoothstep(0.0, 1.2, length(q)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,6 +17,7 @@ export const girderLattice = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Crisp line work: the track's surface grain would only fur the edges.
|
// Crisp line work: the track's surface grain would only fur the edges.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -58,7 +59,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
if (above <= 0.001) {
|
if (above <= 0.001) {
|
||||||
col = sigAir(col, p, 1.0);
|
col = sigAir(col, p, 1.0);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float best = 1e3;
|
float best = 1e3;
|
||||||
@ -94,9 +95,9 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (u_plate > 0.004) {
|
if (u_plate > 0.004) {
|
||||||
float pd = sigShape((p - vec2(halfW0, y0)) / u_plate) * u_plate;
|
float pd = castMain((p - vec2(halfW0, y0)) / u_plate) * u_plate;
|
||||||
plateHit = min(plateHit, pd);
|
plateHit = min(plateHit, pd);
|
||||||
pd = sigShape((p - vec2(-halfW0, y0)) / u_plate) * u_plate;
|
pd = castMain((p - vec2(-halfW0, y0)) / u_plate) * u_plate;
|
||||||
plateHit = min(plateHit, pd);
|
plateHit = min(plateHit, pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
float steel = smoothstep(weight, weight * 0.3, best);
|
float steel = smoothstep(weight, weight * 0.3, best);
|
||||||
|
|
||||||
col = mix(col, pal(2) * (0.3 + above * 0.5), steel);
|
col = mix(col, pal(2) * (0.3 + above * 0.5), steel);
|
||||||
col += pal(3) * sigEdge(best - weight) * 0.4;
|
col += pal(3) * inkStroke(best - weight) * 0.4;
|
||||||
|
|
||||||
// Joint plates.
|
// Joint plates.
|
||||||
col = mix(col, pal(4) * 0.7, smoothstep(0.006, -0.006, plateHit));
|
col = mix(col, pal(4) * 0.7, smoothstep(0.006, -0.006, plateHit));
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export const horizonLines = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// Crisp line work: the track's surface grain would only fur the edges.
|
// Crisp line work: the track's surface grain would only fur the edges.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['space', 'camera', 'style'],
|
traits: ['space', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -80,7 +81,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col *= 0.55 + 0.45 * exp(-dot(p, p) * 0.5);
|
col *= 0.55 + 0.45 * exp(-dot(p, p) * 0.5);
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y)));
|
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const inkBleed = {
|
|||||||
name: 'Ink Bleed',
|
name: 'Ink Bleed',
|
||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const isometricBlocks = {
|
|||||||
family: 'geometric',
|
family: 'geometric',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.6,
|
texture: 0.6,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -102,7 +103,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// squashed by the tilt — so every block in the field is the same
|
// squashed by the tilt — so every block in the field is the same
|
||||||
// silhouette as every other subject in the video.
|
// silhouette as every other subject in the video.
|
||||||
vec2 q = vec2(fx, (p.y - groundY - h) / tilt);
|
vec2 q = vec2(fx, (p.y - groundY - h) / tilt);
|
||||||
float dTop = sigShape(q / (u_plan * cw)) * (u_plan * cw);
|
float dTop = castMain(q / (u_plan * cw)) * (u_plan * cw);
|
||||||
float topMask = smoothstep(0.004, -0.004, dTop);
|
float topMask = smoothstep(0.004, -0.004, dTop);
|
||||||
|
|
||||||
vec3 top = mix(pal(2), pal(3), sat(h / max(u_height, 1e-3))) * 0.8;
|
vec3 top = mix(pal(2), pal(3), sat(h / max(u_height, 1e-3))) * 0.8;
|
||||||
@ -112,12 +113,12 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// a flash.
|
// a flash.
|
||||||
float picked = step(0.75, hash12(cell * 3.17 + 5.0));
|
float picked = step(0.75, hash12(cell * 3.17 + 5.0));
|
||||||
col += pal(3) * topMask * picked * u_beat * 0.45;
|
col += pal(3) * topMask * picked * u_beat * 0.45;
|
||||||
col += pal(4) * sigEdge(dTop) * (0.2 + u_light * 1.2) * step(0.0, dy);
|
col += pal(4) * inkStroke(dTop) * (0.2 + u_light * 1.2) * step(0.0, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.3);
|
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.3);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export const kaleidoTunnel = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// Hard grid lines on flat colour: grain reads as dirt on the lens.
|
// Hard grid lines on flat colour: grain reads as dirt on the lens.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -37,7 +38,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
// Cross-section measured in the signature form: the tunnel mouth is the
|
// Cross-section measured in the signature form: the tunnel mouth is the
|
||||||
// track's shape rather than a circle.
|
// track's shape rather than a circle.
|
||||||
float radius = max(sigShape(p) + 1.0, 1e-4);
|
float radius = max(castMain(p) + 1.0, 1e-4);
|
||||||
vec2 folded = kaleido(p, sides);
|
vec2 folded = kaleido(p, sides);
|
||||||
float angle = atan(folded.y, folded.x);
|
float angle = atan(folded.y, folded.x);
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += pal(3) * (1.0 - fade) * u_glow * 0.6;
|
col += pal(3) * (1.0 - fade) * u_glow * 0.6;
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
|
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const karmanStreet = {
|
|||||||
family: 'flow',
|
family: 'flow',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.7,
|
texture: 0.7,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -92,14 +93,14 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += pal(2) * sat(-vort) * u_glow * 0.5;
|
col += pal(2) * sat(-vort) * u_glow * 0.5;
|
||||||
|
|
||||||
// The obstacle: still, solid, with the stream piling up on its nose.
|
// The obstacle: still, solid, with the stream piling up on its nose.
|
||||||
float d = sigShape((p - origin) / u_body) * u_body;
|
float d = castMain((p - origin) / u_body) * u_body;
|
||||||
col = mix(col, pal(0) * 0.1, smoothstep(0.005, -0.005, d));
|
col = mix(col, pal(0) * 0.1, smoothstep(0.005, -0.005, d));
|
||||||
col += pal(4) * sigEdge(d) * (0.5 + u_glow * 0.5);
|
col += pal(4) * inkStroke(d) * (0.5 + u_glow * 0.5);
|
||||||
col += pal(4) * exp(-abs(d) * 14.0) * smoothstep(0.1, -0.3, p.x - origin.x) * u_glow * 0.35;
|
col += pal(4) * exp(-abs(d) * 14.0) * smoothstep(0.1, -0.3, p.x - origin.x) * u_glow * 0.35;
|
||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.6, length(p - origin) * 0.7));
|
col = sigAir(col, p, smoothstep(0.0, 1.6, length(p - origin) * 0.7));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const magnetLines = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Line work. Grain furs it up, so take only a dusting.
|
// Line work. Grain furs it up, so take only a dusting.
|
||||||
texture: 0.5,
|
texture: 0.5,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -77,16 +78,16 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// lint: fixed-cost — the same three poles
|
// lint: fixed-cost — the same three poles
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
vec2 c = poleAt(i, t);
|
vec2 c = poleAt(i, t);
|
||||||
float d = sigShape((p - c) / u_core) * u_core;
|
float d = castMain((p - c) / u_core) * u_core;
|
||||||
vec3 tint = mod(float(i), 2.0) < 0.5 ? pal(3) : pal(4);
|
vec3 tint = mod(float(i), 2.0) < 0.5 ? pal(3) : pal(4);
|
||||||
col = mix(col, tint * 0.25, smoothstep(0.004, -0.004, d));
|
col = mix(col, tint * 0.25, smoothstep(0.004, -0.004, d));
|
||||||
col += tint * sigEdge(d) * (0.5 + u_glow * 0.6);
|
col += tint * inkStroke(d) * (0.5 + u_glow * 0.6);
|
||||||
col += tint * exp(-abs(d) * 12.0) * u_glow * 0.25;
|
col += tint * exp(-abs(d) * 12.0) * u_glow * 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
col *= 0.7 + 0.3 * exp(-dot(p, p) * 0.3);
|
col *= 0.7 + 0.3 * exp(-dot(p, p) * 0.3);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export const neonCity = {
|
|||||||
family: 'structural',
|
family: 'structural',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['space', 'camera', 'style'],
|
traits: ['space', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -115,7 +116,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = sigAir(col, p, smoothstep(0.0, 1.4, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.4, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
|
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const pendulumTrace = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Fine line work; grain only furs it up.
|
// Fine line work; grain only furs it up.
|
||||||
texture: 0.25,
|
texture: 0.25,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -86,7 +87,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = max(col, prev(uv) * u_persist);
|
col = max(col, prev(uv) * u_persist);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export const pitchShatter = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -68,7 +69,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col += pal(int(mod(slice, 5.0))) * (1.0 - sliceRand) * u_glow * 0.3 * sliceRand;
|
col += pal(int(mod(slice, 5.0))) * (1.0 - sliceRand) * u_glow * 0.3 * sliceRand;
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -10,6 +10,7 @@ export const psychedelicDrift = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -108,7 +109,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// characters includes the one every other scene is built from.
|
// characters includes the one every other scene is built from.
|
||||||
if (kind == 0.0) d = sdStar(sp, size, 5.0 + floor(hash11(s * 1.2) * 3.0));
|
if (kind == 0.0) d = sdStar(sp, size, 5.0 + floor(hash11(s * 1.2) * 3.0));
|
||||||
else if (kind == 1.0) d = sdSmiley(sp, size, u_time, fi);
|
else if (kind == 1.0) d = sdSmiley(sp, size, u_time, fi);
|
||||||
else d = sigShape(sp / max(size, 1e-3)) * size;
|
else d = castMain(sp / max(size, 1e-3)) * size;
|
||||||
|
|
||||||
float hit = 0.0;
|
float hit = 0.0;
|
||||||
for (int j = 0; j < 5; j++) {
|
for (int j = 0; j < 5; j++) {
|
||||||
@ -130,7 +131,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const pylonGrid = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'space'],
|
traits: ['shape', 'space'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -72,7 +73,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Crown stamped in the track's signature form.
|
// Crown stamped in the track's signature form.
|
||||||
vec2 crown = vec2(cx, yTop);
|
vec2 crown = vec2(cx, yTop);
|
||||||
float size = (0.06 + 0.2 * scale) * (1.0 + u_beat * 0.4);
|
float size = (0.06 + 0.2 * scale) * (1.0 + u_beat * 0.4);
|
||||||
col += pal(3) * sigForm(p, crown, size) * inten * (0.6 + u_pulse);
|
col += pal(3) * castForm(p, crown, size) * inten * (0.6 + u_pulse);
|
||||||
col += pal(int(mod(fr, 4.0))) * exp(-dot(p - crown, p - crown) * 60.0) * u_pulse * depthShade;
|
col += pal(int(mod(fr, 4.0))) * exp(-dot(p - crown, p - crown) * 60.0) * u_pulse * depthShade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +81,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Ground haze and the shared air between here and the horizon.
|
// Ground haze and the shared air between here and the horizon.
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y - hy)));
|
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y - hy)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -16,6 +16,7 @@ export const quasicrystal = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Crisp line work: the track's surface grain would only fur the edges.
|
// Crisp line work: the track's surface grain would only fur the edges.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -67,11 +68,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Ridges: where the sum crosses zero, which is the aperiodic skeleton.
|
// Ridges: where the sum crosses zero, which is the aperiodic skeleton.
|
||||||
float ridge = 1.0 - abs(shaped);
|
float ridge = 1.0 - abs(shaped);
|
||||||
col += pal(4) * pow(sat(ridge), 6.0) * u_glow;
|
col += pal(4) * pow(sat(ridge), 6.0) * u_glow;
|
||||||
col += pal(3) * sigEdge(shaped) * u_glow * 0.3;
|
col += pal(3) * inkStroke(shaped) * u_glow * 0.3;
|
||||||
|
|
||||||
col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.22);
|
col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.22);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const saltFlat = {
|
|||||||
name: 'Salt Flat',
|
name: 'Salt Flat',
|
||||||
family: 'minimal',
|
family: 'minimal',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -68,14 +69,14 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// The one object: small, on the horizon, in the track's form.
|
// The one object: small, on the horizon, in the track's form.
|
||||||
if (u_monolith > 0.005) {
|
if (u_monolith > 0.005) {
|
||||||
vec2 at = vec2(u_standing, horizon + u_monolith * 0.9);
|
vec2 at = vec2(u_standing, horizon + u_monolith * 0.9);
|
||||||
float d = sigShape((p - at) / u_monolith) * u_monolith;
|
float d = castMain((p - at) / u_monolith) * u_monolith;
|
||||||
col = mix(col, pal(0) * 0.12, smoothstep(0.006, -0.006, d));
|
col = mix(col, pal(0) * 0.12, smoothstep(0.006, -0.006, d));
|
||||||
col += pal(4) * sigEdge(d) * (0.3 + u_glowBand * 0.5);
|
col += pal(4) * inkStroke(d) * (0.3 + u_glowBand * 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.4, abs(p.x)));
|
col = sigAir(col, p, smoothstep(0.0, 1.4, abs(p.x)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const scaleMosaic = {
|
|||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.8,
|
texture: 0.8,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -62,7 +63,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// back to screen distance at the end. A scale is therefore as wide as its
|
// back to screen distance at the end. A scale is therefore as wide as its
|
||||||
// slice of the turn and as tall as its ring — wider ones further out, which
|
// slice of the turn and as tall as its ring — wider ones further out, which
|
||||||
// is what growing on a cone looks like.
|
// is what growing on a cone looks like.
|
||||||
float d = sigShape(f / max(rad, 1e-3)) * max(rad, 1e-3) * u_growth * r;
|
float d = castMain(f / max(rad, 1e-3)) * max(rad, 1e-3) * u_growth * r;
|
||||||
|
|
||||||
// Shade by lift, so the surface has a direction of light across it.
|
// Shade by lift, so the surface has a direction of light across it.
|
||||||
float shade = 0.3 + 0.7 * sat(0.5 + lift * 1.4);
|
float shade = 0.3 + 0.7 * sat(0.5 + lift * 1.4);
|
||||||
@ -72,7 +73,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, body * 0.6, smoothstep(0.004, -0.02, d));
|
col = mix(col, body * 0.6, smoothstep(0.004, -0.02, d));
|
||||||
|
|
||||||
// Rim light along every scale edge, in the track's line weight.
|
// Rim light along every scale edge, in the track's line weight.
|
||||||
col += pal(4) * sigEdge(d) * (0.3 + u_sheen * 0.8);
|
col += pal(4) * inkStroke(d) * (0.3 + u_sheen * 0.8);
|
||||||
|
|
||||||
// A specular sweep across the whole head, which is what makes hundreds of
|
// A specular sweep across the whole head, which is what makes hundreds of
|
||||||
// separate tiles read as one surface.
|
// separate tiles read as one surface.
|
||||||
@ -81,7 +82,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col *= 0.72 + 0.28 * exp(-r * r * 0.3);
|
col *= 0.72 + 0.28 * exp(-r * r * 0.3);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export const scanTear = {
|
|||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['style'],
|
traits: ['style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col += pal(4) * torn * u_shift * 0.6;
|
col += pal(4) * torn * u_shift * 0.6;
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const shojiGrid = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Paper has a tooth, and this is the one scene that wants it.
|
// Paper has a tooth, and this is the one scene that wants it.
|
||||||
texture: 1.0,
|
texture: 1.0,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -67,10 +68,10 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
if (u_form > 0.01) {
|
if (u_form > 0.01) {
|
||||||
float which = step(0.62, hash12(cell * 1.7 + 9.0));
|
float which = step(0.62, hash12(cell * 1.7 + 9.0));
|
||||||
vec2 at = vec2(f.x * 2.0 / float(u_cols), f.y * 2.0 / float(u_rows));
|
vec2 at = vec2(f.x * 2.0 / float(u_cols), f.y * 2.0 / float(u_rows));
|
||||||
float d = sigShape(at / u_form) * u_form;
|
float d = castMain(at / u_form) * u_form;
|
||||||
col = mix(col, col * 0.35 + pal(4) * glowField * 0.35,
|
col = mix(col, col * 0.35 + pal(4) * glowField * 0.35,
|
||||||
smoothstep(0.01, -0.01, d) * which);
|
smoothstep(0.01, -0.01, d) * which);
|
||||||
col += pal(4) * sigEdge(d) * which * glowField * 0.7;
|
col += pal(4) * inkStroke(d) * which * glowField * 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The frame. Opaque, in front of everything, and the thing that makes the
|
// The frame. Opaque, in front of everything, and the thing that makes the
|
||||||
@ -78,10 +79,10 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
float bar = min(0.5 - abs(f.x), 0.5 - abs(f.y));
|
float bar = min(0.5 - abs(f.x), 0.5 - abs(f.y));
|
||||||
float wood = smoothstep(u_stile, u_stile * 0.4, bar);
|
float wood = smoothstep(u_stile, u_stile * 0.4, bar);
|
||||||
col = mix(col, pal(0) * 0.14, wood);
|
col = mix(col, pal(0) * 0.14, wood);
|
||||||
col += pal(4) * sigEdge(bar - u_stile) * 0.12;
|
col += pal(4) * inkStroke(bar - u_stile) * 0.12;
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export const signalDecay = {
|
|||||||
name: 'Signal Decay',
|
name: 'Signal Decay',
|
||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -101,7 +102,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = max(col, prev(uv) * u_persist);
|
col = max(col, prev(uv) * u_persist);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const silkRibbon = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// A soft drape of light. Grain furs the one thing it is made of.
|
// A soft drape of light. Grain furs the one thing it is made of.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -74,7 +75,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, pal(2), exp(-knot * knot * 30.0) * u_glow * 0.5);
|
col = mix(col, pal(2), exp(-knot * knot * 30.0) * u_glow * 0.5);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -14,6 +14,7 @@ export const slowOrb = {
|
|||||||
// the one where speckle is most visible for being least justified. It keeps
|
// the one where speckle is most visible for being least justified. It keeps
|
||||||
// its own `grain` param, which exists to stop large flat areas banding.
|
// its own `grain` param, which exists to stop large flat areas banding.
|
||||||
texture: 0,
|
texture: 0,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -43,7 +44,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// The body is the track's signature form — this scene is one shape in an
|
// The body is the track's signature form — this scene is one shape in an
|
||||||
// empty frame, so the shape had better be the track's.
|
// empty frame, so the shape had better be the track's.
|
||||||
float wobble = fbm(q * 2.4 + t, 4) * u_wobble;
|
float wobble = fbm(q * 2.4 + t, 4) * u_wobble;
|
||||||
float d = (sigShape(q / max(u_size, 1e-3)) * u_size) * (1.0 + wobble);
|
float d = (castMain(q / max(u_size, 1e-3)) * u_size) * (1.0 + wobble);
|
||||||
|
|
||||||
// TRAIT style: the body's edge is drawn in the track's hand. The scene's
|
// TRAIT style: the body's edge is drawn in the track's hand. The scene's
|
||||||
// u_softness says how soft this orb is; u_sigSoft says how soft this VIDEO
|
// u_softness says how soft this orb is; u_sigSoft says how soft this VIDEO
|
||||||
@ -54,7 +55,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
// A rim in the track's line weight, so a sharp-handed track gets a defined
|
// A rim in the track's line weight, so a sharp-handed track gets a defined
|
||||||
// limb against the halo instead of only a softer gradient.
|
// limb against the halo instead of only a softer gradient.
|
||||||
float rim = sigEdge(d) * u_sigLine;
|
float rim = inkStroke(d) * u_sigLine;
|
||||||
|
|
||||||
vec3 col = pal(0) * 0.05;
|
vec3 col = pal(0) * 0.05;
|
||||||
col = mix(col, pal(1), body * 0.85);
|
col = mix(col, pal(1), body * 0.85);
|
||||||
@ -67,7 +68,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += (hash12(uv * 640.0 + floor(u_frame)) - 0.5) * u_grain * 0.08;
|
col += (hash12(uv * 640.0 + floor(u_frame)) - 0.5) * u_grain * 0.08;
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
|
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export const spectrumSculpture = {
|
|||||||
// Personality: see look/Personality.js.
|
// Personality: see look/Personality.js.
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -65,8 +66,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
float seg = 6.28318530718 / bars;
|
float seg = 6.28318530718 / bars;
|
||||||
|
|
||||||
float angle = atan(p.y, p.x) + t * seg;
|
float angle = atan(p.y, p.x) + t * seg;
|
||||||
// Radial extent measured in the track's form, so the sculpture is built on
|
// Radial extent measured in the track's SIGNATURE form, not in the cast.
|
||||||
// the same outline as everything else in the video.
|
// This is a metric, not a subject: the cast carries notches and a hollow,
|
||||||
|
// and an annulus used as a radius turns the sculpture inside out — it
|
||||||
|
// rendered pure black. A scene that reads a form as geometry rather than
|
||||||
|
// drawing it wants sigShape, and the migration should leave it alone.
|
||||||
float radius = sigShape(p) + 1.0;
|
float radius = sigShape(p) + 1.0;
|
||||||
float index = floor((angle + 3.14159265) / seg);
|
float index = floor((angle + 3.14159265) / seg);
|
||||||
float cellAngle = mod(angle + 3.14159265, seg) / seg;
|
float cellAngle = mod(angle + 3.14159265, seg) / seg;
|
||||||
@ -91,10 +95,10 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += palRamp(slot * 0.7 + 0.15) * inBar * shape * (0.6 + band);
|
col += palRamp(slot * 0.7 + 0.15) * inBar * shape * (0.6 + band);
|
||||||
|
|
||||||
// Inner ring outline holds the composition together.
|
// Inner ring outline holds the composition together.
|
||||||
col += pal(2) * sigEdge(radius - u_radius) * 0.35;
|
col += pal(2) * inkStroke(radius - u_radius) * 0.35;
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
|
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const stairwellDescent = {
|
|||||||
family: 'structural',
|
family: 'structural',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.7,
|
texture: 0.7,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -82,7 +83,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, pal(1) * 0.3, sky * 0.5);
|
col = mix(col, pal(1) * 0.3, sky * 0.5);
|
||||||
col = sigAir(col, p, sat(1.0 - fade));
|
col = sigAir(col, p, sat(1.0 - fade));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const stormRift = {
|
|||||||
name: 'Storm Rift',
|
name: 'Storm Rift',
|
||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'space', 'style'],
|
traits: ['camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -101,7 +102,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = max(col, prev(uv) * u_afterglow);
|
col = max(col, prev(uv) * u_afterglow);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const suspensionSpan = {
|
|||||||
family: 'structural',
|
family: 'structural',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.6,
|
texture: 0.6,
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -78,7 +79,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Deck: one heavy line all the way across, which is what stops the cable
|
// Deck: one heavy line all the way across, which is what stops the cable
|
||||||
// reading as a piece of string.
|
// reading as a piece of string.
|
||||||
col += pal(4) * smoothstep(w * 2.5, w * 0.6, abs(p.y - deckY)) * (0.4 + u_glow * 0.5);
|
col += pal(4) * smoothstep(w * 2.5, w * 0.6, abs(p.y - deckY)) * (0.4 + u_glow * 0.5);
|
||||||
col += pal(4) * sigEdge(abs(p.y - deckY) - w * 3.0) * 0.25;
|
col += pal(4) * inkStroke(abs(p.y - deckY) - w * 3.0) * 0.25;
|
||||||
|
|
||||||
// Towers: a pair of legs and a crossbeam, with the signature form as the
|
// Towers: a pair of legs and a crossbeam, with the signature form as the
|
||||||
// lamp on top — the only object in the frame that is not a line.
|
// lamp on top — the only object in the frame that is not a line.
|
||||||
@ -87,17 +88,17 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col += palRamp(0.05) * smoothstep(w * 3.0, w * 1.2, dTower) * 0.7;
|
col += palRamp(0.05) * smoothstep(w * 3.0, w * 1.2, dTower) * 0.7;
|
||||||
|
|
||||||
if (u_lamp > 0.004) {
|
if (u_lamp > 0.004) {
|
||||||
float d = sigShape((vec2(x, p.y) - vec2(0.0, towerTop + u_lamp)) / u_lamp) * u_lamp;
|
float d = castMain((vec2(x, p.y) - vec2(0.0, towerTop + u_lamp)) / u_lamp) * u_lamp;
|
||||||
col += pal(3) * smoothstep(0.004, -0.004, d) * (0.6 + u_glow);
|
col += pal(3) * smoothstep(0.004, -0.004, d) * (0.6 + u_glow);
|
||||||
col += pal(3) * exp(-abs(d) * 20.0) * u_glow * 0.5;
|
col += pal(3) * exp(-abs(d) * 20.0) * u_glow * 0.5;
|
||||||
col += pal(3) * sigEdge(d) * 0.6;
|
col += pal(3) * inkStroke(d) * 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every other bay is a little further off, so the line of the bridge has
|
// Every other bay is a little further off, so the line of the bridge has
|
||||||
// some air in it rather than being a flat elevation drawing.
|
// some air in it rather than being a flat elevation drawing.
|
||||||
col = sigAir(col, p, smoothstep(0.2, 1.4, abs(bay) * 0.7 + hash11(bayId) * 0.5));
|
col = sigAir(col, p, smoothstep(0.2, 1.4, abs(bay) * 0.7 + hash11(bayId) * 0.5));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const tideRings = {
|
|||||||
name: 'Tide Rings',
|
name: 'Tide Rings',
|
||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'space', 'style'],
|
traits: ['shape', 'camera', 'space', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -52,7 +53,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Distance in the signature metric: round tracks get circular wavefronts.
|
// Distance in the signature metric: round tracks get circular wavefronts.
|
||||||
float d = sigShape(p - src) + 1.0;
|
float d = castMain(p - src) + 1.0;
|
||||||
float amp = exp(-d * u_decay);
|
float amp = exp(-d * u_decay);
|
||||||
sum += sin(d * u_wavelength - t * 6.0 + fract(s) * 6.28) * amp;
|
sum += sin(d * u_wavelength - t * 6.0 + fract(s) * 6.28) * amp;
|
||||||
energy += amp;
|
energy += amp;
|
||||||
@ -71,7 +72,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const timeSmear = {
|
|||||||
name: 'Time Smear',
|
name: 'Time Smear',
|
||||||
family: 'glitch',
|
family: 'glitch',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -75,7 +76,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
col = mix(col, vec3(dot(col, vec3(0.299, 0.587, 0.114))), age * 0.35);
|
col = mix(col, vec3(dot(col, vec3(0.299, 0.587, 0.114))), age * 0.35);
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const truchetFold = {
|
|||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
|
||||||
texture: 0.4,
|
texture: 0.4,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -64,11 +65,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
vec3 col = pal(0) * 0.05;
|
vec3 col = pal(0) * 0.05;
|
||||||
col += tint * line * 0.75;
|
col += tint * line * 0.75;
|
||||||
col += tint * halo * u_glow * 0.35;
|
col += tint * halo * u_glow * 0.35;
|
||||||
col += pal(4) * sigEdge(d) * u_glow * 0.25;
|
col += pal(4) * inkStroke(d) * u_glow * 0.25;
|
||||||
|
|
||||||
col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.25);
|
col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.25);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,6 +24,7 @@ export const turingBloom = {
|
|||||||
name: 'Turing Bloom',
|
name: 'Turing Bloom',
|
||||||
family: 'organic',
|
family: 'organic',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -117,7 +118,7 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.2);
|
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.2);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export const voronoiShatter = {
|
|||||||
family: 'geometric',
|
family: 'geometric',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
texture: 0.5,
|
texture: 0.5,
|
||||||
|
consumes: ['ink'],
|
||||||
traits: ['camera', 'style'],
|
traits: ['camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -84,11 +85,11 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
// Seams: drawn in the track's hand, brightest where three plates meet.
|
// Seams: drawn in the track's hand, brightest where three plates meet.
|
||||||
float seam = smoothstep(u_seam, u_seam * 0.15, border);
|
float seam = smoothstep(u_seam, u_seam * 0.15, border);
|
||||||
col += pal(4) * seam * (0.4 + u_glow * 0.8);
|
col += pal(4) * seam * (0.4 + u_glow * 0.8);
|
||||||
col += pal(3) * sigEdge(border - u_seam) * 0.4;
|
col += pal(3) * inkStroke(border - u_seam) * 0.4;
|
||||||
|
|
||||||
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.25);
|
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.25);
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export const vortexDrift = {
|
|||||||
name: 'Vortex Drift',
|
name: 'Vortex Drift',
|
||||||
family: 'flow',
|
family: 'flow',
|
||||||
kind: 'fragment',
|
kind: 'fragment',
|
||||||
|
consumes: ['cast', 'ink'],
|
||||||
traits: ['shape', 'camera', 'style'],
|
traits: ['shape', 'camera', 'style'],
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
@ -64,14 +65,14 @@ vec4 scene(vec2 uv, vec2 p) {
|
|||||||
|
|
||||||
// The eye itself, in the signature form.
|
// The eye itself, in the signature form.
|
||||||
if (u_core > 0.004) {
|
if (u_core > 0.004) {
|
||||||
float d = sigShape(q / u_core) * u_core;
|
float d = castMain(q / u_core) * u_core;
|
||||||
col = mix(col, pal(0) * 0.05, smoothstep(0.004, -0.01, d));
|
col = mix(col, pal(0) * 0.05, smoothstep(0.004, -0.01, d));
|
||||||
col += pal(3) * sigEdge(d) * 0.8;
|
col += pal(3) * inkStroke(d) * 0.8;
|
||||||
col += pal(4) * exp(-max(d, 0.0) * 18.0) * 0.35;
|
col += pal(4) * exp(-max(d, 0.0) * 18.0) * 0.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
col += sigGrain(uv);
|
col += sigGrain(uv);
|
||||||
return vec4(col, 1.0);
|
return vec4(inkValue(col), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -103,43 +103,69 @@ const CONTRACT_UNIFORMS = new Set([
|
|||||||
* cast in the hexagon video and be the one shot that looks filmed elsewhere.
|
* cast in the hexagon video and be the one shot that looks filmed elsewhere.
|
||||||
* So the claim is machine-checked against the source rather than trusted.
|
* So the claim is machine-checked against the source rather than trusted.
|
||||||
*/
|
*/
|
||||||
// A stage that draws the song's CAST is expressing `shape` more completely than
|
// A scene that draws the song's CAST is expressing `shape` more completely than
|
||||||
// sigShape ever did — the form is the subject rather than a hint applied to one
|
// sigShape ever did — the form is the subject rather than a hint applied to one
|
||||||
// — so castMain/castChorus count as evidence. Likewise inkMask/inkValue are the
|
// — so castMain/castChorus count as evidence.
|
||||||
// style trait carried out in full. See scenes/stage/README.md.
|
//
|
||||||
|
// The INK does not work the same way and must not be listed under `style`. A
|
||||||
|
// trait is a property of the track that a scene may honour; an artifact is
|
||||||
|
// content it draws. Taking the ink says nothing about whether the scene
|
||||||
|
// responds to u_sigLine, and treating it as evidence let Eclipse Field claim a
|
||||||
|
// trait it had stopped honouring — which the runtime gate then caught.
|
||||||
// The same idea as TRAIT_EVIDENCE, for the identity artifacts: a scene that
|
// The same idea as TRAIT_EVIDENCE, for the identity artifacts: a scene that
|
||||||
// declares it consumes the cast has to actually draw it. Without this,
|
// declares it consumes the cast has to actually draw it. Without this,
|
||||||
// `consumes` is a comment, and the migration becomes unverifiable the moment it
|
// `consumes` is a comment, and the migration becomes unverifiable the moment it
|
||||||
// is more than a handful of files.
|
// is more than a handful of files.
|
||||||
const ARTIFACT_EVIDENCE = {
|
const ARTIFACT_EVIDENCE = {
|
||||||
cast: /\bcast(Main|Chorus|SDF)\s*\(/,
|
cast: /\bcast(Main|Chorus|SDF|Form)\s*\(/,
|
||||||
ink: /\bink(Mask|Value|Pattern)\s*\(/,
|
ink: /\bink(Mask|Value|Pattern|Stroke)\s*\(/,
|
||||||
staging: /\b(stageNode|stageScale)\s*\(/,
|
staging: /\b(stageNode|stageScale)\s*\(/,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TRAIT_EVIDENCE = {
|
const TRAIT_EVIDENCE = {
|
||||||
shape: /\b(sig(Shape|Form)|cast(Main|Chorus|SDF))\s*\(/,
|
shape: /\b(sig(Shape|Form)|cast(Main|Chorus|SDF|Form))\s*\(/,
|
||||||
camera: /\bsigCamera\s*\(/,
|
camera: /\bsigCamera\s*\(/,
|
||||||
space: /\b(sigHorizonY|sigAir)\s*\(|\bu_sig(Horizon|Depth|Wash)\b/,
|
space: /\b(sigHorizonY|sigAir)\s*\(|\bu_sig(Horizon|Depth|Wash)\b/,
|
||||||
style: /\b(sigEdge|sigGrain|sigFolded|inkMask|inkValue|inkPattern)\s*\(|\bu_sig(Line|Soft|Texture|Fold)\b/,
|
style: /\b(sigEdge|sigGrain|sigFolded)\s*\(|\bu_sig(Line|Soft|Texture|Fold)\b/,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The shader preamble is a JS template literal, so a backtick anywhere inside
|
// Every shader in this project lives inside a JS template literal, so a
|
||||||
// it silently closes the literal. Twice now that has produced a check page that
|
// backtick anywhere in one silently closes it. Three times now that has cost a
|
||||||
// hangs on "starting…" with an empty console, which is an expensive way to find
|
// debugging round: twice in the preamble, where it produced a check page that
|
||||||
// a typo. One grep is cheaper.
|
// hung on "starting…" with an empty console, and once in a scene, where at
|
||||||
console.log('\nshader contract');
|
// least the module failed to parse loudly. A GLSL comment is the natural place
|
||||||
|
// to reach for backticks when quoting a param name, which is exactly why this
|
||||||
|
// keeps happening.
|
||||||
|
//
|
||||||
|
// Checked across the contract AND every scene, since the scene case is the one
|
||||||
|
// a mechanical pass over sixty files will keep reintroducing.
|
||||||
|
console.log('\nshader literals');
|
||||||
{
|
{
|
||||||
const src = readFileSync(join(SRC, 'engine/shader-contract.js'), 'utf8');
|
const targets = [join(SRC, 'engine/shader-contract.js'), ...walk(join(SRC, 'scenes'))];
|
||||||
const literal = src.slice(src.indexOf('export const PREAMBLE = `') + 25);
|
let clean = 0;
|
||||||
const body = literal.slice(0, literal.indexOf('\n`;'));
|
for (const file of targets) {
|
||||||
const stray = body.split('\n').filter((l) => l.includes('`') && !l.includes('${'));
|
const src = readFileSync(file, 'utf8');
|
||||||
if (stray.length) {
|
const rel = relative(SRC, file).replace(/\\/g, '/');
|
||||||
fail(`shader preamble contains a backtick, which closes the template literal:\n` +
|
// Every template literal in the file, then the lines inside them that
|
||||||
stray.map((l) => ` ${l.trim()}`).join('\n'));
|
// carry a backtick without being an interpolation.
|
||||||
} else {
|
const stray = [];
|
||||||
ok('preamble has no stray backticks');
|
const rx = /`([\s\S]*?)`/g;
|
||||||
|
let m;
|
||||||
|
while ((m = rx.exec(src)) !== null) {
|
||||||
|
if (!/\bvec4 scene|precision highp|void main/.test(m[1])) continue;
|
||||||
|
for (const line of m[1].split('\n')) {
|
||||||
|
if (line.includes('`') && !line.includes('${')) stray.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A shader body that swallowed a closing backtick shows up as an
|
||||||
|
// unbalanced count across the file.
|
||||||
|
const ticks = (src.match(/`/g) || []).length;
|
||||||
|
if (stray.length || ticks % 2 !== 0) {
|
||||||
|
fail(`${rel}: backtick inside a shader literal — it closes the string` +
|
||||||
|
(stray.length ? `:\n${stray.map((l) => ` ${l.trim()}`).join('\n')}` : ''));
|
||||||
|
} else clean++;
|
||||||
}
|
}
|
||||||
|
if (clean === targets.length) ok(`${clean} shader literals balanced, no stray backticks`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('\nscene schema lint');
|
console.log('\nscene schema lint');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user