let colorScale = chroma.scale(["#EED", "#3d295a", "#752536", "#b56576", "#eaac8b"],).domain([-100, 100]);
let colorScale1 = chroma.scale(['#44444a', '#bae8e8', "#81b29a", "#A9B7CF", "#fff"]).domain([-100, 100]);
let colorScale2 = chroma.scale(['#4F7098', '#74C3D8', '#7C99CB', '#76A3E7', '#FFFFFF']).domain([-50, 50]);
let colorScale3 = chroma.scale(['#EED', "#780000", "#c1121f", "#fdf0d5", "#003049", "#669bbc"]).domain([-50, 50]);
let colorScale4 = chroma.scale(["#F8F4E3", "#FFD275", "#FE938C", "#25283D"]).domain([-50, 50]);
let colorScale5 = chroma.scale(["#E4D6CA", "#241717", "#152548", "#322927", "#6A353F"]).domain([-50, 50]);
let colorScale6 = chroma.scale(["#FCF6E9", "#241302", "#984E35", "#C89F83", "#746B70"]).domain([-50, 50]);
createCanvas(windowWidth, windowHeight, WEBGL);
setAttributes('antialias', true);
easycam = createEasyCam({distance: 900, center: [0,0,0],rotation: [0.4,-0.75,0,0]});
for (let x = 0; x < cols; x++) {
radius = Math.min(rows, cols) / 2;
pointLight(255,255,255,0,0,200);
background(colorScale3(0.3).hex());
translate(-w / 2, -h / 2);
function createHatchPatternA(color) {
let pattern = createGraphics(20, 20);
pattern.line(0, 0, 20, 20);
pattern.line(20, 0, 0, 20);
pattern.circle(10,10,10);
pattern.line(10,10,20,20);
pattern.line(20,10,20,20);
function generateTerrain() {
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
terrain[x][y] = map(fBm(xoff, yoff), 0, 1, -100, 100);
for (let i = 0; i < octaves; i++) {
sum += amplitude * noise(x * frequency, y * frequency);
amplitude *= persistence;
function createParticles() {
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
x: x * scl * random(0.97, 1.03),
hatchPattern: createHatchPatternA(colorScale1(terrain[x][y]).hex())
particles.push(particle);
function updateParticles() {
for (let i = 0; i < particles.length; i++) {
let x = particles[i].x / scl;
let y = particles[i].y / scl;
let lowerBound = (currentRow - updateRange + rows) % rows;
let upperBound = (currentRow + updateRange) % rows;
if (lowerBound <= upperBound) {
if (y >= lowerBound && y <= upperBound) {
particles[i].z = lerp(particles[i].z, particles[i].targetZ, 0.1);
if (y >= lowerBound || y <= upperBound) {
particles[i].z = lerp(particles[i].z, particles[i].targetZ, 0.1);
currentRow = (currentRow + displaySpeed) % rows;
function drawParticles() {
for (let i = 0; i < particles.length; i++) {
randomSeed(HALF_PI*i*10);
fill(colorScale5(particles[i].targetZ).hex());
stroke(colorScale6(particles[i].targetZ).hex());
translate(particles[i].x*random(0.95,1.05), particles[i].y*random(0.95,1.05), particles[i].z);
box(partSize,partSize*random(1,5), Math.floor(randomGaussian(8,12)));
function drawParticlesB() {
for (let i = 0; i < particles.length; i++) {
texture(particles[i].hatchPattern);
stroke(colorScale4(particles[i].targetZ).hex());
translate(particles[i].x * random(0.1,0.4), particles[i].y * 0.3, particles[i].z * 3);
function drawParticlesC() {
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
let distance = Math.sqrt((dx * cos(PI / 7 * x * y)) + (dy * sin(TWO_PI * y + x)));
fill(colorScale1(particles[particleIndex].targetZ).hex());
translate(particles[particleIndex].x * 1.5, particles[particleIndex].y * 1.5, particles[particleIndex].z / 1.5);
line(partSizeC,partSizeC*random(4,24), Math.floor(Math.random(12,24)), Math.floor(Math.random(4,16)));
line(partSizeC,partSizeC*random(4,24), Math.floor(Math.random(12,24)), Math.floor(Math.random(4,16)));
rotateY(random(-15,-32));
line(partSizeC,partSizeC*random(4,24), Math.floor(Math.random(12,24)), Math.floor(Math.random(4,16)));
line(partSizeC,partSizeC*random(2,38), Math.floor(Math.random(6,4)), Math.floor(Math.random(3,2)));
line(partSizeC,partSizeC*random(4,24), Math.floor(Math.random(12,24)), Math.floor(Math.random(4,16)));
rotateY(random(-35,-52));
line(partSizeC,partSizeC*random(4,24), Math.floor(Math.random(12,24)), Math.floor(Math.random(4,16)));
fill(colorScale2(particles[particleIndex].targetZ).hex());
translate(particles[particleIndex].x * 1.5, particles[particleIndex].y * 1.5, particles[particleIndex].z / 1.2);
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));
sphere(partSizeC*random(0.3,0.7));