Skip to content

Particles

Deepratna Awale edited this page Sep 28, 2026 · 2 revisions

Particles

Open Wallpaper Engine runs Wallpaper Engine's particle systems as WE does: its operators and initializers as a compiled program, in order, with every emitter on its own clock. The main path simulates on the GPU; a CPU simulation with the same semantics exists alongside it. This page covers the design, GPU/CPU parity and the particle budget.

Building a system

Scene/Loading turns a particle JSON into a program:

Builder Produces
ParticleSystemBuilder, ParticleFamilyBuilder The system and its children
ParticleInitializerBuilder, ParticleOperatorBuilder WE's initializers and operators, in authored order (two of one kind both apply)
ParticleMaterialPlanBuilder The material through WE's genericparticle/rope shaders, blend modes, sprite and trail options
ParticleBudget The thinning factor (below)

Instance overrides (instanceoverride: rate, count, size, alpha, speed, lifetime, colour) and controlpoint<n> are resolved every frame, and may be bound to user properties or timelines.

Simulation

GPU (ParticleGPUSimulator, ParticleSimulation.metal)

  • One compute pass per frame steps every system and writes draw records and indirect draw arguments, so neither the particles nor their count come back to the CPU. The CPU only evaluates the frame's inputs (ParticleFrameInputs).
  • Stages run for every system at once, with a barrier between stages, rather than each system's dispatches in turn.
  • Child events (eventfollow, eventspawn, eventdeath) never leave the GPU.

CPU (ParticleCPUSimulation, ParticleProgramCPU)

A CPU implementation of the same program (initializers, operators, remap, control-point writes, instances). Tests compare the two, and it is the reference for semantics.

Parity

Both simulations share ParticleShared.h, ParticleProgram.h, ParticleNoise, and a seeded ParticleRandom (a particle's spawn order plus the system seed names its random draws), so the same system behaves the same on either path and reference tests are deterministic.

Features

  • 3D simulation with 3D control points; control-point flags (cursor, scene position, parent's point) as WE defines them.
  • Children: static and event children with probability, maxcount, nesting and inheritance; link flag 1 makes a child's control points the parent's particles.
  • Emitters: bursts, delay, duration, periodic emission with random periods, "limit to one per frame", emitting from a layer's image (ParticleEmitterImage).
  • Operators: turbulence, vortex, attractors, boids, drag (with WE's low-frame-rate behaviour), maintain-distance, remap, audio response on rate, turbulence and vortex.
  • Collision: planes, spheres, quads, bounds (bounce, slide, stop, delete) and model bones (ParticleModelCapsules).
  • Renderers: sprites, sprite trails, ropes and rope trails, with WE's orientation, axis and rope UV options; rotation about every axis.
  • Emitters follow their live parents (scripts, timeline); particles live in the emitter's space unless worldspace.

The particle budget

Settings › Performance › Particle Budget: Low 10 000, Medium 25 000 (default), High 50 000, Unlimited.

  • For each system, OWE estimates how many particles it can hold: maxcount × count, or what its emitters keep alive (rate × longest lifetime + bursts) when that is less. Children and instances are included.
  • A scene within the budget is untouched. A scene over it is thinned: every system's maximum and rate are scaled by budget / total, on both simulations, keeping the look.
  • A change rebuilds the content; the scaling is logged once per scene.
  • Counting emission, not only maxcount, matters: a rain preset authored for 100 000 × 5 actually holds under 8 000.

Note

"GPU, no limits" is a project principle: the budget is a user choice with Unlimited available, never a hidden cap. See WE-fidelity principles.

Performance

Measured in the optimisation pass: a small system's fixed GPU cost fell from about 48 µs to 3 µs; every library wallpaper's simulation takes 0.03–0.27 ms of GPU. Heavy scenes are fill-bound (thousands of refracting sprites), not simulation-bound. Boids read a list of their slice rather than every particle. See Performance notes.

Tests

ParticleSimulationSweepTests, ParticleMaterialSweepTests, ParticleLibraryBenchmarkTests, ParticleSimulationPerformanceTests, ParticleMaterialPerformanceTests, and the WEParticleGalleryTests gallery (OWE_PARTICLE_GALLERY). See Testing.

User guide: Scene wallpapers and Settings › Performance

Clone this wiki locally