xxxxxxxxxx
165
let grid;
let perlinImage;
let cols, rows;
let colW, rowH;
function setup()
{
createCanvas(256, 256);
noLoop();
cols = 16; rows = 16;
GeneratePerlin2D(width, height);
image(perlinImage, 0, 0);
}
function GeneratePerlin2D(w, h)
{
GenerateGrid();
// PrintGrid();
colW = w / cols;
rowH = h / rows;
perlinImage = createGraphics(w, h);
perlinImage.loadPixels();
let pixels = perlinImage.pixels;
for (let x = 0; x < w; ++x)
{
for (let y = 0; y < h; ++y)
{
let gray = ComputeGray(x, y);
let p = 4 * (w * y + x);
pixels[p + 0] = gray;
pixels[p + 1] = gray;
pixels[p + 2] = gray;
pixels[p + 3] = 255;
}
}
perlinImage.updatePixels();
}
function GenerateGrid()
{
grid = [];
for (let x = 0; x < cols; ++x)
{
let col = [];
for (let y = 0; y < rows; ++y)
{
col.push(MakeVector());
}
grid.push(col);
}
}
function PrintGrid()
{
function PrintRow(y)
{
function PrintVector(v)
{
let xs = nfs(v.x, 0, 1);
let ys = nfs(v.y, 0, 1);
return `(${xs}, ${ys}) `;
}
let rowStr = "| ";
for (let x = 0; x < cols; ++x)
rowStr += PrintVector(grid[x][y]);
return rowStr + "|\n";
}
let gridStr = "";
for (let x = 0; x < cols; ++x)
gridStr += PrintRow(x);
print(gridStr);
}
function MakeVector()
{
angleMode(DEGREES);
let angle = random(360.0);
return createVector(cos(angle), sin(angle));
}
function ComputeGray(pixelX, pixelY)
{
let dot = ComputeDot(pixelX, pixelY)
return 255 * (dot + 1) / 2;
}
function ComputeDot(pixelX, pixelY)
{
let x0 = int(pixelX / cols);
let x1 = (x0 + 1) % cols;
let y0 = int(pixelY / rows);
let y1 = (y0 + 1) % rows;
let p00 = createVector(x0 , y0 );
let p10 = createVector(x0 + 1, y0 );
let p01 = createVector(x0 , y0 + 1);
let p11 = createVector(x0 + 1, y0 + 1);
let cellX = pixelX % colW;
let cellY = pixelY % rowH;
let cellPoint = createVector(cellX / colW, cellY / rowH);
let diff00 = p5.Vector.sub(p00, cellPoint);
let diff10 = p5.Vector.sub(p10, cellPoint);
let diff01 = p5.Vector.sub(p01, cellPoint);
let diff11 = p5.Vector.sub(p11, cellPoint);
let vec00 = grid[x0][y0];
let vec10 = grid[x1][y0];
let vec01 = grid[x0][y1];
let vec11 = grid[x1][y1];
let dot00 = Dot(diff00, vec00);
let dot10 = Dot(diff10, vec10);
let dot01 = Dot(diff01, vec01);
let dot11 = Dot(diff11, vec11);
let i0 = Interpolate(dot00, dot10, cellX);
let i1 = Interpolate(dot01, dot11, cellX);
return Interpolate(i0, i1, cellY);
}
function Dot(v0, v1)
{
return p5.Vector.dot(v0, v1);
}
function Interpolate(t, min, max)
{
return (max - min) * Pow(t, 3.0) + min;
}
function Pow(t, p)
{
let a = (t) => pow(t, p);
let b = (t) => 1 - a(1 - t);
if (t < 0.5)
return a(2 * t) / 2;
return b(2 * t - 1) / 2;
}