Fly through a procedurally generated galaxy in the browser. A WebGPU particle renderer — millions of stars, zero dependencies, one seed per galaxy.
Written 100% by AI (Claude, Anthropic), guided by Chris Benjaminsen.
Public domain under The Unlicense — use it for anything, no attribution required.
No build step, no dependencies. Any static file server works:
python3 -m http.server 8472
# open http://localhost:8472 in any WebGPU-capable browser- Drag to orbit around the point you grab, right-drag to pan, wheel to zoom, WASD to fly, Space/C up/down, Q/E roll, shift is a 5x boost, shift+wheel adjusts fly speed.
- stars — 250k to 4M
- arms / twist / arm width / arm strength — spiral geometry
- bulge / thickness — central bulge size and disk height
- blue clusters / pink nebulae — young star knots and HII regions along the arms
- haze — dust and gas glow
- spin — differential rotation speed (flat rotation curve)
- exposure — HDR tonemap exposure
- new galaxy — rerolls the seed (kept in the URL hash, so a galaxy you like is shareable/bookmarkable)
#seed=N in the URL pins the seed; #cam=x,y,z sets the starting camera.
- Generation runs on the GPU. A compute shader builds the entire star
field from
(seed, params): Gaussian bulge with a dense nucleus, exponential disk, log-spiral arms with clustered young blue knots, pink HII regions hosted by a random subset of those clusters, tan/blue/violet haze sprites, plus background and foreground field stars. Every slider change is one dispatch — regeneration is instant. - Rendering is additive HDR. Point sprites accumulate into an
rgba16floattarget at half resolution (particle glow upsamples invisibly, fragment cost drops 4x), then a fullscreen pass tonemaps with1 - exp(-c * exposure), gamma, and triangular dither. Additive blending means no sorting and no depth buffer — overlap density reads as brightness, like a real galaxy. - Sprite sizes conserve flux. Projected sizes are clamped to
[minPx, maxPx]and brightness is scaled by(raw/clamped)^2, so surface brightness stays physical at any distance and the core doesn't white-out the screen when you fly through it. - GPU-driven culling. A per-frame compute pass does all per-star work
once (spin, twinkle, projection, streak dimming, spikes), frustum-culls
with a sprite-extent margin, and stochastically merges dim stars (keep
with probability
brightness/T, re-brighten toT— same expected flux from far fewer sprites). Survivors go to compact lists driving indirect draws: point stars into the half-res HDR target, soft haze/HII into a quarter-res layer that rejoins via the bloom chain, nebula at 1/8 res. - Differential rotation uses a flat rotation curve (
omega ~ 1/r) applied in the vertex shader from an accumulated phase, so changing the spin slider changes the rate without snapping star positions.