0x01876c26…01casent to0xbd11994a…7699·#25,476,499·view on Etherscan
Resonance drawingContext.lineJoin = 'round';
for (let i = 0; i < numStrokes; i++) {
const tBase = (i + 0.3 + 0.4 * rnd()) / numStrokes;
const s = tBase * totalLen;
const { x, y, tx, ty } = sampleAt(s);
const hairRoll = rnd();
const numHairs = hairRoll < 0.65 ? 1 : (hairRoll < 0.92 ? 2 : 3);
for (let h = 0; h < numHairs; h++) {
const strokeLen = baseWeight * (0.9 + 3.1 * rnd());
const baseAng = Math.atan2(ty, tx);
const angJitter = (rnd() - 0.5) * 0.55;
const a = baseAng + angJitter;
const perpDist = (rnd() - 0.5) * (1.4 * M + baseWeight * 0.9);
const px = -ty * perpDist;
const py = tx * perpDist;
const cosA = Math.cos(a), sinA = Math.sin(a);
const cx = x + px;
const cy = y + py;
const x1 = cx - cosA * strokeLen / 2;
const y1 = cy - sinA * strokeLen / 2;
const x2 = cx + cosA * strokeLen / 2;
const y2 = cy + sinA * strokeLen / 2;
const variant = variants[Math.floor(rnd() * variants.length)];
const alpha = Math.floor((90 + rnd() * 130) * energyFactor);
const w = baseWeight * (0.30 + 0.95 * Math.pow(rnd(), 1.35));
drawingContext.strokeStyle = `rgba(${variant.r},${variant.g},${variant.b},${alpha / 255})`;
drawingContext.lineWidth = w;
drawingContext.beginPath();
drawingContext.moveTo(x1, y1);
drawingContext.lineTo(x2, y2);
drawingContext.stroke();
}
}
pop();
}
function drawSmoothCurve(pts) {
beginShape();
curveVertex(pts[0].x, pts[0].y);
for (const p of pts) curveVertex(p.x, p.y);
curveVertex(pts[pts.length - 1].x, pts[pts.length - 1].y);
endShape();
}
function drawAnnotations(P) {
const inkCol = color(P.ink);
push();
stroke(red(inkCol), green(inkCol), blue(inkCol), 130);
strokeWeight(0.6);
drawingContext.lineCap = 'butt';
const margin = canvasSize * 0.058;
const ruleY = margin * 0.6;
const tickStart = margin, tickEnd = canvasSize - margin;
line(tickStart, ruleY, tickEnd, ruleY);
const numTicks = 24;
for (let i = 0; i <= numTicks; i++) {
const x = tickStart + (tickEnd - tickStart) * (i / numTicks);
const tickLen = (i % 4 === 0) ? 6 : 3;
line(x, ruleY - tickLen, x, ruleY);
}
const sbY = canvasSize - margin * 0.6;
const sbX = canvasSize - margin - 80;
line(sbX, sbY, sbX + 60, sbY);
for (let i = 0; i <= 4; i++) {
line(sbX + i * 15, sbY, sbX + i * 15, sbY - 5);
}
pop();
}
function drawFrame(P) {
const margin = canvasSize * 0.04;
push();
noFill();
stroke(P.ink);
strokeWeight(1);
rect(margin, margin, canvasSize - 2 * margin, canvasSize - 2 * margin);
stroke(red(color(P.ink)), green(color(P.ink)), blue(color(P.ink)), 90);
strokeWeight(0.5);
rect(margin + 6, margin + 6, canvasSize - 2 * margin - 12, canvasSize - 2 * margin - 12);
pop();
}
function drawInkSplatter(P) {
const inkCol = color(P.ink);
const r = red(inkCol), g = green(inkCol), b = blue(inkCol);
push();
noStroke();
const numFine = 600;
for (let i = 0; i < numFine; i++) {
const u = rnd(), v = rnd();
const lf = sampleField(lowGrid, u, v);
if (rnd() > Math.abs(lf) * 0.6 + 0.05) continue;
const a = rrange(20, 90);
fill(r, g, b, a);
const sz = rrange(0.5, 1.6);
circle(u * canvasSize, v * canvasSize, sz);
}
const numLarge = 12;
for (let i = 0; i < numLarge; i++) {
const u = rnd(), v = rnd();
fill(r, g, b, rrange(50, 100));
const sz = rrange(1.8, 4.5);
circle(u * canvasSize, v * canvasSize, sz);
if (rchance(0.6)) {
fill(r, g, b, 25);
circle(u * canvasSize, v * canvasSize, sz * 2.5);
}
}
pop();
}
function drawFinalOverlay(P) {
const G = 384;
const small = createImage(G, G);
small.loadPixels();
for (let i = 0; i < G * G; i++) {
const v = (rnd() - 0.5) * 12;
const a = Math.abs(v);
small.pixels[i * 4 + 0] = 0;
small.pixels[i * 4 + 1] = 0;
small.pixels[i * 4 + 2] = 0;
small.pixels[i * 4 + 3] = a;
}
small.updatePixels();
push();
drawingContext.globalCompositeOperation = 'multiply';
drawingContext.imageSmoothingEnabled = false;
image(small, 0, 0, canvasSize, canvasSize);
drawingContext.imageSmoothingEnabled = true;
drawingContext.globalCompositeOperation = 'source-over';
pop();
push();
const grd = drawingContext.createRadialGradient(
canvasSize / 2, canvasSize / 2, canvasSize * 0.45,
canvasSize / 2, canvasSize / 2, canvasSize * 0.78
);
grd.addColorStop(0, 'rgba(0,0,0,0)');
grd.addColorStop(1, 'rgba(0,0,0,0.10)');
drawingContext.fillStyle = grd;
drawingContext.fillRect(0, 0, canvasSize, canvasSize);
pop();
}
function mousePressed() {
if (seedLocked) return; // canonical on-chain piece — don't re-roll
if (mouseX < 0 || mouseX > canvasSize || mouseY < 0 || mouseY > canvasSize) return;
seed = Math.floor(Math.random() * 999999);
location.hash = String(seed);
generate();
}
function keyPressed() {
if (key === 's' || key === 'S') {
saveCanvas('Resonance_' + seed, 'png');
} else if (key === 'p' || key === 'P') {
exportPrintPng();
} else if (!seedLocked && keyCode === LEFT_ARROW) {
seed = Math.max(1, seed - 1);
location.hash = String(seed);
generate();
} else if (!seedLocked && keyCode === RIGHT_ARROW) {
seed = seed + 1;
location.hash = String(seed);
generate();
}
}
function exportPrintPng() {
if (!composition) return;
const screenSize = canvasSize;
const screenM = M;
const screenDensity = pixelDensity();
const t0 = performance.now();
console.log(`exporting ${PRINT_EXPORT_SIZE}x${PRINT_EXPORT_SIZE} print PNG...`);
try {
pixelDensity(PRINT_EXPORT_PIXEL_DENSITY);
canvasSize = PRINT_EXPORT_SIZE;
M = canvasSize / DEFAULT_SIZE;
resizeCanvas(canvasSize, canvasSize);
renderPaper();
renderArtwork();
saveCanvas('Resonance_' + seed, 'png');
} finally {
pixelDensity(screenDensity || SCREEN_PIXEL_DENSITY);
canvasSize = screenSize;
M = screenM;
resizeCanvas(canvasSize, canvasSize);
renderPaper();
needsRender = true;
redraw();
}
const t1 = performance.now();
console.log(`print export ${(t1 - t0).toFixed(0)} ms`);
}
function windowResized() {
const newSize = Math.floor(Math.min(window.innerWidth, window.innerHeight));
if (newSize !== canvasSize) {
canvasSize = newSize;
M = canvasSize / DEFAULT_SIZE;
pixelDensity(SCREEN_PIXEL_DENSITY);
resizeCanvas(canvasSize, canvasSize);
if (composition) {
renderPaper();
}
needsRender = true;
redraw();
}
}