JSFiddle - React, Tailwind, and code Playground
by jcubed111
HTML
<canvas id='main' width=500 height=500></canvas>
JavaScript
function rgba(r, g=r, b=g, a=1.0) {
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
function clamp(x, min=0, max=1) {
return Math.max(min, Math.min(max, x));
}
function Vec(...args) {
class Vec{
constructor(x, y) {
this.x = x;
this.y = y;
}
dot(b) {
return this.x * b.x + this.y * b.y;
}
length() {
return (this.x**2 + this.y**2)**0.5;
}
}
return new Vec(...args);
}
function slerp(a, b, f) {
f = 3 * f**2 - 2 * f**3;
return a*(1-f) + b*f;
}
class PerlinNoise{
constructor() {
this.vectors = {};
}
at(x, y) {
const fx = Math.floor(x);
const fy = Math.floor(y);
const dx = x - fx;
const dy = y - fy;
// c d
// a b
const a = Vec(dx, dy ).dot(this.getVector(fx, fy ));
const b = Vec(dx-1, dy ).dot(this.getVector(fx+1, fy ));
const c = Vec(dx, dy-1).dot(this.getVector(fx , fy+1));
const d = Vec(dx-1, dy-1).dot(this.getVector(fx+1, fy+1));
return slerp(slerp(a, b, dx), slerp(c, d, dx), dy);
}
getVector(x, y) {
if(!this.vectors[x]) {
this.vectors[x] = {};
}
if(!this.vectors[x][y]) {
const r = Math.random() * Math.PI * 2;
this.vectors[x][y] = Vec(Math.cos(r), Math.sin(r));
}
return this.vectors[x][y];
}
}
class RecursivePerlinNoise{
constructor(depth=1) {
this.noises = [];
for(let i=0; i<depth; i++) {
this.noises.push(new PerlinNoise());
}
}
at(x, y) {
return this.noises.map((n, i) => 2**-i * n.at(x*2**i, y*2**i)).reduce((a, b) => a + b, 0);
}
}
function colorStop(x, ...stops) {
for(let i=1; i<stops.length; i+=2) {
if(x < stops[i]) {
return stops[i-1];
}
}
return stops[stops.length-1];
}
const ctx = document.getElementById('main').getContext('2d');
function render()...