JSFiddle - React, Tailwind, and code Playground

HTML

<button>Grayscale</button>
<button>Sepia</button>
<button>Red+Green+Blue</button>
<button>HSL</button>
<button>Plasma</button>
<button>Plasma++</button>
<label><input type="checkbox" disabled /><span>Run animation</span></label>
<script>
	function buttonClick(e) {
		if (document._anim) document._anim.stop();
		document._anim = null;
		requestAnimationFrame(() => {
			switch (e.target.textContent) {
				case 'Grayscale': render_grayscale(); break;
				case 'Sepia': render_sepia(); break;
				case 'Red+Green+Blue': render_rgb(); break;
				case 'HSL': document._anim = render_hsl(); break;
				case 'Plasma': document._anim = render_plasma(); break;
				case 'Plasma++': document._anim = render_plasma_plus(); break;
			}
			let checkbox = document.querySelector('input');
			checkbox.checked = !!document._anim;
			checkbox.disabled = !document._anim;
		});
	}
	document.querySelectorAll('button').forEach(b => b.onclick = buttonClick);
	document.querySelector('input').onchange = e => {
		if (document._anim) {
			if (e.target.checked) document._anim.run();
			else document._anim.stop();
		}
	}
</script>
<hr />
<canvas />

CSS

body {
  background: #125616;
}

span {
  color: #eaae34;
}

input:disabled + span {
  color: #888;
}

JavaScript

function diamondSquare(magnitude, roughness) {
	const size = Math.pow(2, magnitude) + 1;
	const data = new Float32Array(size * size);
	const idx = (x, y) => x + y * size;

	let factor = 1;
	const rnd = () => (Math.random() * 2 - 1) * factor;
	const clamp = v => Math.max(-1, Math.min(1, v));

	let currentDistance = size - 1;
	data[0] = rnd(); data[currentDistance * size] = rnd();
	data[currentDistance] = rnd(); data[size * size - 1] = rnd();

	do {
		let halfDistance = currentDistance / 2;
		for (let offsetX = halfDistance; offsetX < size; offsetX += currentDistance) {
			for (let offsetY = halfDistance; offsetY < size; offsetY += currentDistance) {
				let sum =
					data[idx(offsetX - halfDistance, offsetY - halfDistance)] +
					data[idx(offsetX - halfDistance, offsetY + halfDistance)] +
					data[idx(offsetX + halfDistance, offsetY - halfDistance)] +
					data[idx(offsetX + halfDistance, offsetY + halfDistance)];
				data[idx(offsetX, offsetY)] = clamp(sum / 4 + rnd());
			}
		}
		for (let offset1 = 0; offset1 < size; offset1 += currentDistance) {
			for (let offset2 = halfDistance; offset2 < size; offset2 += currentDistance) {
				let count1 = 2, count2 = 2,
					sum1 = data[idx(offset1, offset2 - halfDistance)] +
						data[idx(offset1, offset2 + halfDistance)],
					sum2 = data[idx(offset2 - halfDistance, offset1)] +
						data[idx(offset2 + halfDistance, offset1)];

				if (offset1 > 0) {
					sum1 += data[idx(offset1 - halfDistance, offset2)]; count1++;
					sum2 += data[idx(offset2, offset1 - halfDistance)]; count2++;
				}
				else if (offset1 < size - 1) {
					sum1 += data[idx(offset1 + halfDistance, offset2)]; count1++;
					sum2 += data[idx(offset2, offset1 + halfDistance)]; count2++;
				}
				data[idx(offset1, offset2)] = clamp(sum1 / count1 + rnd());
				data[idx(offset2, offset1)] = clamp(sum2 / count2 + rnd());
			}
		}
		factor *= Math.pow(2, -roughness);
	} while ((currentDistance /= 2) > 1);
	return data;
}

function...