Phaser AE

GPU particles

Pro packv3.0.0-42DLook

Particle pools of up to two million, simulated on the GPU every frame and drawn by one instanced call in the emitter's sorted place. When an effect needs tens of thousands of particles that all obey the same rules, this is the emitter to reach for.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 14, 2026 · updated October 20, 2026

GPU particles: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

gpuParticles

function gpuParticles(): Pack<{ gpuParticles: GpuParticlesApi }>

The GPU particles pack: pools of up to two million particles simulated on the GPU each frame (particles-gpu.sim, before sprites) and drawn by a registered drawer in the emitter object's sorted place — a screen of weather behind the world, a nova over it. Forces as data (accel, drag, curl noise, attract, vortex, orbit, wind), a wrap box for weather over an unbounded world, four-stop colour ramps, fade modes, twinkle, stretch. Additive by default (an unsorted pool is only order-independent additive). WebGPU compute and WebGL2 transform feedback keep the pools GPU-resident; headless the emitters exist and draw nothing.

Constants

GPU_DRAWER_ID

const GPU_DRAWER_ID: 2

The id this pack registers its drawer under.

Types

GpuEmitterApi

interface GpuEmitterApi

The gpu sub-object on a GPU emitter handle.

  • rate: number — Particles per second, live.
  • burst(count: number): void — Queue a one-shot spawn of count this frame.
  • readonly capacity: number — The pool size.
  • readonly alive: number — An estimate of the live count (spawned within the longest lifetime), updated each step.
  • readonly config: GpuEmitterConfig — The live config; mutate ranges and forces in place.
  • paused: boolean — Hold the simulation.

GpuEmitterConfig

interface GpuEmitterConfig

The GPU emitter config. Ranges are [min, max]; a single number is fixed. Degrees, world units, seconds.

  • x?: number — World x. Default 0.
  • y?: number — World y. Default 0.
  • layer?: string — The layer.
  • z?: number — Depth in the layer. Default 0.
  • follow?: Handle — Follow this object.
  • offset?: { x?: number; y?: number } — Offset from it.
  • capacity?: number — Pool size: the most alive at once; a RING — past it the oldest are recycled. 64..2M. Default 65536.
  • rate?: number — Particles per second. Default 0 (bursts only).
  • emitZone?: GpuZone — Born here. Default point.
  • angle?: number | [number, number] — Launch direction range, degrees. Default [0, 360].
  • radial?: boolean — Velocity points away from the emitter (for shells and novas; overrides angle). Default false.
  • speed?: number | [number, number] — Launch speed. Default [40, 80].
  • lifespan?: number | [number, number] — Lifetime, seconds. Default [1, 2].
  • size?: number | [number, number] — Size, world units (the frame's longer side). Default [4, 8].
  • endSize?: number — Size at death as a fraction of the birth size: 0 shrinks to nothing, 1 constant, above 1 grows. Default 0.
  • fade?: boolean | number — Alpha over life: true fades linearly over the whole life; false never; a number fades only over that final fraction (0.2 = the last 20%). Default true.
  • color?: string | ReadonlyArray<string> — Colour over life: one hex, or up to four stops. Default white.
  • alpha?: number — Alpha multiplier. Default 1.
  • twinkle?: number — Per-particle brightness flicker 0..1. Default 0.
  • rotate?: number | [number, number] — Visual rotation range at birth, degrees. Default 0.
  • spin?: number | [number, number] — Spin range, degrees/s. Default 0.
  • alignToVelocity?: boolean — Point the frame along the velocity. Default false.
  • stretch?: number — Elongate along the velocity by speed × this / 100. Default 0.
  • gravityX?: number — Gravity x, units/s². Default 0.
  • gravityY?: number — Gravity y. Default 0.
  • drag?: number — Velocity damping per second. Default 0.
  • forces?: GpuForce[] — Forces, as data; mutate the list live. At most eight.
  • wrap?: { w: number; h: number } — Fold positions into a box of this size centred on the emitter (weather over an unbounded world: move the emitter with the camera).
  • frame?: string | number — The atlas frame (a key or index). Default the white pixel.
  • blend?: 'add' | 'normal' — 'add' (default — an unsorted pool is only order-independent additive) or 'normal'.
  • seed?: number — Seed for the spawn hash. Default from the kernel rng.

GpuEmitterHandle

type GpuEmitterHandle = Handle & { gpu: GpuEmitterApi }

A GPU emitter is a roster handle with a gpu sub-object.

GpuForce

type GpuForce = | { kind: 'accel'; x?: number; y?: number } | { kind: 'drag'; amount: number } | { kind: 'curl'; strength: number; scale?: number; speed?: number } | { kind: 'attract'; x: number; y: number; strength: number; radius?: number } | { kind: 'vortex'; x: number; y: number; strength: number; radius?: number } | { kind: 'orbit'; x: number; y: number; strength: number; radius: number; spring?: number } | { kind: 'wind'; x: number; y: number; gust?: number; gustSpeed?: number }

A force on a GPU emitter, as data. Positions are relative to the emitter. At most eight.

GpuParticlesApi

interface GpuParticlesApi

game.gpuParticles.

  • emitter(cfg: GpuEmitterConfig): GpuEmitterHandle — Spawn a GPU emitter object. Throws on more than eight forces or an unknown frame.
  • readonly emitters: ReadonlyArray<GpuEmitterHandle> — Live emitters.
  • readonly count: number — Estimated live particles across every emitter.
  • readonly ready: boolean — True when the backend has a device and the pipelines exist.

GpuZone

type GpuZone = { kind: 'point' } | { kind: 'circle'; r: number; inner?: number } | { kind: 'rect'; w: number; h: number } | { kind: 'ring'; r: number; width?: number }

Where GPU particles are born, relative to the emitter.