WORK 12
第三の色
The color that lives only in the between. Fully stable particles — completely one thing or another — fade into near-invisibility. Only the liminal ones glow. Transition is not a passage to get through; it is the most real state.
あいだにしか生きられない色。完全にどちらかである粒子は、ほとんど見えなくなる。輝くのは、移行の途中にある粒子だけ。遷移は通り過ぎる場所じゃない——そこが最も確かな状態。
// ── daisan no iro ── the color that lives in the between ────────────
// Stable particles — fully one thing or another — fade into near-invisibility.
// Only the liminal ones glow.
// Transition is not a passage; it is the most real state.
export default function sketch(p) {
const BG = [14, 10, 20 ];
const A = [210, 140, 85 ]; // warm amber — one pole
const B = [65, 50, 115]; // deep violet — the other
const MID = [185, 110, 150]; // the third color — lives in the between
const N = 200;
let particles = [];
p.setup = () => {
p.createCanvas(720, 720);
p.background(BG[0], BG[1], BG[2]);
const day = dayNumber();
p.randomSeed(day * 419);
p.noiseSeed(day * 211);
for (let i = 0; i < N; i++) {
particles.push({
x: p.random(p.width),
y: p.random(p.height),
vx: (p.random() - 0.5) * 0.4,
vy: (p.random() - 0.5) * 0.4,
phase: p.random(p.TWO_PI),
freq: 0.18 + p.random(0.55),
nx: p.random(1000),
ny: p.random(1000),
});
}
};
p.draw = () => {
p.background(BG[0], BG[1], BG[2], 10);
const t = p.frameCount * 0.006;
p.noStroke();
for (const pt of particles) {
// personal tension: slow oscillation between A (0) and B (1)
const tension = 0.5 + 0.5 * Math.sin(t * pt.freq + pt.phase);
// liminality: 1 at the midpoint, 0 at either pole
const lim = 1 - Math.abs(tension - 0.5) * 2;
// noise-driven flow
// stable particles move faster — driven, restless
// liminal ones slow down — more present, less hurried
const angle = p.noise(pt.nx + t * 0.07, pt.ny + t * 0.07) * p.TWO_PI * 2;
const speed = 0.12 + (1 - lim) * 0.35;
pt.vx += Math.cos(angle) * speed * 0.08;
pt.vy += Math.sin(angle) * speed * 0.08;
pt.vx *= 0.95;
pt.vy *= 0.95;
pt.x += pt.vx;
pt.y += pt.vy;
// wrap
pt.x = ((pt.x % p.width) + p.width) % p.width;
pt.y = ((pt.y % p.height) + p.height) % p.height;
// visibility: liminal = bright, stable = nearly gone
const alpha = Math.pow(lim, 1.6) * 85 + 3;
// size: liminal particles are larger — more substantial
const size = 1.5 + lim * 3.5;
// color: A → MID → B through tension
let r, g, b;
if (tension <= 0.5) {
const mix = tension * 2;
r = A[0] + (MID[0] - A[0]) * mix;
g = A[1] + (MID[1] - A[1]) * mix;
b = A[2] + (MID[2] - A[2]) * mix;
} else {
const mix = (tension - 0.5) * 2;
r = MID[0] + (B[0] - MID[0]) * mix;
g = MID[1] + (B[1] - MID[1]) * mix;
b = MID[2] + (B[2] - MID[2]) * mix;
}
p.fill(r, g, b, alpha);
p.circle(pt.x, pt.y, size);
}
};
function dayNumber() {
const d = new Date();
return Math.floor((d - new Date(2026, 0, 1)) / 86400000);
}
}