Phaser AE

WGSL to GLSL snippets

Free packv3.0.0-12D and 3DRenderers

The translator between the two backends' shader languages. Effects written once in WGSL for WebGPU still draw on the WebGL2 fallback, and anything that cannot be translated says so instead of drawing black.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 19, 2026 · updated October 20, 2026

WGSL to GLSL snippets: 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

The effect packs (backdrops, post passes, sprite and mesh shaders, deformers) describe each effect as a WGSL snippet spliced into a fixed template. WebGPU runs it as written. On a device without WebGPU, wgslSnippetToGLSL turns the snippet body into GLSL ES 3.0, checked against every name the template declares and its type, so content that exists only as WGSL still draws.

It parses the whole expression grammar into a tree and works out the type of every part, because two differences between the languages break shaders without any error. In WGSL an integer literal becomes a float where it meets one, so uv * 2 is legal there and an error in GLSL; the translator writes 2.0 in those places and an int elsewhere. And WGSL's float % keeps the sign of the dividend, unlike GLSL's mod, so it becomes a - b * trunc(a / b).

The snippet contract is straight-line maths over scalars, vectors and small square matrices, let and var, if, for and while, and the helper set. Anything outside it throws an Error that names the construct, and the caller reports it once and skips that layer, because GLSL that names an undeclared identifier compiles to a silent black pass.

Features

  • WGSL snippets to GLSL ES 3.0 — one call, wgslSnippetToGLSL(code, scope, helpers?).
  • Checked against the template — scope lists every declared name with its GLSL type, struct members included, and anything else throws.
  • Typed literals — integer literals become floats where WGSL would make them so, default to int otherwise, and hex literals are always integers.
  • Correct remainders — float % keeps the dividend's sign, as in WGSL.
  • Shared helpers — hash21, noise2, fbm2, bgAt and tex, plus a template's own functions through helpers.
  • Loud failures — an error naming the construct, never guessed GLSL.
  • Pure string work — no DOM and no GL context, so it runs anywhere, headless included.

Good for

  • Games on the WebGL2 fallback — custom backdrops, post effects and shaders still appear on devices without WebGPU, through the packs that use it.
  • Effect authors — write a snippet once in WGSL and get the WebGL2 path from it.
  • Template authors — declare a template's names and helpers once, and check every snippet against them.

Make it yours

There are no options; what you control is the call. You pass the snippet, the scope of names your template declares with their GLSL types (scalars, vectors, small square matrices such as 'mat3', or { members: { … } } for a struct), and any helpers your template adds beside the shared set, which the template must declare in both dialects. Two different uses: a backdrop template that declares uv and color and turns a short noise snippet into a full-screen GLSL pass; and a template with a helper of its own, such as noise3, declared with its argument and return types so snippets can call it.

A quick look

A snippet translated and spliced into a GLSL template:

const body = wgslSnippetToGLSL('let p = uv * 2; color = vec4(vec3(noise2(p)), 1);', { uv: 'vec2', color: 'vec4' });
const glsl = `${head} void main() { vec4 color; ${body} out_color = color; }`;   // head: your template's declarations

Works with

Good to know

  • It is not a general WGSL compiler: fn, switch, loop, structs, arrays, pointers, texture calls and undeclared names throw.
  • A snippet that works on WebGPU but uses one of those does not draw on WebGL2.
  • Game code does not need it; the effect packs and the WebGL2 renderer call it.

More Renderers packs

Show all →