new p5(sketch => { sketch.disableFriendlyErrors = true; // reused dimensions and a seed let seed, width, height, noiseResolution; // offscreen layers let noise; // shaders let whiteNoise; sketch.preload = () => { whiteNoise = sketch.loadShader( '../shaders/base.vert', '../shaders/white-noise.frag' ); } sketch.setup = () => { filenamePrefix = 'seigler-p5-3-peanut_butter_and_jelly-'; width = sketch.windowWidth; height = sketch.windowHeight; noiseResolution = [2, 2, 2, 2]; window.onhashchange = () => { seed = window.location.hash.substr(1); generate(); }; seed = window.location.hash.substr(1); sketch.noStroke(); sketch.colorMode(sketch.HSL, 1); sketch.createCanvas(width, height); noise = sketch.createGraphics(width, height, sketch.WEBGL); noise.noStroke(); generate(); }; sketch.draw = () => { }; sketch.keyPressed = () => { if (sketch.key == ' ') { seed = null; generate(); } else if (sketch.key == 's') { sketch.saveCanvas(filenamePrefix + seed + '.jpg', 'jpg'); } }; sketch.doubleClicked = () => { seed = null; generate(); }; let resizeTimer; sketch.windowResized = () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { window.location.reload(); }, 100); }; function generate() { if (seed) { sketch.randomSeed(seed); } else { let seed = Math.floor(sketch.random(1000000000000)); window.location.hash = seed; sketch.randomSeed(seed); } sketch.noiseSeed(sketch.random(0, 1000000000)); sketch.blendMode(sketch.BLEND); sketch.background(291/360, 0.3, 0.25); let stripeAngle = sketch.random(0, Math.PI); let stripeWidth = Math.min(width, height) / sketch.random(10, 80); let stripeLength = Math.max(width, height) * Math.SQRT2; let numStripes = Math.ceil(Math.SQRT2 * stripeLength / stripeWidth); let ox = width/2, oy = height/2; let dx = Math.cos(stripeAngle) * stripeLength / 2; let dy = Math.sin(stripeAngle) * stripeLength / 2; sketch.strokeCap(sketch.SQUARE); for (let i = Math.ceil(numStripes / 2); i > 0; i--) { sketch.stroke(291/360, 0.3, 0.2 + 0.1 * (i % 2)); sketch.strokeWeight((i * 2 - 1) * stripeWidth); sketch.line(ox - dx, oy - dy, ox + dx, oy + dy); } noise.shader(whiteNoise); whiteNoise.setUniform('u_resolution', [width, height]); whiteNoise.setUniform('u_alpha', 0.05); noise.rect(0, 0, width, height); sketch.blendMode(sketch.OVERLAY); sketch.image(noise, 0, 0); // square pixels per circle, helps with gridding sketch.blendMode(sketch.BLEND); sketch.strokeCap(sketch.ROUND); let unit = 5; let rows = Math.max(1, Math.round(height / unit)) + 1; let cols = Math.max(1, Math.round(width / unit)) + 1; let noiseOffset = 1000.37; let gridPoints = []; for (let index = 0; index < rows * cols; index++) { let col = index % cols; let row = Math.floor(index / cols); let noise = noiseResolution.map( (resolution, noiseIndex) => { let gridScale = resolution / Math.min(rows, cols); return sketch.noise( noiseOffset * noiseIndex + row * gridScale, noiseOffset * noiseIndex + col * gridScale ) } ); gridPoints.push({ row, col, noise }); } shuffle(gridPoints); let angleOffset = sketch.random(0, 2*Math.PI); gridPoints.forEach(({row, col, noise: [n0, n1, n2, n3]}, index) => { if (sketch.random() > n0 * 1.75 - 0.5) { return; } let x = width / (cols - 1) * col - unit / 2; let y = height / (rows - 1) * row - unit / 2; let angle = 2 * Math.PI * flattenPerlin(n2) + angleOffset; let length = (8 * n3* n3 + 1) * unit; sketch.stroke( 27 / 360, // hue 0.5, // saturation n1 - 0.2 * (index / gridPoints.length) + 0.1 // lightness ); sketch.strokeWeight(unit * (1 + 2 * n3 * n3 * n3)); sketch.line( x - length * Math.cos(angle), y - length * Math.sin(angle), x + length * Math.cos(angle), y + length * Math.sin(angle) ); }); } function shuffle(array) { // Fisher-Yates shuffle var i = 0, j = 0, temp = null; for (i = array.length - 1; i > 0; i -= 1) { j = Math.floor(sketch.random() * (i + 1)); temp = array[i]; array[i] = array[j]; array[j] = temp; } } function flattenPerlin(x) { return 23.8615 * Math.pow(x, 5) - 59.6041 * Math.pow(x, 4) + 47.2472 * Math.pow(x, 3) - 11.3053 * Math.pow(x, 2) + 0.806219 * x - 0.00259101; } });