Terrain
by oisyn
HTML
Arrow keys to move, pgup/pgdn to change altitude<br>
<canvas width=1024 height=576 id=canvas></canvas><br>
<canvas width=256 height=256 id=heightmap></canvas><br>
CSS
canvas { border: 1px solid black; }
JavaScript
const TerrainSize = 1024, TerrainMask = TerrainSize - 1;
var heightmap = new Float32Array(TerrainSize * TerrainSize);
var colormap;
var sample = (x, y) => heightmap[((y & TerrainMask) * TerrainSize) + (x & TerrainMask)];
var samplecolor = (x, y) => colormap[((y & TerrainMask) * TerrainSize) + (x & TerrainMask)];
var frnd = (min, max) => (max - min) * Math.random() + min;
var clamp = (x, min, max) => Math.min(Math.max(x, min), max);
const MaxHeight = 1024;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
const Width = canvas.width;
const Height = canvas.height;
const HalfWidth = Width / 2;
const HalfHeight = Height / 2;
var pixels = ctx.createImageData(Width, Height);
var pdata = new Uint32Array(pixels.data.buffer);
var hc = document.getElementById("heightmap");
hc.width = TerrainSize;
hc.height = TerrainSize;
hctx = hc.getContext("2d");
var himg = hctx.createImageData(TerrainSize, TerrainSize);
colormap = new Uint32Array(himg.data.buffer);
function put(x, y, v)
{
heightmap[y * TerrainSize + x] = v;
}
// Diamond-Square
heightmap[0] = MaxHeight / 2;
let rndrange = MaxHeight;
for (let w = TerrainSize / 2, l = 1; w >= 1; w >>= 1, l++)
{
const size = 2*w;
rndrange *= 0.45;
//if (w == 2)
// rndrange *= 0.2;
for (let y = 0; y < TerrainSize; y += size)
{
for (let x = 0; x < TerrainSize; x += size)
{
let mid = 0.25 * (sample(x, y) + sample(x+size, y) + sample(x, y+size) + sample(x+size, y+size));
mid = clamp(mid + frnd(-rndrange, rndrange), 0, MaxHeight);
put(x+w, y+w, mid);
}
}
for (let y = 0; y < TerrainSize; y += size)
{
for (let x = 0; x < TerrainSize; x += size)
{
let px = x + w;
let py = y;
let mid = 0.25 * (sample(px - w, py) + sample(px + w, py) + sample(px, py - w) + sample(px, py + w));
mid = clamp(mid + frnd(-rndrange*1.2, rndrange/1.2), 0, MaxHeight);
put(px, py, mid);
px = x;
py = y + w;
mid = 0.25 * (sample(px - w, py) + sample(px + w, py) + sample(px, py - w) +...