WebGPU 2D Renderer
@shell/webgpu renders ECS sprite components directly through WebGPU. It extracts each frame into
reusable typed arrays, conservatively culls sprites outside the active camera, sorts visible
transparent sprites deterministically, batches compatible runs, and submits one command buffer
without creating a renderer display object for every entity.
import { World } from '@shell/ecs';import { Position, Size } from '@shell/transform';import { Image, Texture, WebGPUPlugin } from '@shell/webgpu';
const world = new World();world.addPlugin( WebGPUPlugin.config({ canvas, clearColor: [0.05, 0.06, 0.08, 1], spawnCamera: true, powerPreference: 'high-performance', }),);
await world.mount();world .get('commands') .spawn( Image.with(Texture, { source: '/player.png' }) .with(Position, { x: 100, y: 50 }) .with(Size, { width: 64, height: 64 }), );The plugin accepts either a canvas or container. A container causes the renderer to create and
own a responsive canvas. Importing the package is SSR-safe; mounting requires navigator.gpu and an
available adapter.
| Export | Description |
|---|---|
Sprite | Sprite renderable marker. |
Texture | Asset source and source rectangle. |
Sampler | Nearest/linear filtering and clamp/repeat address. |
Blend | Source-alpha or additive blending. |
Tint | Packed RGB tint and alpha. |
RenderOrder | Layer and explicit order. |
Camera | Active state and zoom. |
Image | Complete sprite bundle. |
CameraPrefab | Camera, position, and rotation prefab. |
defineTextureAtlas | Validated named frame metadata. |
Transform components are owned by @shell/transform and are not re-exported by @shell/webgpu.
WebGPUPlugin installs TransformPlugin as a dependency, while application code imports the
components it authors directly from @shell/transform.
Atlas And Render State
Section titled “Atlas And Render State”const atlas = defineTextureAtlas({ name: 'actors', source: '/actors.png', frames: { idle: { x: 0, y: 0, width: 32, height: 48 }, run: { x: 32, y: 0, width: 32, height: 48 }, },});
commands.spawn( Image.with(atlas.frame('run')) .with(Sampler, { filter: SamplerFilter.Linear }) .with(Blend, { mode: BlendMode.Additive }),);Atlas frames resolve to the existing serializable Texture fields and share one resident image.
Frame metadata supports untrimmed, unrotated origins and dimensions. Cached frame data and bundles
avoid selection-time allocation.
Ordering And Alpha
Section titled “Ordering And Alpha”Sprites sort by layer, Z, explicit order, pipeline, sampler, blend, texture, and entity index.
Transparency ordering takes priority over reducing state switches. The default canvas alpha mode is
premultiplied; sprite colors are straight alpha. Additive blending weights source color by alpha and
adds it to the destination.
Texture Lifetime
Section titled “Texture Lifetime”world.get('webgpuTextures') exposes unload, reload, retry, and replace. Unloading invalidates
in-flight completion and makes stale IDs use the fallback. Replacement accepts a decoded image source
under the existing logical key. Statistics include resident count, estimated bytes, failures,
retries, and replacements. Automatic eviction is intentionally not implemented.
Diagnostics
Section titled “Diagnostics”const device = world.get('webgpuDevice');const frame = world.get('webgpuFrame');const renderer = world.get('webgpuRenderer');device.statusanddevice.errorreport unsupported browsers, acquisition failures, and device loss.frame.camera.diagnosticreports missing, multiple, or zero-sized camera states.frame.statsreports camera extraction, sprite extraction, preparation CPU time, and candidate, visible, and culled sprite counts.renderer.statsreports the visibility counts, CPU encoding time, draw calls, one-frame total and instance-only upload bytes, queue submissions, estimated texture/buffer memory, resident textures, and texture lifecycle counters.
Culling tests the transformed quad corners against the same clip-space viewport used for rendering. It includes camera translation, rotation, zoom, CSS canvas size, sprite rotation, scale, anchor, and pivot. Invalid camera frames, non-finite bounds, and pending natural texture dimensions remain visible conservatively. Offscreen sprites still request their textures deterministically.
Failed image loads use a shared white fallback texture and retain their error. Device loss suspends rendering and is not automatically recovered. Unmounting destroys all renderer-owned GPU resources and browser observers.
Limitations
Section titled “Limitations”The renderer supports one canvas, one active camera, flat transforms, textured quads, nearest/linear and clamp/repeat sampling, and alpha/additive blending. It does not yet support atlas trimming or rotation, hierarchy transforms, text, masks, filters, particles, multiple cameras, render textures, custom shaders, spatial or occlusion culling, automatic device recovery, or a non-WebGPU fallback.
See packages/2d/webgpu/README.md for detailed semantics and examples/webgpu/benchmark.html for
the Pixi comparison harness.