3D Particle Network

webgpucompute-shaderswasm3dspatial-hashing
Seed:0
Camera:ORBITAL

Generating Universe...

Initializing WebGPU

Algorithm: GPU hash-grid neighbor search with O(n) complexity

Generation: Seed-based procedural (cosmic)

Rendering: WebGPU compute shaders + instanced particles

About This Simulation

This is a GPU-accelerated 3D particle network that demonstrates advanced WebGPU compute shader techniques. The entire simulation runs on the GPU, from physics calculations to culling optimizations, achieving 10,000+ particles at 60fps.

Key Features

  • Full GPU Compute: All physics calculations happen in WGSL compute shaders
  • O(n) Neighbor Search: Hash-grid spatial partitioning eliminates quadratic complexity
  • Dynamic Connectivity: Edges are generated in real-time based on particle proximity
  • GPU Frustum Culling: Only visible particles are rendered using compaction + indirect draw
  • Zero-Copy Rendering: Compute shaders write directly to vertex buffers

Algorithm: Spatial Hash Grid

Traditional particle simulations use O(n²) algorithms where every particle checks every other particle. This becomes prohibitively expensive beyond a few hundred particles.

Instead, we use a uniform spatial hash grid that reduces complexity to O(n):

Grid Construction (6 compute passes)

  1. Clear: Zero all cell counters
  2. Histogram: Count particles per cell (atomic operations)
  3. Prefix Sum: Compute offsets for each cell
    • Stage 1: Scan within workgroups (256 elements)
    • Stage 2: Scan chunk sums
    • Stage 3: Add scanned sums back to chunks
  4. Scatter: Write particle indices to sorted cell lists

Force Calculation (1 fused pass)

For each particle:

  • Determine grid cell: cell = floor(position / cell_size)
  • Walk 27 neighbor cells (3×3×3 cube)
  • For each nearby particle:
    • Attraction: Pulls particles together
    • Repulsion: Prevents overlap (inverse square)
    • Edge Generation: Create edge when distance < threshold and i < j

Physics Integration (1 pass)

  • Apply velocity damping
  • Euler integration: position += velocity * dt
  • Spherical boundary collision with reflection

Visibility Culling (1 pass)

  • Test each particle against 6 frustum planes
  • Workgroup-local prefix sum of visibility flags
  • Compact visible particle indices
  • Write indirect draw arguments

Rendering Pipeline

Particles

Rendered as instanced icospheres with per-particle position, size, and color. Uses:

  • Blinn-Phong shading for realistic lighting
  • Distance fog for depth perception
  • Color-coded connectivity: Warmer colors = more neighbors

Edges

Rendered as screen-space quads (not lines) for consistent thickness across devices:

  • Vertex shader fetches edge endpoints from storage buffer
  • Projects to NDC and computes perpendicular direction
  • Expands to quad with desired pixel thickness
  • Fragment shader applies transparency based on edge strength

Performance Characteristics

ParticlesFPSEdgesGPU Time
1,00060~8k~2ms
5,00060~40k~8ms
10,00060~80k~15ms
20,00045~150k~25ms

Tested on M1 Pro (16-core GPU)

Bottlenecks

  1. Edge rendering: Transparent quads require sorting or overdraw
  2. Grid construction: 6 passes have overhead
  3. Neighbor iteration: 27 cells × avg particles per cell

Optimizations Applied

  • ✅ Cell size ≈ connection distance (minimizes false positives)
  • ✅ Fused forces + connectivity (one neighbor walk)
  • ✅ Zero-copy instance buffer (STORAGE + VERTEX usage)
  • ✅ Frustum culling with compaction
  • ✅ Indirect draw (GPU-driven instance count)

Math Details

Frustum Plane Extraction

From view-projection matrix VP, extract 6 planes:

Left:   VP.row4 + VP.row1
Right:  VP.row4 - VP.row1
Bottom: VP.row4 + VP.row2
Top:    VP.row4 - VP.row2
Near:   VP.row4 + VP.row3
Far:    VP.row4 - VP.row3

Each plane is normalized: plane.xyz /= length(plane.xyz)

Prefix Sum (Blelloch Algorithm)

Upsweep (reduce):

for d = N/2 down to 1:
  for k = 0 to d-1:
    temp[2k+2d-1] += temp[2k+d-1]

Downsweep (distribute):

temp[N-1] = 0  // Exclusive scan
for d = 1 to N/2:
  for k = 0 to d-1:
    swap temp[2k+d-1] and temp[2k+2d-1]
    temp[2k+2d-1] += temp[2k+d-1]

Forces

Attraction (spring-like):

F_attract = direction * k_attract

Repulsion (inverse-square):

F_repel = -direction * k_repel / (r² + ε)

Browser Compatibility

BrowserSupportNotes
Chrome 113+Full support
Edge 113+Full support
Safari 26+macOS/iOS/iPadOS/visionOS
Firefox 141+⚠️Supported on Windows, platform coverage maturing

Firefox WebGPU

Firefox 141+ (July 2025) ships with production WebGPU support on Windows. On other platforms, WebGPU may require enabling via about:config:

  1. Type about:config in the address bar
  2. Search for dom.webgpu.enabled
  3. Toggle to true and restart Firefox

Note: Platform coverage is still maturing; Windows users should have full support out of the box.

Technical Specifications

  • Language: Rust (WASM) + TypeScript + WGSL
  • Graphics API: WebGPU
  • Compute Shaders: 9 (grid construction, forces, integration, culling)
  • Render Pipelines: 2 (particles, edges)
  • Buffer Usage: ~8MB for 10k particles
  • Dependencies: wgpu, glam, bytemuck, wasm-bindgen

Source Code

  • Rust Core: simulations/particle-network-3d/src/
  • WGSL Shaders: simulations/particle-network-3d/src/shaders/
  • TypeScript App: simulations/particle-network-3d/src/app.ts
  • React Wrapper: src/components/simulations/ParticleNetwork3D.tsx

Extensions

This codebase can be adapted for:

  • Force-Directed Graphs: Replace distance-based forces with spring forces on edges
  • Molecular Dynamics: Implement Lennard-Jones potential
  • 3D Boids: Add alignment, cohesion, separation rules
  • SPH Fluids: Two-pass density-pressure calculation

References

Controls

  • Left drag: Orbit camera around center
  • Right drag: Pan camera
  • Scroll: Zoom in/out
  • Auto-rotate: Optional automatic rotation

Built with WebGPU, Rust, and WASM. Requires Chrome 113+ or Edge 113+.