vast ocean

This commit is contained in:
2026-05-30 06:42:16 -04:00
parent e38f11f71a
commit 52453fba67
68 changed files with 1704 additions and 66 deletions

View File

@@ -44,6 +44,9 @@ export function renderSVG(scene, params, sizePx = 4800) {
const paperRGB = pal.paper(); // {flat,glowIn,glowOut} rgb arrays
const paperC = { flat: rgbHex(paperRGB.flat), glowIn: rgbHex(paperRGB.glowIn), glowOut: rgbHex(paperRGB.glowOut) };
const ink = rgbHex(pal.feature()); // non-particle marks (optics, disk, damage, header)
// diskPressure: a darker, denser core (compressed gas = higher pressure)
const press = Math.max(0, Math.min(1, params.diskPressure ?? 0));
const coreInk = rgbHex(mix(pal.feature(), [0, 0, 0], press * 0.7));
const featKey = rgbKey(pal.feature());
const colorMap = new Map([[featKey, pal.feature()]]); // distinct bubble colours → gradients
@@ -52,7 +55,9 @@ export function renderSVG(scene, params, sizePx = 4800) {
content ? `<g id="${id}" inkscape:groupmode="layer" inkscape:label="${attr(label)}" style="display:inline"${extra ? ' ' + extra : ''}>\n${content}\n</g>\n` : '';
/* ---------- Background ---------- */
const bg = `<rect width="${w}" height="${h}" fill="${paperC.flat}"/>\n<rect width="${w}" height="${h}" fill="url(#paper)"/>`;
// transparentPaper: omit paper + vignette so the event can float as an object
// over another layer (e.g. the QFT carpet) without a paper rectangle.
const bg = params.transparentPaper ? '' : `<rect width="${w}" height="${h}" fill="${paperC.flat}"/>\n<rect width="${w}" height="${h}" fill="url(#paper)"/>`;
/* ---------- Chamber optics ---------- */
let optics = '';
@@ -206,7 +211,7 @@ export function renderSVG(scene, params, sizePx = 4800) {
}
/* ---------- Vignette ---------- */
const vign = params.vign > 0 ? `<rect width="${w}" height="${h}" fill="url(#vign)"/>` : '';
const vign = (params.vign > 0 && !params.transparentPaper) ? `<rect width="${w}" height="${h}" fill="url(#vign)"/>` : '';
/* ---------- Header ---------- */
let header = '';
@@ -258,7 +263,8 @@ export function renderSVG(scene, params, sizePx = 4800) {
media += `</g>`;
}
if (M.grease && M.grease.length) {
const ch = inv ? '#9c1e1e' : '#f0e296';
// annotateInk overrides the chinagraph colour (e.g. white pencil)
const ch = params.annotateInk || (inv ? '#9c1e1e' : '#f0e296');
let g = `<g stroke="${ch}" fill="${ch}" stroke-linecap="round" stroke-linejoin="round">`;
for (const gm of M.grease) {
if (gm.kind === 'ring' || gm.kind === 'arrow') {
@@ -288,7 +294,7 @@ export function renderSVG(scene, params, sizePx = 4800) {
let s = `<?xml version="1.0" encoding="UTF-8"?>\n`;
s += `<svg xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">\n`;
s += `<metadata>Bubble Chamber · seed=${params.seed} · hash=${cyrb53(params.seed)} · palette=${params.palette || 'mono'}</metadata>\n`;
s += defs({ paperC, ink, baseVign: pal.vign(), params, u, colorMap });
s += defs({ paperC, ink, coreInk, press, baseVign: pal.vign(), params, u, colorMap });
s += layer('background', 'Background', bg);
s += layer('optics', 'Chamber optics', optics);
s += layer('shock', 'Shock disk', shock, params.diskSoften > 0 ? 'filter="url(#soften)"' : '');
@@ -302,7 +308,7 @@ export function renderSVG(scene, params, sizePx = 4800) {
return s;
}
function defs({ paperC, ink, baseVign, params, u, colorMap }) {
function defs({ paperC, ink, coreInk, press = 0, baseVign, params, u, colorMap }) {
const soften = params.diskSoften > 0
? `<filter id="soften" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="${(params.diskSoften * u).toFixed(2)}"/></filter>`
: '';
@@ -324,8 +330,9 @@ function defs({ paperC, ink, baseVign, params, u, colorMap }) {
</radialGradient>
${bubGrads}
<radialGradient id="shockcore" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="${ink}" stop-opacity="0.5"/>
<stop offset="60%" stop-color="${ink}" stop-opacity="0.28"/>
<stop offset="0%" stop-color="${coreInk || ink}" stop-opacity="${(0.5 + press * 0.45).toFixed(2)}"/>
<stop offset="28%" stop-color="${coreInk || ink}" stop-opacity="${(0.32 + press * 0.32).toFixed(2)}"/>
<stop offset="62%" stop-color="${ink}" stop-opacity="0.28"/>
<stop offset="100%" stop-color="${ink}" stop-opacity="0"/>
</radialGradient>
<radialGradient id="shockstain" cx="50%" cy="50%" r="50%">