Skip to content

Benjaminsen/Blids

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Blids

Millions of boids in the browser. A WebGPU flocking simulation tuned for Chrome/Blink — up to 4 million agents, artifact-free, in ~700 lines of dependency-free JavaScript and WGSL.

Live demo: chrisbenjaminsen.com/labs/blids

Made with AI

Written 100% by AI (Claude, Anthropic), guided by Chris Benjaminsen.

License

Public domain under The Unlicense — use it for anything, no attribution required.

Running locally

No build step, no dependencies. Any static file server works:

python3 -m http.server 8471
# open http://localhost:8471 in a WebGPU-capable browser (Chrome/Edge)

Controls

  • boids — population, 65k to 4M
  • radius — interaction range (auto-shrinks at high populations to keep the neighbor math exact)
  • separation / alignment / cohesion — the classic Reynolds weights
  • speed / size / noise — cruise speed, render size, per-boid wander
  • constrain to circle — circular arena instead of screen-edge wrap
  • 2x (half-rate sim) — simulate at half the display rate with interpolated rendering (roughly doubles the frame budget)
  • restart — re-seed the flock; hold the pointer down to scatter boids

While dragging any slider its label shows the live value. The HUD also shows fps, GPU sim time, and a build tag.

Architecture

Two cleanly separated layers.

Physics — all forces are exact pairwise functions of true Euclidean distance; nothing cell-, grid-, or lattice-shaped ever touches a force:

  • Classic Reynolds rules: alignment and cohesion with uniform weight over the interaction radius, and (my_pos − their_pos)/d² separation over a 0.35× inner radius — with one amendment: every hard radius cut is replaced by a smooth "skirt" to zero. A step edge at distance r makes the flock condense into r-spaced clusters that read as a grid (verified: the artifact survived every acceleration architecture until the edges were smoothed).
  • Front-weighted vision — neighbors ahead count ~5× more than behind, like a real bird's field of view. This damps the band/stripe instabilities that symmetric-kernel flocks are prone to.
  • World topology: torus (screen-edge wrap, default) or circular arena with a purely radial boundary force. Both verified artifact-free.
  • A small per-boid random kick ("noise") keeps aligned flocks from crystallizing into a lattice; slide it to 0 for fully deterministic boids.

Performance:

  • A counting-sort spatial grid (count → 3-level prefix scan → scatter) finds neighbors and makes their memory reads cache-coherent. It is used ONLY for lookup — candidates are accepted by true distance — so the grid cannot influence force direction or magnitude. Scales to 1024×1024 cells.
  • The interaction radius auto-shrinks with population (the slider is an upper bound), so the neighbor loop stays exact — no sampling — at any count.
  • Optional half-rate simulation with per-vertex interpolation: the sort's scatter buffer already holds previous positions at the same indices as the update output, so full-rate smooth motion costs one extra buffer read.
  • Rendering is one instanced draw, 3 vertices per boid, vertex-pulled straight from the sim buffer. 4× MSAA (sub-pixel boids otherwise moiré against the pixel raster) with additive blending, so overlap reads as brightness.
  • GPU timing via timestamp-query when available.

Hard-won lessons (the artifact hunt)

Persistent "grid" patterns in a flocking sim can come from at least four distinct sources — this project hit all four:

  1. Grid-sampled force approximations — biased per-cell sampling and interpolated force fields, including a provable lattice force that appears when radial weights at cell centers don't form a partition of unity.
  2. Rendering — sub-pixel triangles moiré against the pixel raster (fixed by MSAA; additive blending also removes draw-order bias).
  3. Sharp kernel edges — flocks self-space into clusters at any hard cutoff distance, producing a "grid" scaled by the interaction radius.
  4. The world itself — periodic rectangular domains stabilize axis-aligned traveling bands (Vicsek banding), and straight walls seed axis-aligned density fronts.

The combination that works: exact pairwise forces, smooth kernels, MSAA, and axis-free boundaries. If you're building one of these and see a grid, check those four in that order — and put a build tag on screen so you never debug against a stale cached script.

Debugging

#1000000 in the URL presets the count. #…-debug runs a fast-forward on the first frame and logs a BLIDS_DEBUG line to the console: global alignment, axis-affinity of headings (0.75 = isotropic, 1.0 = axis-locked), and integrity counters.

About

Boids implemented in WebGPU Optimized towards the Chrome Blink Engine

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages