Creates a system. Settings not given use DEFAULT_PARTICLES. capacity, render.shading,
render.blending, render.sort, render.shadowSteps and render.lightSteps are fixed at
construction (make a new system to change them); everything else is live through set.
ReadonlybuffersGPU buffers.
ReadonlycapacityPool size.
ReadonlyclockSpawn scheduling (serials and ring slots).
ReadonlycurvesLifetime curves.
ReadonlygridGrid read by the forces and lighting, if any.
ReadonlylightingSun and sky light.
ReadonlyobjectAdd this to your scene (one instanced mesh). Particle positions are in its local space.
Resolved settings.
ReadonlysourcesWeighted spawn sources (for emitter.shape: 'sources').
Seconds simulated (wraps every 1000 s for float precision).
ReadonlyuniformsShader uniforms.
Absorption.
Clean smoke albedo.
Dirty smoke albedo.
Ambient temperature.
HG anisotropy.
Aspect.
Blackbody on/off (0/1).
Buoyancy.
Camera position in this system's local space.
Smoke cap height (0 = off).
Cooling rate.
Detail.
Detail distance.
Drag.
Step, seconds.
Emitter centre.
Emitter size.
Initial velocity.
Glow colour.
Glow strength.
Gravity.
Grid lift.
Brightness.
Life range.
Opacity.
Radians per pixel (for minimum on-screen width of sparks).
Haze refraction.
Seed.
Emitter shape id.
Silver lining.
Base size.
Size random range.
Soft fade distance.
Farthest sort distance.
Sources in use.
Sum of source weights.
Particles in this frame's batch.
First serial of this frame's batch.
Ring slot of this frame's batch.
Random speed.
Stretch.
Temperature range.
Animation clock.
Turbulence strength.
Turbulence scale.
Turbulence speed.
Wind.
Wind shear per 100 m.
Total weight of the sources (0 without sources).
Kills every particle (next update starts empty) and restarts the serials.
Removes the mesh and frees GPU resources.
Nodes of particle index (for grid splats and custom passes).
Advances the clock and uniforms by dt and returns this frame's compute passes (emit, update)
without running them, so several systems (and grid passes) can go to the GPU in one
renderer.compute([...]). Call ParticleSystem.sort after them if sorting.
Optionalcamera: Camera | nullReplaces all settings (anything not given goes back to defaults); structural ones stay.
Optionalcapacity?: numberPool size: the most particles alive at once. Changing it rebuilds the GPU buffers.
Optionalcurves?: { color?: string[]; opacity?: number[]; size?: number[] }Shape over life (0 → 1), each an evenly spaced list of 1 to 8 keys.
Optionalcolor?: string[]Colour (#rrggbb); multiplied by the blackbody colour when render.blackbody.
Optionalopacity?: number[]Opacity multiplier.
Optionalsize?: number[]Size multiplier.
Optionalemitter?: {Spawn shape and initial state.
Optionalposition?: [number, number, number]Centre, local space, metres.
Optionalshape?: EmitterShapepoint, box (half extents size), disc (radius size[0], on XZ), sphere (radius size[0]) or sources (see threejs-particles!ParticleSystem.setSources).
Optionalsize?: [number, number, number]Box half extents / disc and sphere radius in [0]; for sources, the jitter half extents around each source.
Optionalspread?: numberRandom extra speed in a random direction, m/s.
Optionaltemperature?: [number, number]Initial temperature range, kelvin (drives buoyancy, cooling and blackbody colour).
Optionalvelocity?: [number, number, number]Initial velocity, m/s.
Optionalforces?: {What moves particles.
OptionalambientTemperature?: numberAmbient air temperature, kelvin.
Optionalbuoyancy?: numberBuoyancy: up-acceleration = 9.81 × buoyancy × (T − ambient) / ambient (Boussinesq).
Optionalcooling?: numberExponential cooling towards ambient, 1/s.
Optionaldrag?: numberDrag towards the air velocity, 1/s.
Optionalgravity?: numberGravity, m/s² (down).
OptionalgridLift?: numberWith a grid: up-acceleration from the grid's channel 0 (heat h), gridLift × h / (1 + h) m/s².
Optionalturbulence?: numberCurl-noise turbulence, m/s².
OptionalturbulenceScale?: numberEddy size, metres.
OptionalturbulenceSpeed?: numberHow fast the eddies change, 1/s.
Optionalwind?: [number, number, number]Air velocity, m/s; drag pulls particles towards it.
OptionalwindShear?: numberWind grows by this share per 100 m above emitter.position.y (wind shear).
Optionallife?: [number, number]Life range, seconds.
OptionalmaxPerFrame?: numberMost particles spawned in one update (caps catch-up after a long frame).
Optionalrate?: numberParticles per second. With emitter.shape: 'sources' this is per unit of source weight, so a
bigger fire front spawns more. Throttled so the pool never runs out (capacity / mean life).
Optionalrender?: {How particles are drawn.
Optionalabsorption?: numberSmoke: light absorbed per unit of density.
Optionalalbedo?: [string, string]Smoke albedo for clean (white) smoke and dirty (dark) smoke; particles mix by their source tint.
Optionalanisotropy?: numberSmoke: Henyey-Greenstein anisotropy (0 isotropic … 0.9 strongly forward).
Optionalaspect?: numberHeight / width of each quad.
Optionalblackbody?: booleanColour from temperature (blackbody) instead of only the colour curve.
Optionalblending?: "additive" | "alpha" | "premultiplied"additive (sparks), alpha (smoke) or premultiplied (flames: emit light and partly hide what is behind).
OptionalcapHeight?: numberSmoke: height above the emitter (metres) where the plume caps into bright, dense, sharply billowing pyrocumulus-like cloud. 0 = off.
Optionaldetail?: numberPer-pixel noise detail 0…1 (0 = flat sprites, cheapest).
OptionaldetailDistance?: numberBeyond this camera distance (metres) the per-pixel detail and self-shadow taps fade out.
Optionalglow?: stringSmoke: warm light from below (#rrggbb), scaled by how hot the particle still is.
OptionalglowStrength?: numberSmoke: glow strength.
Optionalintensity?: numberBrightness multiplier (HDR; > 1 blooms).
OptionallightSteps?: numberSmoke with a grid: per-particle density steps towards the sun through the grid (0…8). Rebuilds the compute pass.
Optionalopacity?: numberOpacity multiplier.
Optionalrefraction?: numberHaze: screen-space refraction strength (fraction of the screen).
Optionalshading?: ParticleShadingBuilt-in shading: unlit sprites, noise-shaped flame tongues, lit volumetric smoke, thin spark streaks, refracting haze.
OptionalshadowSteps?: numberSmoke: per-pixel density taps towards the sun (0…4). Rebuilds the material.
OptionalsilverLining?: numberSmoke: extra forward-scattered light on thin edges when back-lit (silver lining).
Optionalsize?: numberBase size (width), metres.
OptionalsizeRandom?: [number, number]Random size multiplier range.
Optionalsoftness?: numberSoft depth fade against opaque geometry, metres (0 = hard).
Optionalsort?: booleanBack-to-front GPU sort (alpha blending).
Optionalstretch?: numberStretch along velocity: extra length = speed × stretch (seconds). 0 = camera-facing quads.
Optionalseed?: string | numberSeed for every per-particle random number (spawn position, velocity, size, life).
Merges input into the settings. Structural settings (see the constructor) are ignored with a warning.
Optionalcapacity?: numberPool size: the most particles alive at once. Changing it rebuilds the GPU buffers.
Optionalcurves?: { color?: string[]; opacity?: number[]; size?: number[] }Shape over life (0 → 1), each an evenly spaced list of 1 to 8 keys.
Optionalcolor?: string[]Colour (#rrggbb); multiplied by the blackbody colour when render.blackbody.
Optionalopacity?: number[]Opacity multiplier.
Optionalsize?: number[]Size multiplier.
Optionalemitter?: {Spawn shape and initial state.
Optionalposition?: [number, number, number]Centre, local space, metres.
Optionalshape?: EmitterShapepoint, box (half extents size), disc (radius size[0], on XZ), sphere (radius size[0]) or sources (see threejs-particles!ParticleSystem.setSources).
Optionalsize?: [number, number, number]Box half extents / disc and sphere radius in [0]; for sources, the jitter half extents around each source.
Optionalspread?: numberRandom extra speed in a random direction, m/s.
Optionaltemperature?: [number, number]Initial temperature range, kelvin (drives buoyancy, cooling and blackbody colour).
Optionalvelocity?: [number, number, number]Initial velocity, m/s.
Optionalforces?: {What moves particles.
OptionalambientTemperature?: numberAmbient air temperature, kelvin.
Optionalbuoyancy?: numberBuoyancy: up-acceleration = 9.81 × buoyancy × (T − ambient) / ambient (Boussinesq).
Optionalcooling?: numberExponential cooling towards ambient, 1/s.
Optionaldrag?: numberDrag towards the air velocity, 1/s.
Optionalgravity?: numberGravity, m/s² (down).
OptionalgridLift?: numberWith a grid: up-acceleration from the grid's channel 0 (heat h), gridLift × h / (1 + h) m/s².
Optionalturbulence?: numberCurl-noise turbulence, m/s².
OptionalturbulenceScale?: numberEddy size, metres.
OptionalturbulenceSpeed?: numberHow fast the eddies change, 1/s.
Optionalwind?: [number, number, number]Air velocity, m/s; drag pulls particles towards it.
OptionalwindShear?: numberWind grows by this share per 100 m above emitter.position.y (wind shear).
Optionallife?: [number, number]Life range, seconds.
OptionalmaxPerFrame?: numberMost particles spawned in one update (caps catch-up after a long frame).
Optionalrate?: numberParticles per second. With emitter.shape: 'sources' this is per unit of source weight, so a
bigger fire front spawns more. Throttled so the pool never runs out (capacity / mean life).
Optionalrender?: {How particles are drawn.
Optionalabsorption?: numberSmoke: light absorbed per unit of density.
Optionalalbedo?: [string, string]Smoke albedo for clean (white) smoke and dirty (dark) smoke; particles mix by their source tint.
Optionalanisotropy?: numberSmoke: Henyey-Greenstein anisotropy (0 isotropic … 0.9 strongly forward).
Optionalaspect?: numberHeight / width of each quad.
Optionalblackbody?: booleanColour from temperature (blackbody) instead of only the colour curve.
Optionalblending?: "additive" | "alpha" | "premultiplied"additive (sparks), alpha (smoke) or premultiplied (flames: emit light and partly hide what is behind).
OptionalcapHeight?: numberSmoke: height above the emitter (metres) where the plume caps into bright, dense, sharply billowing pyrocumulus-like cloud. 0 = off.
Optionaldetail?: numberPer-pixel noise detail 0…1 (0 = flat sprites, cheapest).
OptionaldetailDistance?: numberBeyond this camera distance (metres) the per-pixel detail and self-shadow taps fade out.
Optionalglow?: stringSmoke: warm light from below (#rrggbb), scaled by how hot the particle still is.
OptionalglowStrength?: numberSmoke: glow strength.
Optionalintensity?: numberBrightness multiplier (HDR; > 1 blooms).
OptionallightSteps?: numberSmoke with a grid: per-particle density steps towards the sun through the grid (0…8). Rebuilds the compute pass.
Optionalopacity?: numberOpacity multiplier.
Optionalrefraction?: numberHaze: screen-space refraction strength (fraction of the screen).
Optionalshading?: ParticleShadingBuilt-in shading: unlit sprites, noise-shaped flame tongues, lit volumetric smoke, thin spark streaks, refracting haze.
OptionalshadowSteps?: numberSmoke: per-pixel density taps towards the sun (0…4). Rebuilds the material.
OptionalsilverLining?: numberSmoke: extra forward-scattered light on thin edges when back-lit (silver lining).
Optionalsize?: numberBase size (width), metres.
OptionalsizeRandom?: [number, number]Random size multiplier range.
Optionalsoftness?: numberSoft depth fade against opaque geometry, metres (0 = hard).
Optionalsort?: booleanBack-to-front GPU sort (alpha blending).
Optionalstretch?: numberStretch along velocity: extra length = speed × stretch (seconds). 0 = camera-facing quads.
Optionalseed?: string | numberSeed for every per-particle random number (spawn position, velocity, size, life).
Replaces the weighted spawn sources: SOURCE_STRIDE (8) floats each, x, y, z (local), weight,
then data: size scale, lift (spawn up to this many metres above the source), tint (0 clean …
1 dirty smoke), temperature scale. Optional motion, MOTION_STRIDE (4) floats per source: a
velocity (m/s, added to the emitter's: particles inherit a moving source's speed) and an opacity
multiplier. Zero-weight sources are skipped; past maxSources the heaviest are kept. Uploads only
the used part.
Optionalcount: numberOptionalmotion: ArrayLike<number> | nullBack-to-front depth sort (when render.sort and a camera was given to the last prepare/update).
Advances the particles by dt seconds on the GPU: emits, integrates, and sorts if enabled.
camera (default: none) is used for sorting and spark sizing. Needs a WebGPU renderer; on the
WebGL backend the system hides itself.
Optionalcamera: Camera | null
A fixed-capacity pool of GPU particles: emit, update and (optionally) depth-sort run as TSL compute passes; one instanced draw renders them as camera-facing or velocity-stretched billboards with soft depth fade. Nothing is read back to the CPU.
Emission is a ring buffer: each update spawns
rate × dtparticles (fractions carry over) from a point, box, disc, sphere or a weighted list of sources the CPU refreshes cheaply. Every particle's random numbers come from its serial number andseed, so a run is reproducible. Forces: gravity, temperature-driven buoyancy with cooling, wind with shear and drag, curl-noise turbulence and, with a ParticleGrid, lift from the grid's heat. Size, colour and opacity follow lifetime curves.Example