initial remote
This commit is contained in:
@@ -135,7 +135,7 @@ export function renderCanvasPhoto(ctx, w, h, scene, params, opts = {}) {
|
||||
ic.globalAlpha = 1;
|
||||
|
||||
// 3c. shock disk drawn into the ink layer so bloom catches it
|
||||
if (scene.shock) drawShock(ic, scene.shock, tx, ty, scale, u, P);
|
||||
if (scene.shock) drawShock(ic, scene.shock, tx, ty, scale, u, P, params, sprite);
|
||||
|
||||
/* ---------- Pass 4: halation / bloom ---------- */
|
||||
// composite a blurred copy of the ink under the sharp ink for soft spread
|
||||
@@ -195,51 +195,63 @@ export function renderCanvasPhoto(ctx, w, h, scene, params, opts = {}) {
|
||||
}
|
||||
|
||||
/* ---- shock disk ---- */
|
||||
function drawShock(c, shock, tx, ty, scale, u, P) {
|
||||
function drawShock(c, shock, tx, ty, scale, u, P, params, sprite) {
|
||||
const [r, g, b] = P.ink;
|
||||
const px = tx(shock.x), py = ty(shock.y), R = shock.r * scale;
|
||||
const useBubbles = params.diskBubbles !== false;
|
||||
|
||||
// disk body: dark annulus that keeps a lighter, detailed centre
|
||||
// disk body: dark annulus that keeps a lighter, detailed centre.
|
||||
// softer when the line work is bubbles (the bubbles carry the density).
|
||||
const bodyK = useBubbles ? 0.6 : 1.0;
|
||||
const core = c.createRadialGradient(px, py, 0, px, py, R);
|
||||
core.addColorStop(0.0, `rgba(${r},${g},${b},${0.06 * shock.intensity})`);
|
||||
core.addColorStop(0.35, `rgba(${r},${g},${b},${0.18 * shock.intensity})`);
|
||||
core.addColorStop(0.72, `rgba(${r},${g},${b},${0.38 * shock.intensity})`);
|
||||
core.addColorStop(0.94, `rgba(${r},${g},${b},${0.34 * shock.intensity})`);
|
||||
core.addColorStop(0.0, `rgba(${r},${g},${b},${0.06 * shock.intensity * bodyK})`);
|
||||
core.addColorStop(0.35, `rgba(${r},${g},${b},${0.18 * shock.intensity * bodyK})`);
|
||||
core.addColorStop(0.72, `rgba(${r},${g},${b},${0.38 * shock.intensity * bodyK})`);
|
||||
core.addColorStop(0.94, `rgba(${r},${g},${b},${0.34 * shock.intensity * bodyK})`);
|
||||
core.addColorStop(1, `rgba(${r},${g},${b},0)`);
|
||||
c.fillStyle = core;
|
||||
c.beginPath(); c.arc(px, py, R, 0, Math.PI * 2); c.fill();
|
||||
|
||||
// radial striations (the sunburst)
|
||||
c.lineCap = 'round';
|
||||
for (const s of shock.striations) {
|
||||
const ix = px + Math.cos(s.a) * s.inner * scale;
|
||||
const iy = py + Math.sin(s.a) * s.inner * scale;
|
||||
const ox = px + Math.cos(s.a) * s.outer * scale;
|
||||
const oy = py + Math.sin(s.a) * s.outer * scale;
|
||||
const mx = (ix + ox) / 2 + Math.cos(s.a + Math.PI / 2) * s.wobble * scale;
|
||||
const my = (iy + oy) / 2 + Math.sin(s.a + Math.PI / 2) * s.wobble * scale;
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${s.opacity})`;
|
||||
c.lineWidth = s.width * u;
|
||||
c.beginPath();
|
||||
c.moveTo(ix, iy);
|
||||
c.quadraticCurveTo(mx, my, ox, oy);
|
||||
c.stroke();
|
||||
}
|
||||
|
||||
// inner pressure-front rings
|
||||
for (const ring of shock.rings) {
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${ring.opacity})`;
|
||||
c.lineWidth = ring.width * u;
|
||||
c.beginPath(); c.arc(px, py, ring.rr * scale, 0, Math.PI * 2); c.stroke();
|
||||
}
|
||||
|
||||
// rim as eroded arc segments
|
||||
if (shock.rimSegs) {
|
||||
for (const seg of shock.rimSegs) {
|
||||
if (useBubbles && shock.bubbleStrokes) {
|
||||
// describe striations / rings / rim / core with the particle method
|
||||
const dRng = makeRng(params.seed, 'diskbubbles');
|
||||
for (const stroke of shock.bubbleStrokes) {
|
||||
const bubs = sampleBubbles(stroke, params, dRng);
|
||||
c.globalAlpha = Math.min(1, 0.45 + stroke.weight * 0.5);
|
||||
for (const bb of bubs) {
|
||||
const rr = Math.max(bb.r * scale, 0.45);
|
||||
const d = rr * 2.4;
|
||||
c.drawImage(sprite, tx(bb.x) - d / 2, ty(bb.y) - d / 2, d, d);
|
||||
}
|
||||
}
|
||||
c.globalAlpha = 1;
|
||||
} else {
|
||||
// legacy: clean vector strokes
|
||||
c.lineCap = 'round';
|
||||
for (const s of shock.striations) {
|
||||
const ix = px + Math.cos(s.a) * s.inner * scale, iy = py + Math.sin(s.a) * s.inner * scale;
|
||||
const ox = px + Math.cos(s.a) * s.outer * scale, oy = py + Math.sin(s.a) * s.outer * scale;
|
||||
const mx = (ix + ox) / 2 + Math.cos(s.a + Math.PI / 2) * s.wobble * scale;
|
||||
const my = (iy + oy) / 2 + Math.sin(s.a + Math.PI / 2) * s.wobble * scale;
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${s.opacity})`;
|
||||
c.lineWidth = s.width * u;
|
||||
c.beginPath(); c.moveTo(ix, iy); c.quadraticCurveTo(mx, my, ox, oy); c.stroke();
|
||||
}
|
||||
for (const ring of shock.rings) {
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${ring.opacity})`;
|
||||
c.lineWidth = ring.width * u;
|
||||
c.beginPath(); c.arc(px, py, ring.rr * scale, 0, Math.PI * 2); c.stroke();
|
||||
}
|
||||
for (const seg of (shock.rimSegs || [])) {
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${seg.opacity})`;
|
||||
c.lineWidth = seg.width * u;
|
||||
c.beginPath(); c.arc(px, py, shock.r * scale, seg.a0, seg.a1); c.stroke();
|
||||
}
|
||||
for (const k of shock.core) {
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${k.opacity})`;
|
||||
c.lineWidth = k.width * u;
|
||||
c.beginPath(); c.moveTo(tx(k.x1), ty(k.y1)); c.lineTo(tx(k.x2), ty(k.y2)); c.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
// staining blotches: dark = grime, light = lifted/washed clean spots
|
||||
@@ -263,13 +275,6 @@ function drawShock(c, shock, tx, ty, scale, u, P) {
|
||||
c.globalCompositeOperation = 'source-over';
|
||||
}
|
||||
|
||||
// textured core chords
|
||||
for (const k of shock.core) {
|
||||
c.strokeStyle = `rgba(${r},${g},${b},${k.opacity})`;
|
||||
c.lineWidth = k.width * u;
|
||||
c.beginPath(); c.moveTo(tx(k.x1), ty(k.y1)); c.lineTo(tx(k.x2), ty(k.y2)); c.stroke();
|
||||
}
|
||||
|
||||
// keep a bright, detailed centre by clearing a soft hole in the ink
|
||||
if (shock.bright) {
|
||||
c.save();
|
||||
|
||||
Reference in New Issue
Block a user