Summary
A particle draws one whole image with fixed UVs. There is no way to give it a frame from a sprite sheet, so particles cannot be animated, and cannot vary their appearance across a burst.
Current state
ParticleEmitterSettings.image is a single HTMLCanvasElement | HTMLImageElement, and Particle.draw blits all of it:
renderer.drawImage(this.image, 0, 0, w, h, 0, 0, w, h);
No frame, no atlas region, no per-particle UVs. Every particle of an emitter is visually identical apart from tint, scale, rotation and alpha.
What this would enable
- animated particles — smoke that curls, sparks that flicker, an explosion playing a frame sequence, each particle advancing through the sheet over its own lifetime
- variety within a burst — several debris shapes drawn from one sheet, picked per particle at birth, so a burst does not read as N copies of one sprite
- Both are common enough that their absence is usually worked around by running several emitters with different images, which multiplies the per-emitter cost for what should be one batch.
Shape of the API
Roughly what a Sprite already accepts, so the vocabulary carries over:
- a frame size (or a named region set) alongside
image
- per-particle frame selection: a sequence advanced over the particle's life, or a random frame chosen at birth
- the existing lifetime/scale/rotation machinery unchanged
Why this is filed now, before it is built
It constrains #1404 (GPU-instanced particle rendering). Instancing carries a per-instance record, and per-particle UVs must be reserved in that record from the start — a UV rect is four floats, and the existing instance record (src/video/gpu/instancerecord.ts) already documents a spare four-float slot with "an atlas offset" named as an intended use.
Retrofitting UVs after an instanced batcher exists means changing the vertex layout, the shader and both GPU backends. Reserving the slot up front costs nothing.
Worth noting instancing does not otherwise conflict: particles on different frames of the same sheet batch in one draw. The constraint it does impose is one texture per instanced draw, so particles drawn from genuinely different images would still need separate draws — which is already true of the current quad batcher.
Not urgent
Filed to record the constraint, not to schedule the work.
Summary
A particle draws one whole image with fixed UVs. There is no way to give it a frame from a sprite sheet, so particles cannot be animated, and cannot vary their appearance across a burst.
Current state
ParticleEmitterSettings.imageis a singleHTMLCanvasElement | HTMLImageElement, andParticle.drawblits all of it:No frame, no atlas region, no per-particle UVs. Every particle of an emitter is visually identical apart from tint, scale, rotation and alpha.
What this would enable
Shape of the API
Roughly what a
Spritealready accepts, so the vocabulary carries over:imageWhy this is filed now, before it is built
It constrains #1404 (GPU-instanced particle rendering). Instancing carries a per-instance record, and per-particle UVs must be reserved in that record from the start — a UV rect is four floats, and the existing instance record (
src/video/gpu/instancerecord.ts) already documents a spare four-float slot with "an atlas offset" named as an intended use.Retrofitting UVs after an instanced batcher exists means changing the vertex layout, the shader and both GPU backends. Reserving the slot up front costs nothing.
Worth noting instancing does not otherwise conflict: particles on different frames of the same sheet batch in one draw. The constraint it does impose is one texture per instanced draw, so particles drawn from genuinely different images would still need separate draws — which is already true of the current quad batcher.
Not urgent
Filed to record the constraint, not to schedule the work.