Perlin noise
Log in to post a comment.
// Forked from "Gaussian mountains" by Alexjust // https://turtletoy.net/turtle/c0af204ebf Canvas.setpenopacity(-1); let dens = 5 // min=1, max=10, step=1 dens=1/dens const turtle = new Turtle(); const width = 90; const zstart = 80; const layer = dens*6; const layers = 27/dens; const perspective = 0.7*dens+0.07; turtle.penup(); let h=0; const leeway=29 // min=0, max=30, step=1 const amp=6 // min=-10, max=10, step=0.1 const res =1 // min=1, max=10, step=1 const rows = 600 const scale = 21.3 // min=0, max=40, step=0.1 const rad = 19 // min=0, max=50, step=1 const vermult = 1 // min=0, max=20, step=1 const cols = 600 const filledge = 1 //min=0, max=1, step=1 let gaussMat = generatePerlinNoiseMatrix(rows, cols, scale); gaussMat = applyGaussianBlur(gaussMat, rad) function walk(i) { const left = -width + perspective * i; const right = width - perspective * i; const z = zstart - layer * i; if (filledge==1){ turtle.penup(); turtle.goto(-500, z); turtle.pendown(); turtle.goto(left, z); turtle.penup(); turtle.goto(500, z); turtle.pendown(); turtle.goto(right, z); turtle.penup() } turtle.goto(left, z); let u = 0; for (let n = left; n < right; n += res) { if (n < left + leeway ) { h = z + gaussMat[u][i*vermult]*amp*(Math.sin((n-left)/leeway)*1.21603709862); console.log((Math.sin((n-left)/leeway)*1.21603709862)) } else if(n > right - leeway){ h = z + gaussMat[u][i*vermult]*amp*(Math.sin((right-n)/leeway)*1.21603709862); } else{ h = z + gaussMat[u][i*vermult]*amp; } turtle.goto(n, h); turtle.pendown(); u+=1; } turtle.goto(right, z); turtle.penup(); return i < layers; } function generateGaussianNoiseMatrix(rows, cols, scale, mean) { const noiseMatrix = []; for (let i = 0; i < rows; i++) { const row = []; for (let j = 0; j < cols; j++) { const u1 = 1 - Math.random(); const u2 = 1 - Math.random(); const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); const z1 = Math.sqrt(-2 * Math.log(u1)) * Math.sin(2 * Math.PI * u2); const noiseValue = mean + scale * z0; row.push(noiseValue); } noiseMatrix.push(row); } return noiseMatrix; } // Function to apply Gaussian blur to a matrix function applyGaussianBlur(matrix, radius) { const kernelSize = radius * 2 + 1; const kernel = []; for (let i = 0; i < kernelSize; i++) { const row = []; for (let j = 0; j < kernelSize; j++) { const x = i - radius; const y = j - radius; const weight = Math.exp(-(x * x + y * y) / (2 * radius * radius)); row.push(weight); } kernel.push(row); } const blurredMatrix = []; for (let i = 0; i < matrix.length; i++) { const newRow = []; for (let j = 0; j < matrix[i].length; j++) { let sum = 0; let totalWeight = 0; for (let ki = 0; ki < kernelSize; ki++) { for (let kj = 0; kj < kernelSize; kj++) { const mi = i - radius + ki; const mj = j - radius + kj; if (mi >= 0 && mi < matrix.length && mj >= 0 && mj < matrix[i].length) { sum += matrix[mi][mj] * kernel[ki][kj]; totalWeight += kernel[ki][kj]; } } } newRow.push(sum / totalWeight); } blurredMatrix.push(newRow); } return blurredMatrix; } function generatePerlinNoiseMatrix(width, height, frequency) { const grid = []; for (let i = 0; i < width; i++) { grid.push([]); for (let j = 0; j < height; j++) { const angle = Math.random() * 2 * Math.PI; grid[i].push({ x: Math.cos(angle), y: Math.sin(angle) }); } } function dotProductGradient(x, y, gradient) { return (x * gradient.x) + (y * gradient.y); } function interpolate(a, b, t) { return (1 - t) * a + t * b; } function smoothstep(t) { return t * t * (3 - 2 * t); } const noiseMatrix = []; for (let y = 0; y < height; y++) { noiseMatrix.push([]); for (let x = 0; x < width; x++) { const cellX = Math.floor(x / frequency); const cellY = Math.floor(y / frequency); const topLeft = dotProductGradient(x - cellX * frequency, y - cellY * frequency, grid[cellX][cellY]); const topRight = dotProductGradient(x - (cellX + 1) * frequency, y - cellY * frequency, grid[cellX + 1][cellY]); const bottomLeft = dotProductGradient(x - cellX * frequency, y - (cellY + 1) * frequency, grid[cellX][cellY + 1]); const bottomRight = dotProductGradient(x - (cellX + 1) * frequency, y - (cellY + 1) * frequency, grid[cellX + 1][cellY + 1]); const tx = smoothstep((x - cellX * frequency) / frequency); const ty = smoothstep((y - cellY * frequency) / frequency); const interpolateTop = interpolate(topLeft, topRight, tx); const interpolateBottom = interpolate(bottomLeft, bottomRight, tx); noiseMatrix[y].push(interpolate(interpolateTop, interpolateBottom, ty)); } } return noiseMatrix; }