Particle System

The engine's flagship subsystem — 100M+ GPU particles with full physics, thermal simulation, chemistry, SPH fluids, SDF collision, flocking, and volumetric rendering. Everything runs on compute shaders via vGPU.

Scale: The particle system spans 60+ simulation files and 30+ rendering files — the largest subsystem in the engine. This guide covers the architecture and key concepts. See individual module docs for deep dives.

Architecture Overview

The particle system has three distinct layers:

┌─────────────────────────────────────────────┐
│  Editor / Game API                           │
│  EditorParticles.js — orchestrates per-frame │
├─────────────────────────────────────────────┤
│  Rendering Layer (engine/render/particles/)  │
│  SDF Billboard · Half-Res Composite · Beams  │
│  Bonds · Decals · Distortion · Mesh · Trail  │
├─────────────────────────────────────────────┤
│  Simulation Layer (engine/sim/particles/)    │
│  ParticleSimWorld — main compute shader      │
│  + 30 advanced subsystems (GPU compute)      │
├─────────────────────────────────────────────┤
│  Emitter System (ParticleEmitterSystem.js)   │
│  Presets, spawn shapes, rate control          │
└─────────────────────────────────────────────┘

Per-Frame Pipeline

Each frame in EditorParticles.js:

  1. Emit — Spawn new particles from active emitters into GPU buffers
  2. Alive-list compaction — GPU scan writes alive particle indices (skip dead slots)
  3. Main sim — GPU compute: gravity, curl noise, forces, integration, lifetime
  4. Advanced systems — Thermal, SPH, flocking, bonds, chemistry, constraints
  5. Sort — Radix sort by camera distance for correct alpha blending
  6. Collisions — SDF collision against entity meshes + ground plane
  7. Light extraction — GPU compute finds hottest particles → async readback → LightManager
  8. Render — SDF billboard at half-res → additive composite onto scene

Emitter System

ParticleEmitterSystem.js manages emitter presets and controls particle spawning.

Matter States

StatePhase ValueRender ModeExamples
Solid0Matte diffuse + specularSparks, debris, snow
Liquid1Fresnel + refractionWater, blood, rain
Gas2Volumetric (Beer-Lambert)Smoke, steam, fog
Plasma3Emissive glowFire core, lightning, magic

Spawn Shapes

ParticleSpawnShapes.js provides configurable emission geometries:

GPU Simulation

The core simulation runs in ParticleSimWorld.js — a massive compute shader that processes all particles each frame. It reads from and writes to several GPU buffers:

Buffer Layout

BufferPer-Particle DataStride
Positionvec4(x, y, z, lifetime)16 bytes
Velocityvec4(vx, vy, vz, age)16 bytes
Thermalvec4(temperature, heat, packedMaterial, latentEnergy)16 bytes
Colorvec4(r, g, b, size)16 bytes

thermalData.z packing: Lower 8 bits = material index (0–15), upper bits = collision group ID. Encode: (groupId << 8) | materialIdx. Decode in WGSL: materialIdx = u32(thermal.z) & 0xFFu.

Advanced Subsystems

Initialized via initAllAdvancedSystems(), these modules extend the core sim:

Thermal & Chemistry

Temperature simulation with material-specific melt/boil points, latent heat, and phase transitions. 16 material presets (water, metal, wax, lava, etc.).

SPH Fluids

Smoothed Particle Hydrodynamics for realistic fluid behavior — pressure, viscosity, surface tension.

SDF Collision

Particles collide with entity meshes using signed distance fields (sphere, box, cylinder shapes). Per-entity SDF from PrefabRegistry.

Flocking

Boids-style behavior: separation, alignment, cohesion. Uses neighbor grid for spatial queries.

Bonds

Spring connections between particles for soft-body/cloth-like behavior. Async CPU readback for bond evaluation.

Electromagnetic

Electric and magnetic field forces. Charged particle interactions.

Constraints

Distance, position, and velocity constraints. Used for rope, chains, and attached particles.

Event System

Particle events (collision, death, threshold) that trigger sub-emissions or gameplay actions.

Performance Optimizations

Alive-List Compaction

Instead of dispatching threads for all slots (including dead particles), a GPU scan builds an alive list of active particle indices. The main sim then dispatches only aliveCount threads via indirect dispatch.

Radix Sort

Replaced bitonic sort with 4-bit radix sort. For 100M particles: 24 dispatches (8 passes × 3) vs bitonic's ~289 dispatches. Drop-in replacement via ParticleRadixSort.js.

FBM Noise Pre-bake

ParticleNoiseTexture.js pre-bakes 4-octave FBM curl noise into a 3D texture. The sim shader does a single textureSampleLevel instead of computing 4 octaves per particle per frame.

Neighbor Grid

Spatial hashing grid for O(1) neighbor queries. Used by SPH, flocking, and bond systems. Rebuilds each frame on GPU.

Rendering

SDF Billboard Renderer

The primary particle renderer (ParticleSdfRenderer.js) draws each particle as a camera-facing quad and raymarches a signed distance field in the fragment shader to produce volumetric shapes.

The fragment shader branches by matter phase:

Lifetime Effects

Color, size, and alpha are modulated over lifetime via GPU textures:

Blackbody Rendering

Hot particles use the Tanner Helland blackbody approximation (CIE 1931) instead of a linear ramp. Very hot particles (thermalGlow > 0.5) get an emissive bloom boost.

Additional Renderers

RendererPurpose
ParticleBeamRendererLaser/lightning beam connections
ParticleBondRendererSpring/bond visualization
ParticleDecalRendererGround impact decals with age fade
ParticleDistortionRendererHeat haze distortion post-effect
ParticleMeshRendererMesh-shaped particles (rocks, debris)
ParticleTrailHistoryRibbon/trail rendering
ParticleSPHSurfaceRendererScreen-space fluid surface (marching)
RopeGPURendererGPU-accelerated rope/chain rendering

Audio Integration

ParticleAudioBridge.js maps particle substance properties (temperature, density, velocity) to procedural audio parameters. Fire crackles, water splashes, and wind howls are all generated from particle state — no pre-recorded samples needed.

Key Files

FilePurpose
sim/particles/ParticleSimWorld.jsCore GPU compute sim (205K lines)
sim/particles/ParticleEmitterSystem.jsEmitter presets and spawning (78K)
sim/particles/ParticleAdvanced.jsAdvanced subsystem orchestration (65K)
sim/particles/ParticleConstraints.jsDistance/position constraints (59K)
render/particles/ParticleSdfRenderer.jsSDF billboard rendering
render/particles/ParticleHalfResComposite.jsHalf-res compositing
render/shaders/modules/core/particles_sdf_billboard.jsMain SDF particle shader (700+ lines)
editor/js/modules/EditorParticles.jsPer-frame orchestration