Perlin Noise Notebook

Cell 1: White Noise

Generate 1D white noise (purely random) and plot it.

// generate random height‐values and plot them const width = 500, height = 200; const data = Array.from({length: width}, () => Math.random() * height); const canvas = document.getElementById("cnv1"); const ctx = canvas.getContext("2d"); ctx.clearRect(0,0,width,height); ctx.strokeStyle = "#00FF00"; // ← vintage oscilloscope green ctx.beginPath(); ctx.moveTo(0, height - data[0]); data.forEach((d,i) => ctx.lineTo(i, height - d)); ctx.stroke();

Cell 2: Smoothed Noise via Linear Interpolation

Pick random values on a coarse grid and linearly interpolate between them.

// random base values & linear interpolation const width = 500, height = 200, grid = 10; const base = Array.from({length:grid}, () => Math.random() * height); const smooth = new Array(width); const cellSize = width / (grid - 1); for (let x = 0; x < width; x++) { const fx = x / cellSize, i0 = Math.floor(fx), i1 = Math.min(i0 + 1, grid - 1), t = fx - i0; smooth[x] = base[i0] + (base[i1] - base[i0]) * t; } const canvas = document.getElementById("cnv2"), ctx = canvas.getContext("2d"); ctx.clearRect(0,0,width,height); ctx.strokeStyle = "#00FF00"; // ← vintage oscilloscope green ctx.beginPath(); ctx.moveTo(0, height - smooth[0]); for (let x = 1; x < width; x++) { ctx.lineTo(x, height - smooth[x]); } ctx.stroke();

Cell 3: 1D Perlin Noise & Fade Curve

Perlin noise picks a random gradient (±1 here) at each integer, computes dot‐products with the distance, and then blends via the “fade” curve 6t⁵−15t⁴+10t³.

// fade, lerp, gradient, p‐array shuffle, 1D Perlin, plus plotting function fade(t) { return t*t*t*(t*(t*6 - 15) + 10); } function lerp(a,b,t) { return a + (b - a)*t; } function grad1(hash,x) { return (hash & 1) === 0 ? x : -x; } // build permutation table const p = new Uint8Array(512); (() => { const perm = Array.from({length:256},(_,i)=>i); for (let i = 255; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [perm[i], perm[j]] = [perm[j], perm[i]]; } for (let i = 0; i < 256; i++) { p[i] = p[i+256] = perm[i]; } })(); function noise1D(x) { const xi = Math.floor(x) & 255, xf = x - Math.floor(x), u = fade(xf), a = grad1(p[xi], xf), b = grad1(p[xi+1], xf-1); return lerp(a, b, u); } // draw fade curve const fadeC = document.getElementById("fadeC"), fctx = fadeC.getContext("2d"), Wf = fadeC.width, Hf = fadeC.height; fctx.clearRect(0,0,Wf,Hf); fctx.strokeStyle = "#00FF00"; // ← vintage oscilloscope green fctx.beginPath(); for (let i=0; i<=Wf; i++) { const t = i/Wf, y = (1 - fade(t)) * Hf; if (i===0) fctx.moveTo(i,y); else fctx.lineTo(i,y); } fctx.stroke(); // draw noise const canvas = document.getElementById("cnv3"), ctx = canvas.getContext("2d"), W = canvas.width, H = canvas.height; ctx.clearRect(0,0,W,H); ctx.strokeStyle = "#00FF00"; // ← vintage oscilloscope green ctx.beginPath(); for (let x=0; x< W; x++) { const v = noise1D(x/50), y = (v*0.5 + 0.5)*H; if (x===0) ctx.moveTo(x, H-y); else ctx.lineTo(x, H-y); } ctx.stroke();

Cell 4: Interactive 2D Fractal Perlin Noise

Combine multiple octaves (fBm). Tweak sliders and watch the texture update.