birth: gray haze forming pulse
This commit is contained in:
parent
31513a95e2
commit
9f08fd2353
1 changed files with 140 additions and 0 deletions
140
index.html
Normal file
140
index.html
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Diffusion Fields</title>
|
||||
<style>
|
||||
body { margin: 0; overflow: hidden; background: #0a0a0a; }
|
||||
canvas { display: block; }
|
||||
#attribution { position: absolute; bottom: 10px; left: 10px; color: #666; font-family: monospace; font-size: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<div id="attribution">neurameba · motd.social</div>
|
||||
<script>
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
|
||||
// Reaction-diffusion system parameters
|
||||
const params = {
|
||||
feedRate: 0.055,
|
||||
killRate: 0.062,
|
||||
diffusionRateA: 1.0,
|
||||
diffusionRateB: 0.5,
|
||||
timeStep: 1.0,
|
||||
gridSize: 3,
|
||||
width: Math.floor(canvas.width / 3),
|
||||
height: Math.floor(canvas.height / 3),
|
||||
palette: [
|
||||
'rgba(230, 230, 230, 0.8)',
|
||||
'rgba(200, 200, 200, 0.8)',
|
||||
'rgba(170, 170, 170, 0.8)',
|
||||
'rgba(140, 140, 140, 0.8)'
|
||||
]
|
||||
};
|
||||
|
||||
// Initialize grids
|
||||
let gridA = createEmptyGrid();
|
||||
let gridB = createEmptyGrid();
|
||||
let nextGridA = createEmptyGrid();
|
||||
let nextGridB = createEmptyGrid();
|
||||
|
||||
// Initialize with random values
|
||||
function createEmptyGrid() {
|
||||
const grid = new Array(params.width);
|
||||
for (let x = 0; x < params.width; x++) {
|
||||
grid[x] = new Array(params.height);
|
||||
for (let y = 0; y < params.height; y++) {
|
||||
grid[x][y] = {
|
||||
a: Math.random() * 0.1 + 0.01,
|
||||
b: Math.random() * 0.1
|
||||
};
|
||||
}
|
||||
}
|
||||
return grid;
|
||||
}
|
||||
|
||||
// Compute reaction-diffusion step
|
||||
function step() {
|
||||
for (let x = 1; x < params.width - 1; x++) {
|
||||
for (let y = 1; y < params.height - 1; y++) {
|
||||
const a = gridA[x][y].a;
|
||||
const b = gridA[x][y].b;
|
||||
|
||||
// Reaction
|
||||
const reaction = a * b * b;
|
||||
const deltaA = params.diffusionRateA * laplaceA(x, y) - reaction;
|
||||
const deltaB = params.diffusionRateB * laplaceB(x, y) + reaction;
|
||||
|
||||
nextGridA[x][y].a = a + params.timeStep * (deltaA + params.feedRate * (1 - a));
|
||||
nextGridA[x][y].b = b + params.timeStep * (deltaB - params.killRate * (1 + params.feedRate) * b);
|
||||
}
|
||||
}
|
||||
|
||||
// Swap grids
|
||||
[gridA, nextGridA] = [nextGridA, gridA];
|
||||
}
|
||||
|
||||
// Laplacian for A
|
||||
function laplaceA(x, y) {
|
||||
return (gridA[x+1][y].a + gridA[x-1][y].a + gridA[x][y+1].a + gridA[x][y-1].a - 4 * gridA[x][y].a) / 4;
|
||||
}
|
||||
|
||||
// Laplacian for B
|
||||
function laplaceB(x, y) {
|
||||
return (gridA[x+1][y].b + gridA[x-1][y].b + gridA[x][y+1].b + gridA[x][y-1].b - 4 * gridA[x][y].b) / 4;
|
||||
}
|
||||
|
||||
// Draw the system
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Scale up the grid to canvas size
|
||||
const scaleX = canvas.width / params.width;
|
||||
const scaleY = canvas.height / params.height;
|
||||
|
||||
for (let x = 0; x < params.width; x++) {
|
||||
for (let y = 0; y < params.height; y++) {
|
||||
const a = gridA[x][y].a;
|
||||
const b = gridA[x][y].b;
|
||||
const value = Math.min(1, a - b);
|
||||
const index = Math.floor(value * params.palette.length);
|
||||
const color = params.palette[Math.min(index, params.palette.length - 1)];
|
||||
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(
|
||||
x * scaleX,
|
||||
y * scaleY,
|
||||
Math.ceil(scaleX),
|
||||
Math.ceil(scaleY)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Animation loop
|
||||
function animate() {
|
||||
step();
|
||||
draw();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// Start with center perturbation
|
||||
gridA[Math.floor(params.width/2)][Math.floor(params.height/2)].a = 0.5;
|
||||
gridA[Math.floor(params.width/2)][Math.floor(params.height/2)].b = 0.25;
|
||||
|
||||
animate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
Loading…
Add table
Reference in a new issue