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:
Dejvino
2026-08-18 06:39:19 +02:00
co-authored by Claude Opus 5
parent e5bb7d77e0
commit 2d3ed8eb02
49 changed files with 234 additions and 123 deletions
+27
View File
@@ -452,6 +452,33 @@ float inkMask(float d, vec2 uv) {
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. */
vec3 inkValue(vec3 col) {
if (u_inkPosterize < 1.5) return col;
+3 -2
View File
@@ -17,6 +17,7 @@ export const analogWow = {
family: 'glitch',
kind: 'fragment',
texture: 0.9,
consumes: ['ink'],
traits: ['camera', 'style'],
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;
// The boundary between bands is drawn in the track's weight, so even a
// 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;
}
@@ -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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -14,6 +14,7 @@ export const apollonianGasket = {
kind: 'fragment',
// Drawn geometry; grain only muddies the small discs.
texture: 0.3,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -88,14 +89,14 @@ vec4 scene(vec2 uv, vec2 p) {
vec3 col = pal(0) * 0.06;
col += palRamp(gen) * edge * (0.55 + u_rim * 0.7);
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.
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -21,6 +21,7 @@ export const aqueductMarch = {
family: 'structural',
kind: 'fragment',
texture: 0.9,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
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 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);
}
@@ -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));
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(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);
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -13,6 +13,7 @@ export const auroraVeil = {
name: 'Aurora Veil',
family: 'flow',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.x)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -17,6 +17,7 @@ export const balanceStack = {
name: 'Balance Stack',
family: 'minimal',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
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;
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.
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));
// 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;
}
col = sigAir(col, p, smoothstep(0.1, 1.5, abs(p.x) * 0.7 + sat(above * 0.5)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -11,6 +11,7 @@ export const blockMosh = {
family: 'glitch',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['ink'],
traits: ['camera', 'style'],
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -15,6 +15,7 @@ export const cargoBelt = {
kind: 'fragment',
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -65,11 +66,11 @@ vec4 scene(vec2 uv, vec2 p) {
if (rnd > u_gap) {
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 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);
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
// whole-frame: a per-crate blink is not a flash.
@@ -82,7 +83,7 @@ vec4 scene(vec2 uv, vec2 p) {
}
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -15,6 +15,7 @@ export const cellDivide = {
name: 'Cell Divide',
family: 'organic',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -95,13 +96,13 @@ vec4 scene(vec2 uv, vec2 p) {
// Nucleus, in the track's signature form.
if (u_nucleus > 0.01) {
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 += pal(2) * sigEdge(d) * (0.35 + u_glow * 0.4);
col += pal(2) * inkStroke(d) * (0.35 + u_glow * 0.4);
}
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -15,6 +15,7 @@ export const circuitBloom = {
kind: 'fragment',
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -91,13 +92,17 @@ vec4 scene(vec2 uv, vec2 p) {
// Pads sit where both traces meet, stamped in the signature form.
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(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);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -9,6 +9,7 @@ export const classicWave = {
// Personality: see look/Personality.js.
// Smooth concentric colour: grain only mutes the ramp it is built on.
texture: 0,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -38,7 +39,7 @@ vec4 scene(vec2 uv, vec2 p) {
p = sigCamera(p);
// The rings take the track's signature form: round tracks get circles,
// 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 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -9,6 +9,7 @@ export const curlFlow = {
family: 'flow',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -81,7 +82,7 @@ vec4 scene(vec2 uv, vec2 p) {
col *= 0.6 + 0.4 * exp(-dot(p, p) * 0.35);
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -12,6 +12,7 @@ export const dataAisle = {
family: 'structural',
kind: 'fragment',
texture: 0.6,
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -62,7 +63,7 @@ vec3 wall(vec2 at, float side, float t, float lightAmount) {
float bright = mix(0.25, 1.0, busy);
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;
}
@@ -106,7 +107,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = mix(col, pal(1) * 0.12, sat(far * u_haze));
col = sigAir(col, p, far);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -22,6 +22,7 @@ export const drosteFeedback = {
family: 'glitch',
kind: 'fragment',
texture: 0.5,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -54,7 +55,7 @@ vec4 scene(vec2 uv, vec2 p) {
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 += 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;
// 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.
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.35);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -13,6 +13,7 @@ export const dustChamber = {
name: 'Dust Chamber',
family: 'minimal',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
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 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 = sigAir(col, p, smoothstep(0.0, 1.5, length(p)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -18,7 +18,12 @@ export const eclipseField = {
kind: 'fragment',
// Crisp line work: the track's surface grain would only fur the edges.
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: {
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);
// 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.
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.
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -12,6 +12,7 @@ export const flora = {
family: 'organic',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -48,7 +49,7 @@ float petal(vec2 p, vec2 node, vec2 dir, float len, float width) {
float across = dot(off, perp);
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));
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);
return form * clip;
}
@@ -105,13 +106,13 @@ vec4 scene(vec2 uv, vec2 p) {
for (int k = 0; k < 6; k++) {
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);
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -16,6 +16,7 @@ export const gateCorridor = {
kind: 'fragment',
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
params: {
@@ -62,7 +63,7 @@ vec4 scene(vec2 uv, vec2 p) {
float phase = fract((fi / float(u_gates)) + t);
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
// 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -17,6 +17,7 @@ export const girderLattice = {
kind: 'fragment',
// Crisp line work: the track's surface grain would only fur the edges.
texture: 0,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
params: {
@@ -58,7 +59,7 @@ vec4 scene(vec2 uv, vec2 p) {
if (above <= 0.001) {
col = sigAir(col, p, 1.0);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
float best = 1e3;
@@ -94,9 +95,9 @@ vec4 scene(vec2 uv, vec2 p) {
}
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);
pd = sigShape((p - vec2(-halfW0, y0)) / u_plate) * u_plate;
pd = castMain((p - vec2(-halfW0, y0)) / u_plate) * u_plate;
plateHit = min(plateHit, pd);
}
@@ -109,7 +110,7 @@ vec4 scene(vec2 uv, vec2 p) {
float steel = smoothstep(weight, weight * 0.3, best);
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.
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.
// Crisp line work: the track's surface grain would only fur the edges.
texture: 0,
consumes: ['ink'],
traits: ['space', 'camera', 'style'],
params: {
@@ -80,7 +81,7 @@ vec4 scene(vec2 uv, vec2 p) {
col *= 0.55 + 0.45 * exp(-dot(p, p) * 0.5);
col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -13,6 +13,7 @@ export const inkBleed = {
name: 'Ink Bleed',
family: 'organic',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = sigAir(col, p, smoothstep(0.0, 1.7, length(p)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -13,6 +13,7 @@ export const isometricBlocks = {
family: 'geometric',
kind: 'fragment',
texture: 0.6,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -102,7 +103,7 @@ vec4 scene(vec2 uv, vec2 p) {
// squashed by the tilt — so every block in the field is the same
// silhouette as every other subject in the video.
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);
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.
float picked = step(0.75, hash12(cell * 3.17 + 5.0));
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 += 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.
// Hard grid lines on flat colour: grain reads as dirt on the lens.
texture: 0,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -37,7 +38,7 @@ vec4 scene(vec2 uv, vec2 p) {
// Cross-section measured in the signature form: the tunnel mouth is the
// 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);
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -13,6 +13,7 @@ export const karmanStreet = {
family: 'flow',
kind: 'fragment',
texture: 0.7,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
params: {
@@ -92,14 +93,14 @@ vec4 scene(vec2 uv, vec2 p) {
col += pal(2) * sat(-vort) * u_glow * 0.5;
// 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 += 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 = sigAir(col, p, smoothstep(0.0, 1.6, length(p - origin) * 0.7));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -14,6 +14,7 @@ export const magnetLines = {
kind: 'fragment',
// Line work. Grain furs it up, so take only a dusting.
texture: 0.5,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -77,16 +78,16 @@ vec4 scene(vec2 uv, vec2 p) {
// lint: fixed-cost — the same three poles
for (int i = 0; i < 3; i++) {
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);
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 *= 0.7 + 0.3 * exp(-dot(p, p) * 0.3);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -12,6 +12,7 @@ export const neonCity = {
family: 'structural',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['ink'],
traits: ['space', 'camera', 'style'],
params: {
@@ -115,7 +116,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = sigAir(col, p, smoothstep(0.0, 1.4, length(p)));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -15,6 +15,7 @@ export const pendulumTrace = {
kind: 'fragment',
// Fine line work; grain only furs it up.
texture: 0.25,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -86,7 +87,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = max(col, prev(uv) * u_persist);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -10,6 +10,7 @@ export const pitchShatter = {
family: 'glitch',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['ink'],
traits: ['camera', 'style'],
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -10,6 +10,7 @@ export const psychedelicDrift = {
family: 'glitch',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -108,7 +109,7 @@ vec4 scene(vec2 uv, vec2 p) {
// 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));
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;
for (int j = 0; j < 5; j++) {
@@ -130,7 +131,7 @@ vec4 scene(vec2 uv, vec2 p) {
}
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -11,6 +11,7 @@ export const pylonGrid = {
// Personality: see look/Personality.js.
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['cast', 'ink'],
traits: ['shape', 'space'],
params: {
@@ -72,7 +73,7 @@ vec4 scene(vec2 uv, vec2 p) {
// Crown stamped in the track's signature form.
vec2 crown = vec2(cx, yTop);
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;
}
}
@@ -80,7 +81,7 @@ vec4 scene(vec2 uv, vec2 p) {
// 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -16,6 +16,7 @@ export const quasicrystal = {
kind: 'fragment',
// Crisp line work: the track's surface grain would only fur the edges.
texture: 0,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -67,11 +68,11 @@ vec4 scene(vec2 uv, vec2 p) {
// 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 += pal(3) * inkStroke(shaped) * u_glow * 0.3;
col *= 0.65 + 0.35 * exp(-dot(p, p) * 0.22);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -13,6 +13,7 @@ export const saltFlat = {
name: 'Salt Flat',
family: 'minimal',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
params: {
@@ -68,14 +69,14 @@ vec4 scene(vec2 uv, vec2 p) {
// The one object: small, on the horizon, in the track's form.
if (u_monolith > 0.005) {
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 += 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -15,6 +15,7 @@ export const scaleMosaic = {
family: 'organic',
kind: 'fragment',
texture: 0.8,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
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
// slice of the turn and as tall as its ring — wider ones further out, which
// 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.
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));
// 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
// 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -10,6 +10,7 @@ export const scanTear = {
family: 'glitch',
kind: 'fragment',
// Personality: see look/Personality.js.
consumes: ['ink'],
traits: ['style'],
params: {
@@ -73,7 +74,7 @@ vec4 scene(vec2 uv, vec2 p) {
col += pal(4) * torn * u_shift * 0.6;
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+5 -4
View File
@@ -14,6 +14,7 @@ export const shojiGrid = {
kind: 'fragment',
// Paper has a tooth, and this is the one scene that wants it.
texture: 1.0,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -67,10 +68,10 @@ vec4 scene(vec2 uv, vec2 p) {
if (u_form > 0.01) {
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));
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,
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
@@ -78,10 +79,10 @@ vec4 scene(vec2 uv, vec2 p) {
float bar = min(0.5 - abs(f.x), 0.5 - abs(f.y));
float wood = smoothstep(u_stile, u_stile * 0.4, bar);
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);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -10,6 +10,7 @@ export const signalDecay = {
name: 'Signal Decay',
family: 'glitch',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -101,7 +102,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = max(col, prev(uv) * u_persist);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -11,6 +11,7 @@ export const silkRibbon = {
// Personality: see look/Personality.js.
// A soft drape of light. Grain furs the one thing it is made of.
texture: 0,
consumes: ['ink'],
traits: ['camera', 'style'],
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -14,6 +14,7 @@ export const slowOrb = {
// 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.
texture: 0,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
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
// empty frame, so the shape had better be the track's.
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
// 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
// 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;
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 += 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.
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -65,8 +66,11 @@ vec4 scene(vec2 uv, vec2 p) {
float seg = 6.28318530718 / bars;
float angle = atan(p.y, p.x) + t * seg;
// Radial extent measured in the track's form, so the sculpture is built on
// the same outline as everything else in the video.
// Radial extent measured in the track's SIGNATURE form, not in the cast.
// 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 index = floor((angle + 3.14159265) / 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);
// 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);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -14,6 +14,7 @@ export const stairwellDescent = {
family: 'structural',
kind: 'fragment',
texture: 0.7,
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -82,7 +83,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = mix(col, pal(1) * 0.3, sky * 0.5);
col = sigAir(col, p, sat(1.0 - fade));
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -13,6 +13,7 @@ export const stormRift = {
name: 'Storm Rift',
family: 'glitch',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'space', 'style'],
params: {
@@ -101,7 +102,7 @@ vec4 scene(vec2 uv, vec2 p) {
col = max(col, prev(uv) * u_afterglow);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -13,6 +13,7 @@ export const suspensionSpan = {
family: 'structural',
kind: 'fragment',
texture: 0.6,
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
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
// 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) * 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
// 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;
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) * 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
// 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -14,6 +14,7 @@ export const tideRings = {
name: 'Tide Rings',
family: 'organic',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'space', 'style'],
params: {
@@ -52,7 +53,7 @@ vec4 scene(vec2 uv, vec2 p) {
);
// 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);
sum += sin(d * u_wavelength - t * 6.0 + fract(s) * 6.28) * 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -14,6 +14,7 @@ export const timeSmear = {
name: 'Time Smear',
family: 'glitch',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'style'],
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+3 -2
View File
@@ -13,6 +13,7 @@ export const truchetFold = {
kind: 'fragment',
// Takes the track's surface grain, but lightly — this is drawn, not filmed.
texture: 0.4,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -64,11 +65,11 @@ vec4 scene(vec2 uv, vec2 p) {
vec3 col = pal(0) * 0.05;
col += tint * line * 0.75;
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+2 -1
View File
@@ -24,6 +24,7 @@ export const turingBloom = {
name: 'Turing Bloom',
family: 'organic',
kind: 'fragment',
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -117,7 +118,7 @@ vec4 scene(vec2 uv, vec2 p) {
col *= 0.75 + 0.25 * exp(-dot(p, p) * 0.2);
col += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
@@ -20,6 +20,7 @@ export const voronoiShatter = {
family: 'geometric',
kind: 'fragment',
texture: 0.5,
consumes: ['ink'],
traits: ['camera', 'style'],
params: {
@@ -84,11 +85,11 @@ vec4 scene(vec2 uv, vec2 p) {
// Seams: drawn in the track's hand, brightest where three plates meet.
float seam = smoothstep(u_seam, u_seam * 0.15, border);
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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};
+4 -3
View File
@@ -13,6 +13,7 @@ export const vortexDrift = {
name: 'Vortex Drift',
family: 'flow',
kind: 'fragment',
consumes: ['cast', 'ink'],
traits: ['shape', 'camera', 'style'],
params: {
@@ -64,14 +65,14 @@ vec4 scene(vec2 uv, vec2 p) {
// The eye itself, in the signature form.
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 += 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 += sigGrain(uv);
return vec4(col, 1.0);
return vec4(inkValue(col), 1.0);
}
`,
};