Headline: full data-oriented rewrite of the particle subsystem with
backend-agnostic auto-routing GPU compute (WebGPU) on top of the
existing CPU path (used by the WebGL2 backend).
Highlights
- SoA storage (Float32Array per channel, fixed capacity at construction)
replaces per-instance Particle objects. Spawn/Update/Death modules
operate on the live range directly.
- Distribution<T> (Range/VectorRange/Constant/Curve/Gradient/ConeDirection)
unifies how spawn-time values and over-lifetime values are sampled.
- Module pipeline: SpawnModule (RateSpawn, BurstSpawn) ·
UpdateModule (12 built-ins, all GPU-eligible: ApplyForce, Drag,
ColorOverLifetime, ColorOverSpeed, ScaleOverLifetime, RotateOverLifetime,
AlphaFadeOverLifetime, VelocityOverLifetime, AttractToPoint,
RepelFromPoint, OrbitalForce, Turbulence) · DeathModule (SpawnOnDeath).
- Auto-routing: a system using only GPU-eligible modules on a WebGPU
backend runs entirely on a composite compute pipeline (integration +
modules + pack-instances in one dispatch); any custom CPU-only module
forces the CPU path. The renderer reads the compute output directly
with no readback.
- ParticleSystem constructor: TypeScript overloads for mutual
exclusivity (`(texture)` · `(texture, frames)` · `(spritesheet)` ·
`(options)`); `device` and backend are auto-detected via render(backend).
- Custom UpdateModules opt into GPU acceleration by implementing
wgsl()/writeUniforms()/uploadTextures().
Breaking
- UniversalEmitter and the legacy per-particle Affector classes are
gone. Migrate to RateSpawn/BurstSpawn + UpdateModules.
- Particle positions are LOCAL to the system; setPosition the system
itself rather than per-particle world coordinates.
Examples
- bonfire (WebGL2/WebGPU shared) running on GPU compute when WebGPU.
- fireworks, particle-basics, additive-particles, particle-stress
showcasing custom modules and ParticleSystem capacity scaling.