Files
bubblechambersimart/tools/qft-variations-light.mjs
2026-05-29 15:40:42 -04:00

231 lines
8.2 KiB
JavaScript

/* ============================================================
qft-variations-light.mjs — sketch 04.
Lighter backgrounds, larger field scales (most bleed past the
frame), per-edge hue GRADIENTS within each field, and
noticeably THICKER strokes than previous sketches. Custom
paperOverride RGB for the more unusual pale grounds.
Output → output/qft/sketch04/
============================================================ */
import { writeFileSync, mkdirSync } from 'node:fs';
import { generateQFTScene } from '../src/qft/scene.js';
import { paramsFromSeed } from '../src/qft/params.js';
import { renderQFTSVG } from '../src/qft/renderer.js';
const BASE_SEED = 'FEYNMAN-7167';
const OUT_DIR = 'output/qft/sketch04';
const SIZE = 1800;
mkdirSync(OUT_DIR, { recursive: true });
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
({ hueStart, hueEnd, saturation, lightness, opacity });
// helper: build a paperOverride from one RGB and derive sensible glow stops
const paper = (flat, glowInDelta = [18, 16, 14], glowOutDelta = [-25, -22, -20]) => ({
flat,
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
});
// dark header/vignette tones to read against light paper
const DARK_FEATURE = [60, 48, 36];
const DARK_VIGN = [70, 55, 40];
const variations = [
{
name: '01_warm-sunset-cream',
label: 'Warm sunset · cream · huge cubic bleeding past frame',
overrides: {
substrate: 'cream',
stroke: 2.6,
cubicScale: 1.75,
schlegelScale: 0.85,
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
fields: {
cubic: F(0.10, 0.02, 0.65, 0.40, 0.82), // amber → red
schlegel: F(0.13, 0.06, 0.45, 0.38, 0.65), // gold → orange
e8: F(0.05, 0.13, 0.75, 0.42, 0.92), // red → gold
links: F(0.95, 0.04, 0.85, 0.38, 0.96), // pink → red bright
},
},
},
{
name: '02_pale-verdigris-linen',
label: 'Pale verdigris · linen ground · large scales',
overrides: {
paperOverride: paper([222, 210, 184]),
vignOverride: DARK_VIGN,
featureOverride: DARK_FEATURE,
stroke: 2.4,
cubicScale: 1.55,
schlegelScale: 1.35,
e8Count: 3, e8Scale: 0.24, e8OriginRadius: 0.48,
fields: {
cubic: F(0.44, 0.50, 0.55, 0.34, 0.82), // teal → cyan
schlegel: F(0.06, 0.10, 0.55, 0.38, 0.66), // copper accents
e8: F(0.35, 0.46, 0.60, 0.32, 0.90), // sage → teal
links: F(0.04, 0.10, 0.80, 0.38, 0.95),
},
},
},
{
name: '03_rose-peach',
label: 'Rose pastel on peach paper · huge cubic',
overrides: {
paperOverride: paper([232, 200, 175]),
vignOverride: [90, 50, 40],
featureOverride: [110, 60, 50],
stroke: 2.8,
cubicScale: 1.65,
schlegelScale: 0.75, schlegelOriginX: 0.20,
e8Count: 2, e8Scale: 0.28, e8OriginRadius: 0.52,
fields: {
cubic: F(0.92, 0.04, 0.55, 0.42, 0.82),
schlegel: F(0.88, 0.94, 0.45, 0.40, 0.66),
e8: F(0.96, 0.06, 0.65, 0.42, 0.92),
links: F(0.90, 0.04, 0.85, 0.38, 0.96),
},
},
},
{
name: '04_pale-sky-ivory',
label: 'Pale sky · ivory · huge Schlegel tesseract',
overrides: {
paperOverride: paper([232, 222, 200]),
vignOverride: [60, 50, 40],
featureOverride: DARK_FEATURE,
stroke: 2.4,
cubicScale: 0.70,
schlegelScale: 1.95, // massive — bleeds significantly
e8Count: 3, e8Scale: 0.20, e8OriginRadius: 0.60,
fields: {
cubic: F(0.58, 0.66, 0.55, 0.30, 0.80), // blue → violet
schlegel: F(0.62, 0.72, 0.55, 0.32, 0.66), // indigo → violet
e8: F(0.55, 0.70, 0.65, 0.30, 0.92),
links: F(0.60, 0.80, 0.85, 0.32, 0.96),
},
},
},
{
name: '05_mint-gold-pale',
label: 'Mint & gold · pale-mint ground',
overrides: {
paperOverride: paper([210, 225, 208]),
vignOverride: [30, 55, 35],
featureOverride: [40, 70, 45],
stroke: 2.6,
cubicScale: 1.50,
schlegelScale: 1.25,
e8Count: 3, e8Scale: 0.26, e8OriginRadius: 0.48,
fields: {
cubic: F(0.40, 0.50, 0.55, 0.30, 0.82), // mint teal
schlegel: F(0.10, 0.16, 0.60, 0.36, 0.66), // gold
e8: F(0.13, 0.20, 0.80, 0.40, 0.92),
links: F(0.08, 0.14, 0.85, 0.40, 0.96),
},
},
},
{
name: '06_bone-radial-gradient',
label: 'Bone china · radial gradient (cool centre → warm edges)',
overrides: {
paperOverride: paper([234, 230, 222]),
vignOverride: [70, 60, 50],
featureOverride: DARK_FEATURE,
stroke: 2.6, gradientMode: 'radial',
cubicScale: 1.55, schlegelScale: 1.30,
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
fields: {
cubic: F(0.55, 0.06, 0.62, 0.36, 0.82), // cyan centre → orange edges
schlegel: F(0.58, 0.04, 0.50, 0.34, 0.70),
e8: F(0.55, 0.05, 0.72, 0.40, 0.92),
links: F(0.55, 0.05, 0.85, 0.40, 0.96),
},
},
},
{
name: '07_pale-mauve-violet',
label: 'Pale mauve fog · violet → pink gradients · thick',
overrides: {
paperOverride: paper([222, 205, 224]),
vignOverride: [55, 35, 60],
featureOverride: [75, 50, 90],
stroke: 3.0,
cubicScale: 1.85, // bleeds heavily
schlegelScale: 0.90,
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.50,
fields: {
cubic: F(0.74, 0.92, 0.55, 0.34, 0.84),
schlegel: F(0.78, 0.86, 0.50, 0.32, 0.68),
e8: F(0.82, 0.96, 0.65, 0.38, 0.92),
links: F(0.78, 0.95, 0.85, 0.36, 0.96),
},
},
},
{
name: '08_faded-blueprint',
label: 'Faded blueprint · pale cyan paper · huge Schlegel',
overrides: {
paperOverride: paper([186, 214, 228]),
vignOverride: [40, 55, 70],
featureOverride: [30, 50, 75],
stroke: 2.8,
cubicScale: 0.80,
schlegelScale: 1.90,
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
fields: {
cubic: F(0.60, 0.66, 0.60, 0.22, 0.86), // dark blue → navy
schlegel: F(0.58, 0.62, 0.55, 0.20, 0.66),
e8: F(0.62, 0.72, 0.70, 0.28, 0.92),
links: F(0.58, 0.68, 0.85, 0.28, 0.96),
},
},
},
{
name: '09_linen-sepia-large',
label: 'Linen · warm sepia gradients · everything LARGE · thickest strokes',
overrides: {
paperOverride: paper([226, 210, 178]),
vignOverride: [80, 55, 30],
featureOverride: [85, 55, 30],
stroke: 3.4, // chunkiest of the set
cubicScale: 1.65, schlegelScale: 1.55,
e8Count: 3, e8Scale: 0.28, e8OriginRadius: 0.50,
fields: {
cubic: F(0.06, 0.12, 0.55, 0.30, 0.86),
schlegel: F(0.10, 0.03, 0.45, 0.28, 0.70),
e8: F(0.08, 0.16, 0.70, 0.36, 0.92),
links: F(0.02, 0.12, 0.85, 0.30, 0.96),
},
},
},
{
name: '10_pearl-pastel-spectrum',
label: 'Pearl · pastel rainbow (per-field hue families)',
overrides: {
paperOverride: paper([240, 235, 230]),
vignOverride: [70, 65, 60],
featureOverride: [80, 70, 60],
stroke: 2.8,
cubicScale: 1.50, schlegelScale: 1.40,
e8Count: 3, e8Scale: 0.24, e8OriginRadius: 0.55,
fields: {
cubic: F(0.55, 0.70, 0.50, 0.42, 0.80), // cyan → violet pastel
schlegel: F(0.08, 0.18, 0.45, 0.42, 0.62), // gold → yellow pastel
e8: F(0.86, 0.04, 0.55, 0.42, 0.86), // pink → red pastel
links: F(0.38, 0.55, 0.70, 0.40, 0.94), // green → cyan pastel
},
},
},
];
const base = paramsFromSeed(BASE_SEED);
for (const v of variations) {
const params = { ...base, ...v.overrides };
if (v.overrides.fields) params.fields = v.overrides.fields;
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
const path = `${OUT_DIR}/${v.name}.svg`;
writeFileSync(path, svg);
console.log(`ok ${v.name} · ${v.label}`);
}
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);