Phaser AE

Wisps

Pro packv3.0.0-43DLook

Steam and smoke as a ribbon that twists about its own vertical axis as it rises: the coffee-cup plume, in true 3D. Every wisp in the world is one instanced draw, with no mesh to author and no particles to simulate.

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

Wisps: 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.

What it does

A scrolling billboard is a picture of smoke. A wisp is a plane that really turns in space as it rises, the angle of the turn read per vertex from a drifting column of tileable noise, so the ribbon curls, uncurls and never repeats. A sheet that turns hides parts of itself and shows a different amount of surface at every height, and the eye reads it as a volume. Wind sways the top while the base stays pinned to whatever the wisp rises from, and a remap of the noise erodes the sheet into separate curling wisps instead of a solid strip.

The awkward cases of a turning plane are handled. The whole ribbon turns to face the camera about its vertical axis, so it never shows you its edge, and where a twisted slice is edge-on to the eye the shader dissolves it rather than drawing a hard bright line.

It is cheap. The 12 by 40 grid of each ribbon is generated from the vertex index, so there is no vertex buffer, no mesh and no simulation step, and the animation is four texture reads a vertex. It shares render-3d's camera uniform, so a wisp takes exactly the fog and tone map the solids do, and it draws depth-tested so walls hide it, but never writes depth, so ribbons that overlap blend instead of clipping each other.

Features

  • A real twist — geometry turning in the vertex stage, from 0 (a flat billboard) through 10 (the coffee cup) to a shredded corkscrew.
  • Wind with a pinned base — wind sways the top, weighted by height squared, while the base stays put.
  • Steam or smoke — remap erodes a solid sheet into separate curls.
  • One draw for every wisp — no vertex buffer, no mesh and no particles.
  • Fits the scene — the solids' fog and tone map, depth-tested, both faces drawn.
  • Live fields — every field of a returned wisp changes on the next frame, and strength dims them all at once.
  • Its own noise — tileable noise baked at boot, shared as noiseFrame, or a greyscale frame of your own per wisp.

Good for

  • Chimneys in village and farm scenes.
  • Cups and hot drinks — the thin curl of steam above a mug.
  • Cooling vents and hot springs in industrial and outdoor scenes.
  • Censers — incense rising in a still room.
  • Smouldering wrecks after a battle, where the smoke stands rather than travels.
  • Busy dioramas, where many columns of smoke still cost one draw.

Make it yours

A wisp is a spec: its base x, y and z, its width w and height h, color, alpha, twist, wind, speed, remap, an extra yaw on top of the camera-facing, and a noise frame to drive it. Every field stays live on the returned wisp, so w.wind = 4 makes it sway next frame. The manifest sets the baked noise's noiseSize and seed, the overall strength and whether the pass is enabled.

Two different columns from the same call: a thin, pale plume of steam over a cup, half a unit wide and two and a half tall with a full twist and a little wind; and a factory chimney fourteen units tall, three wide, in a dirty grey, with less twist, strong wind and a hard remap that breaks it into separate curls.

A quick look

const steam = game.wisps.add({ x: 0, y: 1.1, z: 0, w: 0.5, h: 2.5, twist: 10, wind: 0.4, alpha: 0.55 });
// a chimney: taller, wider, dirtier, more eroded
game.wisps.add({ x: 12, y: 6, z: -3, w: 3, h: 14, color: '#8d8a86', twist: 6, wind: 3, remap: [0.55, 1] });
steam.wind = 1.2;                                   // every field is live

Works with

  • render-3d — required; it shares its camera, fog and tone map.
  • world-3d — the 3D world the wisps stand in.
  • core-3d — the usual 3D setup to compose this beside.
  • vfx3d-smoke and particles-3d — for smoke that travels: puffs that expand and drift, billows and dust.

Good to know

  • The base is pinned to a fixed point; to follow a moving object, set x, y and z each frame.
  • Wisps in front of one another blend rather than sort. At the opacities smoke wants this is invisible; at alpha: 1 with hard remap edges it can show.
  • A wisp is a standing column, not smoke with a life; for a puff that drifts away, use vfx3d-smoke.

More Look packs

Show all →