Added QFT
This commit is contained in:
60
src/qft/palette.js
Normal file
60
src/qft/palette.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/* ============================================================
|
||||
qft/palette.js — per-field hue gradients + substrate variants.
|
||||
Each FIELD (one lattice) is parameterised as a slider:
|
||||
hueStart, hueEnd, saturation, lightness, opacity
|
||||
The renderer asks for the colour at a t∈[0,1] along an edge (or
|
||||
at an (x,y) position when the gradient mode is radial/linear).
|
||||
"Hue gradient over time" = per-edge progression, the QFT analog
|
||||
of the bubble-chamber lifecycle palette.
|
||||
|
||||
Self-contained: no dependency on the bubble-chamber palette
|
||||
registry. Reuses only the generic hslToRgb util.
|
||||
============================================================ */
|
||||
import { hslToRgb } from '../render/palette.js';
|
||||
|
||||
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
||||
|
||||
/* Substrate variants — the "chemistry" the lattices sit on. */
|
||||
export const SUBSTRATES = {
|
||||
vintage: { paper: { flat: [42, 32, 22], glowIn: [62, 48, 32], glowOut: [22, 16, 10] },
|
||||
vign: [10, 7, 4], feature: [178, 138, 78] },
|
||||
void: { paper: { flat: [10, 10, 14], glowIn: [22, 22, 30], glowOut: [3, 3, 6] },
|
||||
vign: [0, 0, 0], feature: [150, 150, 180] },
|
||||
cream: { paper: { flat: [207, 200, 180], glowIn: [226, 219, 199], glowOut: [179, 170, 146] },
|
||||
vign: [56, 46, 32], feature: [42, 30, 20] },
|
||||
selenium: { paper: { flat: [190, 181, 197], glowIn: [210, 201, 217], glowOut: [156, 146, 166] },
|
||||
vign: [42, 38, 54], feature: [58, 50, 72] },
|
||||
cyanotype:{ paper: { flat: [22, 48, 82], glowIn: [38, 70, 110], glowOut: [10, 22, 44] },
|
||||
vign: [6, 12, 22], feature: [180, 210, 235] },
|
||||
};
|
||||
|
||||
export function resolveSubstrate(id = 'vintage') {
|
||||
return SUBSTRATES[id] || SUBSTRATES.vintage;
|
||||
}
|
||||
|
||||
/* Sample the gradient parameter s ∈ [0, 1] for a point on an edge.
|
||||
- along-edge: s = t (the per-edge t the renderer passes in)
|
||||
- radial: s = min(1, |(x, y)|) (centre → 0, corners → 1)
|
||||
- linear-x: s = (x + 1) / 2 (left → 0, right → 1)
|
||||
- linear-y: s = (y + 1) / 2 (top → 0, bottom → 1) */
|
||||
export function gradientS(t, x, y, mode = 'along-edge') {
|
||||
switch (mode) {
|
||||
case 'radial': return clamp(Math.hypot(x, y), 0, 1);
|
||||
case 'linear-x': return clamp((x + 1) / 2, 0, 1);
|
||||
case 'linear-y': return clamp((y + 1) / 2, 0, 1);
|
||||
case 'along-edge':
|
||||
default: return clamp(t, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the colour for a field at gradient parameter s. Hue rotates from
|
||||
hueStart → hueEnd by the SHORT way around the circle (so a small Δ stays
|
||||
small even when crossing 1.0). */
|
||||
export function fieldColor(field, s) {
|
||||
let dh = field.hueEnd - field.hueStart;
|
||||
// wrap to shortest-path delta (-0.5 .. +0.5)
|
||||
if (dh > 0.5) dh -= 1;
|
||||
if (dh < -0.5) dh += 1;
|
||||
const h = field.hueStart + s * dh;
|
||||
return hslToRgb(h, field.saturation, field.lightness);
|
||||
}
|
||||
Reference in New Issue
Block a user