Put down your desired configuration in the input fields and a perlin noise map will be generated!
xxxxxxxxxx
// Made by Sichen Liu @lil_sichen
// Thanks to Sebastian Lague, who provided the algorithm for perlin generation
// with his Unity procedural generation tutorial
let width = 800;
let height = 800;
//Configuration
let noiseScale = 800,
octave = 3,
persistence = 1,
lacunarity = 1;
//UI
let greeting, notice,
scaleInput, octaveInput, persistenceInput, lacunarityInput,
scaleText, octaveText, persistenceText, lacunarityText,
button, saveButton;
// Other
// When generation is over, data is stored in noiseMap
var noiseMap;
var drawSpeed = 3200;
var noiseGen;
var drawComplete = false;
var img;
function setup() {
// increased width to include UI
img = createImage(width, height); // same as new p5.Image(100, 100);
img.loadPixels();
createCanvas(width + 300, height);
background(255);
setupUI();
refreshMap();
}
function setupUI() {
greeting = createElement('h2', 'Configuration');
greeting.position(width, 5);
notice = createElement('bold', "There is a with p5 or openprocessing atm so the number inputs are blocked. You can use the up/down buttons instead");
notice.position(width, 60);
scaleText = createElement("bold", "Scale");
scaleText.position(width, 120);
scaleInput = createInput(noiseScale, "number");
scaleInput.position(width + 100, 120);
octaveText = createElement("bold", "Octave");
octaveText.position(width, 150);
octaveInput = createInput(octave, "number");
octaveInput.position(octaveText.x + 100, 150);
persistenceText = createElement("bold", "Persistence");
persistenceText.position(width, 180);
persistenceInput = createInput(persistence, "number");
persistenceInput.position(persistenceText.x + 100, 180);
lacunarityText = createElement("bold", "Lacunarity");
lacunarityText.position(width, 210);
lacunarityInput = createInput(lacunarity, "number");
lacunarityInput.position(lacunarityText.x + 100, 210);
button = createButton('Generate');
button.position(width, 240);
button.mousePressed(refreshMap);
saveButton = createButton('Save Texture as PNG');
saveButton.position(width, 270);
saveButton.mousePressed(saveMap)
}
function draw() {
if (!drawComplete) {
drawMap();
saveButton.hide()
} else {
saveButton.show()
}
}
function drawMap() {
for (var i = 0; i < drawSpeed; i++) {
var nextColor = noiseGen.next();
if (!nextColor.done) {
drawComplete = false;
// stroke(nextColor.value.color);
// point(nextColor.value.x, nextColor.value.y);
img.set(nextColor.value.x, nextColor.value.y, nextColor.value.color);
} else if (!drawComplete) {
console.log("complete");
drawComplete = true;
}
}
img.updatePixels()
image(img, 0, 0);
}
function saveMap() {
img.save('perlin_noise', 'png');
}
function refreshMap() {
drawComplete = true
noiseScale = parseFloat(scaleInput.value());
octave = parseFloat(octaveInput.value());
persistence = parseFloat(persistenceInput.value());
lacunarity = parseFloat(lacunarityInput.value());
noiseGen = generateNoiseMap(width, height, noiseScale, octave, persistence, lacunarity, noiseMap);
drawComplete = false;
}
function* generateNoiseMap(width, height, scale, octaves, persistence, lacunarity, sendMapTo = null) {
var map = make2DArray(width, height);
var noiseMap = make2DArray(width, height);
var maxNoiseHeight = Number.MIN_VALUE;
var minNoiseHeight = Number.MAX_VALUE;
for (let x = 0; x < map.length; x++) {
for (let y = 0; y < map[x].length; y++) {
let amplitude = 1;
let frequency = 1;
let noiseHeight = 0;
for (var i = 0; i < octaves; i++) {
var sampleX = x / scale * frequency;
var sampleY = y / scale * frequency;
var perlinValue = noise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
if (noiseHeight > maxNoiseHeight) {
maxNoiseHeight = noiseHeight;
} else if (noiseHeight < minNoiseHeight) {
minNoiseHeight = noiseHeight;
}
noiseMap[x][y] = noiseHeight;
}
}
for (let x = 0; x < map.length; x++) {
for (let y = 0; y < map[x].length; y++) {
map[x][y] = (noiseMap[x][y] - minNoiseHeight) / (maxNoiseHeight - minNoiseHeight);
var drawPoint = yield {
color: map[x][y] * 255,
x: x,
y: y
};
}
}
if (sendMapTo != null)
sendMapTo = map;
}
function make2DArray(cols, rows) {
let arr = new Array(cols);
for (let i = 0; i < arr.length; i++) {
arr[i] = new Array(rows);
}
return arr;
}