canvas {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
let yseed = 0;
let xseed = 1000;
let yoff = 0;

const size = Math.min(window.innerWidth * 0.9, window.innerHeight * 0.9);

function setup() {
  createCanvas(size, size);
  background(252);
  frameRate(1);
}

function draw() {
  background("#fff");
  noiseShape(0, 0, width, height, yoff);
  yoff = random(1000);
  grain(1000);
}

function noiseShape(oX, oY, w, h, yoff) {
  const inc = 30;

  push();
  translate(oX, oY);
  for (let x = 0; x <= w; x += inc) {
    let xoff = 0;
    for (let y = 0; y <= h; y += inc) {
      const n = map(noise(xoff, yoff), 0, 1, 0.1, 6);

      wonkyCircle(x, y, inc / 2, n);
      xoff += 0.05;
    }
    yoff += 0.05;
  }
  pop();
}

function wonkyCircle(oX, oY, rad, n) {
  const points = [];
  push();
  translate(oX, oY);
  noFill();
  stroke("#17183B");
  beginShape();
  const xMult = 1;
  const yMult = 1;
  for (let i = 0; i < TWO_PI; i += n) {
    const xoff = map(cos(i), -1, 1, 0, 0.1);
    const yoff = map(sin(i), -1, 1, 0, 0.1);
    const radius = map(noise(xoff, yoff), 0, 1, rad / 2, rad);
    const x = radius * cos(i) * xMult;
    const y = radius * sin(i) * yMult;
    vertex(x, y);
    points.push({ x, y });
  }
  endShape(CLOSE);

  for (let i = 0; i < floor(random(150)); i++) {
    const p1 = points[floor(random(points.length))];
    const p2 = points[floor(random(points.length))];

    const { x, y } = p1;
    const { x: x1, y: y1 } = p2;

    wonkyLine(x, y, x1, y1, 0.0125);
  }
  pop();
}

class WonkyLine {
  constructor(x, y, x1, y1, roughness) {
    this.x = x;
    this.y = y;
    this.x1 = x1;
    this.y1 = y1;
    this.roughness = roughness;
  }

  draw() {
    const d = dist(this.x, this.y, this.x1, this.y1);
    let xoff = random(1000);
    push();
    translate(this.x, this.y);
    rotate(atan2(this.y1 - this.y, this.x1 - this.x));
    noFill();
    beginShape();
    for (let x = 0; x < d; x += 1) {
      const n = map(noise(xoff), 0, 1, -5, 5);
      vertex(x, n);
      xoff += this.roughness;
    }
    endShape();
    pop();
  }
}

function wonkyLine(x, y, x1, y1, roughness = 0.01) {
  const line = new WonkyLine(x, y, x1, y1, roughness);
  line.draw();
}

function grain(num) {
  push();
  noStroke();
  // draw the bulk of the grain
  for (let i = 0; i < num; i++) {
    const x = random(width);
    const y = random(height);
    const w = random(1, 2);
    const h = random(1, 2);
    fill(random(200, 255), 100);
    rect(x, y, w, h);
  }
  // draw some dark grains
  for (let i = 0; i < num / 50; i++) {
    const x = random(width);
    const y = random(height);
    const w = random(1, 3);
    const h = random(1, 3);
    fill(250, random(240, 255));
    rect(x, y, w, h);
  }
  pop();
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js