PixiJS ParticleContainer: Batch‑Rendering Thousands of Sprites for Mobile‑Friendly Visuals
Batch rendering with PixiJS ParticleContainer lets you display thousands of sprites—like snowflakes or fireflies—on mobile without dropping frame rates. Learn how to set it up, when it works best, and its trade‑offs.
04 Jan 2026, 04:56 UTC

Problem: Rendering Thousands of Sprites on Mobile
When building effects such as starfields, explosions, or snow, developers often create thousands of Sprite objects. Each sprite adds its own draw call and transform overhead, which quickly drops frame rates on mobile devices. The bottleneck is not the GPU but the CPU’s work in issuing many individual WebGL commands.
What ParticleContainer Does
The PIXI.ParticleContainer class batches sprites that share a single base texture and a limited set of transform properties into a single WebGL draw call. By enabling only the properties you need (position, rotation, alpha, etc.), you reduce CPU overhead dramatically while still allowing per‑particle updates.
Key points:
- All children must reference the same
Texture(or sub‑texture from an atlas). - Supported flags:
position,rotation,scale,alpha,uv, and optionallyvertices. - Features like per‑sprite tint, blend modes, filters, or custom shaders are ignored.
Worked Example: Falling Snow
Below is a minimal example that creates 3,000 snowflakes using a ParticleContainer. The code runs in a browser with PixiJS 6.x or later.
// 1. Create the Pixi Application
const app = new PIXI.Application({
width: 800,
height: 600,
backgroundColor: 0x111111,
antialias: true,
});
document.body.appendChild(app.view);
// 2. Load a shared texture (a 16×16 white circle)
PIXI.Loader.shared.add('snowflake', 'snowflake.png').load(setup);
function setup(loader, resources) {
// 3. Create a ParticleContainer
const particleCount = 3000;
const container = new PIXI.ParticleContainer(particleCount, {
position: true,
rotation: true,
alpha: true,
scale: true,
});
app.stage.addChild(container);
// 4. Instantiate sprites and add to the container
const texture = resources.snowflake.texture;
for (let i = 0; i < particleCount; i++) {
const sprite = new PIXI.Sprite(texture);
sprite.x = Math.random() * app.screen.width;
sprite.y = Math.random() * app.screen.height;
sprite.vy = 50 + Math.random() * 100; // speed in px/s
sprite.rotationSpeed = Math.PI / 4 * (Math.random() - 0.5);
container.addChild(sprite);
}
// 5. Animate: move each sprite downward each tick
app.ticker.add(delta => {
container.children.forEach(sprite => {
sprite.y += sprite.vy * delta;
sprite.rotation += sprite.rotationSpeed * delta;
if (sprite.y > app.screen.height) {
sprite.y = -sprite.height;
sprite.x = Math.random() * app.screen.width;
}
});
});
}
Notice the container is created with a capacity of particleCount and only the transform flags you need. This reduces the number of WebGL draw calls to a single call per frame.
Limitations & Trade‑offs
- Texture Uniformity: All particles must share the same base texture. If you need color variation, pre‑color the texture or use multiple containers with different textures.
- No Tint or Blend Mode: Per‑sprite tint, blend modes, and filters are ignored. Use separate containers or custom shaders if you require these effects.
- Runtime Texture Changes: Changing a particle’s texture forces a flush of the batch, which can degrade performance. Plan your atlas ahead of time.
- Scale and UV Restrictions: If you need per‑particle UV changes or dynamic scaling beyond the flags, you may need to fall back to regular sprites.
Practical Checklist Before Using ParticleContainer
- Verify your PixiJS version (≥6.x) supports the desired flags via the documentation.
- Confirm all particles share a single base texture or sub‑texture.
- Choose only the flags you need to keep the vertex buffer minimal.
- Measure performance: run the example in Chrome’s Performance panel and compare FPS against an equivalent
ContainerofSpriteobjects. - Test edge cases: change a sprite’s texture or tint at runtime and observe the FPS drop.
Actionable Takeaway
If your visual effect relies on many identical sprites—snow, fireflies, or particle explosions—use PIXI.ParticleContainer to batch them. Keep the property set minimal, pre‑define textures, and avoid runtime changes that flush the batch. This simple change can lift frame rates from 30 fps to 60+fps on mid‑range phones.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.