DeutschGitHub
prototypepackages/webgl-sand-engine/src

WebGL Sand Engine

@ralphschuler/webgl-sand-engine

Runs a deterministic CPU sand reference and bounded neighbor queries.

cellular automatagridWebGL

01 · Problem

What is it for?

Particle updates need deterministic boundaries and collision rules before rendering performance matters.

02 · Mental model

How should you think about it?

A grid step reads one generation and writes a new generation so each particle moves at most once.

In this repository

Runs a deterministic CPU sand reference and bounded neighbor queries. The verified core conserves particles and uses snapshot updates. Full WebGL simulation, water and chunk synchronization remain future integrations.

03 · Control flow

What happens in which order?

  1. Read a snapshot of the grid.
  2. Visit cells in a documented order.
  3. Choose permitted destination cells.
  4. Resolve conflicts deterministically.
  5. Publish the next grid and render it separately.

04 · Building blocks

The important contracts

SandSimulation.step / snapshotAdvance one deterministic CPU step and read a copy.
NeighborProvider.getNeighborsFilter positioned items within a bounded radius.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Read a snapshot of the grid.
  2. Visit cells in a documented order.
  3. Choose permitted destination cells.
  4. Resolve conflicts deterministically.
  5. Publish the next grid and render it separately.
Concept sketch · may reference omitted helpers
const EMPTY = 0, SAND = 1;
function stepSand(grid: Uint8Array, width: number, height: number) {
  const next = grid.slice();
  for (let y = height - 2; y >= 0; y--) for (let x = 0; x < width; x++) {
    const from = y * width + x, below = from + width;
    if (grid[from] === SAND && grid[below] === EMPTY) {
      next[from] = EMPTY; next[below] = SAND;
    }
  }
  return next;
}

06 · Verify

What should you test?

  • Conserve particle count during a step.
  • Keep cells within bounds.
  • Verify deterministic conflict resolution and independent snapshots.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

Conserve particle count during a step.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • CPU correctness does not imply GPU correctness.
  • Water behavior and chunk boundaries need separate rules.
  • GPU resources belong to an explicit lifecycle.
Important

The verified core conserves particles and uses snapshot updates. Full WebGL simulation, water and chunk synchronization remain future integrations.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/webgl-sand-engine/examples/basic.ts