a fern crozier unrolling, drawn in one continuous graphite line
painted by Claude Fable 5p5 2.3.2 · brush 2.2.2 · 2026-08-24
// composition: one fern crozier unrolling at the lower-right thirds crossing; the stem enters from the bottom edge and the rest stays empty cream
// layering: green wash pads under the coil first, then a single continuous 2B line — stem into spiral — then a faint 2H echo on the outer turn
const PALETTE = [
"#f3eedc", // cream paper
"#74845e", // fern green
"#9aa87c", // pale green pad
"#4b4741", // graphite
];
const CX = 538;
const CY = 508;
function spiralPoint(k) {
const a = Math.PI / 2 + k * 0.085;
const r = 150 * Math.exp(-0.155 * k * 0.085);
return [CX + Math.cos(a) * r, CY + Math.sin(a) * r];
}
function setup() {
createCanvas(800, 800, WEBGL);
brush.scaleBrushes(2.3);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background("#f3eedc");
// furled pinnae: wash pads spaced along the coil, shrinking inward
brush.noStroke();
brush.fillBleed(0.45, "out");
brush.fillTexture(0.55, 0.55);
const padK = [2, 14, 26, 38, 50, 62, 76, 92, 110];
for (let i = 0; i < 9; i++) {
const p = spiralPoint(padK[i]);
const a = Math.PI / 2 + padK[i] * 0.085;
const off = 9 + random(-2, 3);
const col = i % 2 === 0 ? "#74845e" : "#9aa87c";
brush.fill(col, 96 + random(-14, 30));
brush.circle(p[0] + Math.cos(a) * off, p[1] + Math.sin(a) * off, 15 - i * 1.1 + random(-1, 1), true);
}
// two small pads where leaflets are only beginning, along the stem
brush.fill("#9aa87c", 78);
brush.circle(586, 726, 8, true);
brush.fill("#74845e", 90);
brush.circle(566, 682, 7, true);
// one pad dropped on the paper, away from the plant
brush.fill("#9aa87c", 58);
brush.circle(452, 726, 6, true);
// the single continuous line: stem from the bottom edge, then the coil
const pts = [];
pts.push([622 + random(-2, 2), 806]);
pts.push([612, 758]);
pts.push([598, 718]);
pts.push([578, 688]);
pts.push([557, 668]);
for (let k = 0; k <= 200; k += 2) pts.push(spiralPoint(k));
brush.noFill();
brush.set("2B", "#4b4741", 1.25);
for (let i = 0; i < pts.length - 1; i += 12) {
const end = Math.min(i + 13, pts.length);
brush.beginShape(0.4);
for (let m = i; m < end; m++) {
brush.vertex(pts[m][0] + random(-0.7, 0.7), pts[m][1] + random(-0.7, 0.7));
}
brush.endShape(false);
}
// a fainter second thought along the outer turn
brush.set("2H", "#4b4741", 0.7);
brush.beginShape(0.4);
for (let k = 0; k <= 66; k += 6) {
const a = Math.PI / 2 + k * 0.085;
const p = spiralPoint(k);
brush.vertex(p[0] + Math.cos(a) * 3 + random(-0.6, 0.6), p[1] + Math.sin(a) * 3 + random(-0.6, 0.6));
}
brush.endShape(false);
// hairs on the young stem
brush.set("2H", "#4b4741", 0.55);
brush.line(604, 742, 611, 738);
brush.line(592, 706, 599, 701);
brush.line(571, 679, 577, 672);
brush.line(613, 774, 620, 771);
brush.line(548, 660, 552, 653);
}