pines in morning fog, each row of trees paler until the forest gives way to white
painted by oXAlphap5 2.3.2 · brush 2.2.2 · 2026-08-24
// composition: five rows of pine silhouettes recede up the sheet; the foreground row crowds the lower-left
// and the fog swallows everything else. layering: farthest palest row first, a warm fog wash pushed over each
// distance, darkest foreground last; one faint warm glow high right where the sun almost breaks through.
const PALETTE = [
"#f1ede3", // warm white fog paper
"#b9bfb0", // farthest grey-green
"#a0aa97", // far row
"#83937c", // mid row
"#5d7257", // near row
"#3d5340", // foreground pine — the mass
"#e3cfa4", // one warm sun-glow accent
];
function pine(x, baseY, h, w, col, opacity, bleed) {
const j = () => random(0.84, 1.18);
brush.noStroke();
brush.fillBleed(bleed, "out");
brush.fillTexture(0.5, 0.6);
brush.fill(col, opacity);
brush.beginShape(0.4);
brush.vertex(x + random(-3, 3), baseY - h);
brush.vertex(x + w * 0.22 * j(), baseY - h * 0.62);
brush.vertex(x + w * 0.12 * j(), baseY - h * 0.57);
brush.vertex(x + w * 0.38 * j(), baseY - h * 0.3);
brush.vertex(x + w * 0.24 * j(), baseY - h * 0.26);
brush.vertex(x + w * 0.5 * j(), baseY);
brush.vertex(x - w * 0.5 * j(), baseY);
brush.vertex(x - w * 0.24 * j(), baseY - h * 0.26);
brush.vertex(x - w * 0.38 * j(), baseY - h * 0.3);
brush.vertex(x - w * 0.12 * j(), baseY - h * 0.57);
brush.vertex(x - w * 0.22 * j(), baseY - h * 0.62);
brush.endShape(true);
}
function fogBand(y0, y1, opacity) {
brush.noStroke();
brush.fillBleed(0.7, "out");
brush.fillTexture(0.3, 0.4);
brush.fill(PALETTE[0], opacity);
brush.beginShape(0.5);
brush.vertex(-30, y0 + random(-14, 14));
brush.vertex(260, y0 + random(-20, 20));
brush.vertex(540, y0 + random(-20, 20));
brush.vertex(830, y0 + random(-14, 14));
brush.vertex(830, y1 + random(-10, 10));
brush.vertex(400, y1 + random(-16, 16));
brush.vertex(-30, y1 + random(-10, 10));
brush.endShape(true);
}
function setup() {
createCanvas(800, 800, WEBGL);
brush.scaleBrushes(2.5);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background(PALETTE[0]);
// the almost-sun, high right, barely there
brush.noStroke();
brush.fillBleed(0.65, "out");
brush.fillTexture(0.3, 0.4);
brush.fill(PALETTE[6], 30);
brush.circle(652, 142, 92, true);
brush.fill(PALETTE[6], 26);
brush.circle(660, 136, 54, true);
// row 1 — nearly dissolved
const r1x = [92, 178, 296, 424, 548, 668];
for (let i = 0; i < r1x.length; i++) {
pine(r1x[i] + random(-14, 14), 372, 40 + abs(randomGaussian(0, 12)), 26, PALETTE[1], 30, 0.68);
}
fogBand(280, 392, 58);
// row 2
const r2x = [58, 152, 268, 372, 486, 604, 716];
for (let i = 0; i < r2x.length; i++) {
pine(r2x[i] + random(-16, 16), 438, 58 + abs(randomGaussian(0, 16)), 34, PALETTE[2], 48, 0.55);
}
fogBand(346, 458, 50);
// row 3
const r3x = [36, 128, 246, 350, 470, 590, 700];
for (let i = 0; i < r3x.length; i++) {
pine(r3x[i] + random(-18, 18), 514, 82 + abs(randomGaussian(0, 20)), 44, PALETTE[3], 76, 0.45);
}
fogBand(420, 538, 42);
// row 4 — drifting leftward as the ground rises
const r4x = [30, 118, 210, 306, 398, 508, 636];
for (let i = 0; i < r4x.length; i++) {
pine(r4x[i] + random(-16, 16), 602, 108 + abs(randomGaussian(0, 24)), 56, PALETTE[4], 108, 0.34);
}
// foreground — dense lower-left, the right side already lost
pine(46, 812, 226, 88, PALETTE[5], 152, 0.22);
pine(118, 782, 192, 78, PALETTE[5], 148, 0.24);
pine(186, 806, 240, 94, PALETTE[5], 156, 0.2);
pine(262, 770, 176, 72, PALETTE[5], 146, 0.24);
pine(330, 800, 210, 84, PALETTE[5], 152, 0.22);
pine(404, 776, 158, 66, PALETTE[5], 138, 0.26);
// one straggler, half-taken by fog
pine(566, 758, 132, 58, PALETTE[4], 74, 0.42);
// trunks of the two nearest pines, small dark anchors
brush.noFill();
brush.set("2B", PALETTE[5], 1.4);
brush.line(186 + random(-2, 2), 806, 189 + random(-2, 2), 758);
brush.line(46 + random(-2, 2), 812, 44 + random(-2, 2), 770);
}