Skip to content

@typegpu/kitpasses

Passes

Define shared render targets and outputs so every renderer writes colour, depth and data such as motion vectors.

kit.passes

module

passes.create(root, screen, { shared?, … }?) → Passes

passes.create(root, screen, writes, { shared?, … }?) → Passes

passes.output(schema, spec) → Output

rootborrows
the root
screentakes
the surface, or the targets, which give the formats; each one the description names is drawn into
shared?needs
bindings
Passesreturns
a description you destroy, which holds the pipelines it builds
writestakes
what fills each target, by its key in screen
schematakes
what the target holds per pixel, such as d.vec2f for an rg16float target
spectakes
write, which gives the value at a pixel, and what it clears to and carries from the vertex
Outputreturns
an output to give a target in passes.create
accessors
layerpixelssampleCountdepthOnly
outputs
shadedaccumulationrevealage
schemas
ScreenVertexViewport
constants
colordepth
helpers
fullScreen
types
OutputWriteWritesFedShadersDrawingCompoundDrawableDrawnBuiltStagesPassesBeginOptionsScreen
Optionscreate · 7 fields
jitter?

Position= none

Moves clip positions for rasterisation in a 'use gpu' function.

clear?

readonly number[] | GPUColorDict= transparent black

Sets the color target value where nothing drew.

bias?

{ readonly constant?: number; readonly slope?: number }= none

Adds a depth bias to every pipeline, in depth-format steps and per unit of slope, as depthBias and depthBiasSlopeScale.

depth?

{ readonly clear?: number; readonly compare?: GPUCompareFunction; readonly stencilClear?: number }= { clear: 1, compare: 'less', stencilClear: 0 }

Sets the depth clear value and comparison, and the stencil clear value for formats with stencil.

enabled?

() => boolean= always

Reports whether the description should draw in the current frame, exposed as enabled.

label?

string= none

Labels passes in the GPU debug panel and captures.

shared?

Shared= none

Binds a layout from bindings.share in every pass begin and record start, and fills its parts in every pipeline the description builds.

TargetOptionscreate · 8 fields
resolve?

{ readonly [K in keyof T]?: Exclude<keyof T, K> | Surface }= none

Maps multisampled targets to their resolve destinations at the end of a pass.

jitter?

Position= none

Moves clip positions for rasterisation in a 'use gpu' function.

clear?

readonly number[] | GPUColorDict= transparent black

Sets the color target value where nothing drew.

bias?

{ readonly constant?: number; readonly slope?: number }= none

Adds a depth bias to every pipeline, in depth-format steps and per unit of slope, as depthBias and depthBiasSlopeScale.

depth?

{ readonly clear?: number; readonly compare?: GPUCompareFunction; readonly stencilClear?: number }= { clear: 1, compare: 'less', stencilClear: 0 }

Sets the depth clear value and comparison, and the stencil clear value for formats with stencil.

enabled?

() => boolean= always

Reports whether the description should draw in the current frame, exposed as enabled.

label?

string= none

Labels passes in the GPU debug panel and captures.

shared?

Shared= none

Binds a layout from bindings.share in every pass begin and record start, and fills its parts in every pipeline the description builds.

records
  • pipe().recordencoder
  • pipe().compositeencoder
  • beneath().recordencoder
  • beneath().compositeencoder
  • add().drawrender
  • without().recordencoder
  • without().compositeencoder
  • instead().recordencoder
  • instead().compositeencoder
  • recordencoder
  • compositeencoder

begin from the frame, with the shared group set, then each drawing's draw from add into the pass; into targets with layers, record does so once per layer. composite records a pass of its own.

owns

the pipelines `add` builds ·until the drawing or description is destroyed ·a pipeline per description that composites ·bind groups ·a buffer per layer ·a buffer per viewport its pipelines read

WebGPU pipelines and bind groups need no destruction. Compound drawings free the resources they built for the description. composite lays translucent drawings over the colour with that pipeline and a bind group per pair of textures. A description drawn into layers holds each layer's index in a uniform with a bind group, until it is destroyed.

lifecycle

initAsync()destroy()[Symbol.dispose]

injects
  • per-instance

    What was piped into it, such as the camera, for a drawing's kernels per description.

binds
  • none

    What is piped in binds what its own @binds say.

  • 1 uniform

    passes.layer, the layer drawn, in a pipeline of a description drawn into layers that reads it.

  • 1 uniform

    passes.pixels, the drawn region, in a pipeline that reads it.

needs
  • bindings

    As options.shared; fills accessors in its pipelines.

latticeThin beams turning over a sky, embers rising through them, smoothed over frames with TAA.

The sky, beams and embers share one description for colour, TAA motion and depth. The description runs taa.motion for each drawing. Grey means still, colour means motion and black means no motion output. Drag horizontally to turn the camera. Put the embers in scene.without('motion') to keep the motion beneath them. Only the beams appear in depth, because the sky and embers test depth without writing it.

TAA needs motion vectors and a pick of your own needs ids at each pixel. Every renderer must write these alongside colour. Implementing each output separately in every renderer duplicates shader code. Renderers without the required data, such as particles without ids, also need a rule for that target.

passes.create defines what each target holds. A renderer supplies a drawing with a vertex function, a surface containing per-pixel data such as colour or id, and a draw call. scene.add(drawing) builds a pipeline that computes every output from that surface. scene.record(frame, drawn) draws it into the targets.

import {
import d
d
} from 'typegpu';
import {
import passes
passes
} from '@typegpu/kit';
const
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}>
screen
=
import targets
targets
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<...>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
, {
hdr: {
readonly format: "rgba16float";
readonly sampled: true;
}
hdr
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
motion: {
readonly format: "rg16float";
readonly sampled: true;
}
motion
: {
format: "rg16float"
format
: 'rg16float',
sampled: true
sampled
: true },
depth: {
readonly format: "depth24plus";
readonly sampled: true;
}
depth
: {
format: "depth24plus"
format
: 'depth24plus',
sampled: true
sampled
: true },
});
const
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>
scene
=
import passes
passes
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}, {
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>(root: TgpuRoot, screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}>, writes: {
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}, options?: passes.TargetOptions<...> | undefined): passes.Passes<...> (+1 overload)

Describes the targets and outputs for scene passes. With a surface such as the canvas, writes only each renderer's colour. With a target set, writes colour into the target marked color, depth into the target marked depth, and other outputs into their named targets. Multisampled targets resolve according to resolve. Targets with layers draw one pass per layer, and every target the description draws into needs the same layers. add builds a renderer's drawing. begin starts a pass. pipe supplies fills such as a camera.

@param ― screen the surface, or the targets, which give the formats; each one the description names is drawn into

@param ― writes what fills each target, by its key in screen

@returns ― a description you destroy, which holds the pipelines it builds

create
(
const root: TgpuRoot
root
,
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly motion: {
readonly format: "rg16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
readonly sampled: true;
};
}>
screen
, {
hdr: typeof passes.color
hdr
:
import passes
passes
.
const color: typeof passes.color

Marks the target that receives each renderer's colour.

color
,
motion: passes.Output<unknown, {
readonly position: d.v4f;
}>
motion
,
depth: typeof passes.depth
depth
:
import passes
passes
.
const depth: typeof passes.depth

Marks the depth target.

depth
})
.
Passes<{ readonly hdr: typeof color; readonly motion: Output<unknown, { readonly position: d.v4f; }>; readonly depth: typeof depth; }>.pipe(fill: Inject): passes.Passes<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>

Adds fill after existing fills and returns a description of the same passes. Piped fills take precedence over a drawing's own. For example, passes.create(…).pipe(view.inject()) uses the camera from view.

pipe
(
const view: cameras.OrbitCamera
view
.
CameraBase.inject(): Inject

Fills cameras.current for the pipelines created from the configuration it is piped into.

inject
());
// What each vertex carries to its pixels, and what the renderer knows at a pixel
const
const Corner: d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>
Corner
=
import d
d
.
struct<{
position: d.Vec4f;
world: d.Vec3f;
}>(props: {
position: d.Vec4f;
world: d.Vec3f;
}): d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>
export struct

Creates a struct schema that can be used to construct GPU buffers. Ensures proper alignment and padding of properties (as opposed to a d.unstruct schema). The order of members matches the passed in properties object.

@example const CircleStruct = d.struct({ radius: d.f32, pos: d.vec3f });

@param ― props Record with string keys and TgpuData values, each entry describing one struct member.

struct
({
position: d.Vec4f
position
:
import d
d
.
const vec4f: d.Vec4f
vec4f
,
world: d.Vec3f
world
:
import d
d
.
const vec3f: d.Vec3f
vec3f
});
const
const Seen: d.WgslStruct<{
color: d.Vec4f;
}>
Seen
=
import d
d
.
struct<{
color: d.Vec4f;
}>(props: {
color: d.Vec4f;
}): d.WgslStruct<{
color: d.Vec4f;
}>
export struct

Creates a struct schema that can be used to construct GPU buffers. Ensures proper alignment and padding of properties (as opposed to a d.unstruct schema). The order of members matches the passed in properties object.

@example const CircleStruct = d.struct({ radius: d.f32, pos: d.vec3f });

@param ― props Record with string keys and TgpuData values, each entry describing one struct member.

struct
({
color: d.Vec4f
color
:
import d
d
.
const vec4f: d.Vec4f
vec4f
});
const
const at: (vertexIndex: number, instanceIndex: number) => {
position: d.v4f;
world: d.v3f;
}
at
= (
vertexIndex: number
vertexIndex
: number,
instanceIndex: number
instanceIndex
: number) => {
'use gpu';
const
const corners: d.v3f[]
corners
= [
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(-1, 0, 0),
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(1, 0, 0),
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(0, 2, 0)];
const
const world: d.v3f
world
=
const corners: d.v3f[]
corners
[
vertexIndex: number
vertexIndex
]! +
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(
import d
d
.
function f32(v?: number | boolean): number
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
(
instanceIndex: number
instanceIndex
) * 3, 0, 0);
return
const Corner: d.WgslStruct
(props?: {
position: d.v4f;
world: d.v3f;
} | undefined) => {
position: d.v4f;
world: d.v3f;
}
Corner
({
position: d.v4f
position
:
import cameras
cameras
.
const current: TgpuAccessor<d.WgslStruct<{
viewProjection: d.Mat4x4f;
position: d.Vec3f;
right: d.Vec3f;
up: d.Vec3f;
}>>

Provides the camera for a pipeline. A camera's inject() fills it with the camera uniform.

current
.
TgpuAccessor<WgslStruct<{ viewProjection: Mat4x4f; position: Vec3f; right: Vec3f; up: Vec3f; }>>.$: {
viewProjection: d.m4x4f;
position: d.v3f;
right: d.v3f;
up: d.v3f;
}
$
.
viewProjection: d.m4x4f

Transforms world coordinates to clip space.

viewProjection
*
import d
d
.
const vec4f: d.Vec4f
(v0: AnyNumericVec3Instance, w: number) => d.v4f (+9 overloads)
vec4f
(
const world: d.v3f
world
, 1),
world: d.v3f
world
});
};
const
const surfaceOf: (corner: d.Infer<typeof Corner>) => {
color: d.v4f;
}
surfaceOf
= (
corner: {
position: d.v4f;
world: d.v3f;
}
corner
:
import d
d
.
type Infer<T> = T extends {
readonly [$repr]: infer TRepr;
} ? TRepr : T
export Infer

Extracts the inferred representation of a resource. For inferring types as seen by the GPU, see

InferGPU

@example type A = Infer // => number type B = Infer<WgslArray> // => number[] type C = Infer<Atomic> // => number

Infer
<typeof
const Corner: d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>
Corner
>) => {
'use gpu';
return
const Seen: d.WgslStruct
(props?: {
color: d.v4f;
} | undefined) => {
color: d.v4f;
}
Seen
({
color: d.v4f
color
:
import d
d
.
const vec4f: d.Vec4f
(v0: AnyNumericVec3Instance, w: number) => d.v4f (+9 overloads)
vec4f
(
corner: {
position: d.v4f;
world: d.v3f;
}
corner
.
world: d.v3f
world
* 0.25 + 0.5, 1) });
};
// Four triangles, drawn into every target the scene describes
const
const triangles: passes.Drawn
triangles
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly motion: Output<unknown, { readonly position: d.v4f; }>; readonly depth: typeof depth; }>.add<d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>, {
color: d.v4f;
}>(this: passes.Passes<passes.Fed<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>, {
color: d.v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
({
Shaders<WgslStruct<{ position: Vec4f; world: Vec3f; }>, { color: v4f; }>.Vertex: d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>

Defines a vertex with its position and data carried to pixels.

Vertex
:
const Corner: d.WgslStruct<{
position: d.Vec4f;
world: d.Vec3f;
}>
Corner
,
Shaders<WgslStruct<{ position: Vec4f; world: Vec3f; }>, { color: v4f; }>.at: (vertexIndex: number, instanceIndex: number) => {
position: d.v4f;
world: d.v3f;
}
at
,
Shaders<WgslStruct<{ position: Vec4f; world: Vec3f; }>, { color: v4f; }>.surfaceOf?: ((vertex: {
position: d.v4f;
world: d.v3f;
}) => {
color: d.v4f;
}) | undefined

Computes data at a pixel from the interpolated vertex. position is the pixel position. Required for descriptions that write colour and for depthOf.

surfaceOf
,
Shaders<WgslStruct<{ position: Vec4f; world: Vec3f; }>, { color: v4f; }>.color?: passes.Output<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
}> | undefined

Supplies the output for the color target when the description has one.

color
:
import passes
passes
.
const shaded: passes.Output<{
readonly color: d.v4f;
}, unknown>

Writes the surface's color unchanged as a renderer's color output.

shaded
,
Drawing<WgslStruct<{ position: Vec4f; world: Vec3f; }>, { color: v4f; }>.draw(pass: TgpuRenderCommands): void

Records a draw into the pass, on which the description has set the pipeline it built. That pipeline binds indices if supplied. drawIndexed throws without an index buffer. A group the drawing sets with pass.setBindGroup stays for later drawings in the pass that read its layout, so give such a layout to one drawing.

draw
: (
pass: TgpuRenderCommands
pass
) =>
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3, 4),
});
await
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly motion: Output<unknown, { readonly position: d.v4f; }>; readonly depth: typeof depth; }>.initAsync(): Promise<void>

Compiles every pipeline built for this description and the resources required by each added drawing.

initAsync
();
import frames
frames
.
function animate(loop: Pick<frames.Frames, "run"> & Partial<Pick<frames.Frames, "seconds">>, options?: frames.AnimateOptions): frames.Animation
export animate

Runs the loop on each scheduled frame. Time advances by at most maxDt per frame, never steps back, and stops while the surface is paused. Destroying the animation keeps the loop alive. Another animation on the same loop continues from its recorded time. A frame error stops the animation.

@param ― loop the loop to run on each unpaused frame. Continues from its seconds if it ran before

@returns ― an animation you destroy to stop the frames

animate
(
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) =>
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly motion: Output<unknown, { readonly position: d.v4f; }>; readonly depth: typeof depth; }>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly hdr: typeof passes.color;
readonly motion: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly depth: typeof passes.depth;
}> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const triangles: passes.Drawn
triangles
)));

passes.create(root, surface) draws each renderer’s colour into the canvas without extra targets or outputs.

passes.create takes a target set or a surface, { format, view(frame), width, height } with an optional pixelRatio. The surface form is for textures created outside the kit, such as a canvas. A texture you create to draw into and sample elsewhere, such as a label, a decal or a mirror, is a target set. targets.create takes any { width, height } and sizes a fixed set once, when it is created:

import {
import passes
passes
,
import targets
targets
} from '@typegpu/kit';
const
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
= {
width: number
width
: 512,
height: number
height
: 256,
pixelRatio: number
pixelRatio
: 1 };
const
const page: targets.Targets<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>
page
=
import targets
targets
.
function create<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
, {
ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
}
ink
: {
format: "rgba8unorm"
format
: 'rgba8unorm',
sampled: true
sampled
: true } });
const
const tags: text.TextSet
tags
=
import text
text
.
function create(root: TgpuRoot, font: Font, options: text.Options): text.TextSet

Creates labels drawn from a baked MSDF font atlas. The CPU lays out each string, and instanced glyph quads place it in world or screen space. Throws unless capacity and length are integers of at least 1.

@injects ― per-instance move, setLabel, setQuad, quadAt and erase, for kernels piped with it

@owns ― 2 buffers, a sampler: the quads and the labels

@binds ― 3 storage, 1 uniform: the drawing, the quads, the labels and the font's glyphs, and passes.pixels with text.screen or text.pinned

@binds ― 1 storage: move or setLabel, the labels

@binds ― 1 storage: setQuad, quadAt or erase, the quads

@records ― drawing, added to passes, after the passes that move the labels.

@param ― font the font it draws with, which it borrows

@param ― options.place a 'use gpu' function; it and shade carry the fills of what they read beside the camera, such as tgpu.fn(lifted).pipe(scene.inject())

@returns ― a set of labels you destroy before its font

create
(
const root: TgpuRoot
root
,
const font: Font
font
, {
Options.capacity: number

Sets the number of labels to an integer of at least 1.

capacity
: 1,
Options.length: number

Limits glyphs drawn per label to an integer of at least 1. Spaces use no glyph slot; glyphs beyond the limit are omitted.

length
: 3,
Options.place?: text.Place | undefined

Places glyph corners with facing, flat, pinned, screen or a custom function. Default facing.

place
:
import text
text
.
const screen: (position: v3f, offset: v2f) => v4f

Places text on screen with position in pixels from the top-left of the region the pass draws. em uses points, the pass's passes.pixels pixels per point, to preserve label size across pixel densities.

screen
});
const
const paint: passes.Passes<{
readonly ink: typeof passes.color;
}>
paint
=
import passes
passes
.
function create<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}, {
readonly ink: typeof passes.color;
}>(root: TgpuRoot, screen: targets.Targets<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>, writes: {
readonly ink: typeof passes.color;
}, options?: passes.TargetOptions<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}> | undefined): passes.Passes<{
readonly ink: typeof passes.color;
}> (+1 overload)

Describes the targets and outputs for scene passes. With a surface such as the canvas, writes only each renderer's colour. With a target set, writes colour into the target marked color, depth into the target marked depth, and other outputs into their named targets. Multisampled targets resolve according to resolve. Targets with layers draw one pass per layer, and every target the description draws into needs the same layers. add builds a renderer's drawing. begin starts a pass. pipe supplies fills such as a camera.

@param ― screen the surface, or the targets, which give the formats; each one the description names is drawn into

@param ― writes what fills each target, by its key in screen

@returns ― a description you destroy, which holds the pipelines it builds

create
(
const root: TgpuRoot
root
,
const page: targets.Targets<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>
page
, {
ink: typeof passes.color
ink
:
import passes
passes
.
const color: typeof passes.color

Marks the target that receives each renderer's colour.

color
});
const
const drawn: passes.Drawn
drawn
=
const paint: passes.Passes<{
readonly ink: typeof passes.color;
}>
paint
.
Passes<{ readonly ink: typeof color; }>.add<WgslStruct<{
position: Vec4f;
uv: Vec2f;
bounds: Vec4f;
color: Vec4f;
label: U32;
glyph: U32;
local: Vec2f;
}>, {
label: number;
color: v4f;
}>(this: passes.Passes<passes.Fed<{
label: number;
color: v4f;
}, {
position: v4f;
uv: v2f;
bounds: v4f;
color: v4f;
label: number;
glyph: number;
local: v2f;
}>>, drawing: passes.Drawing<WgslStruct<{
position: Vec4f;
uv: Vec2f;
bounds: Vec4f;
color: Vec4f;
label: U32;
glyph: U32;
local: Vec2f;
}>, {
label: number;
color: v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
(
const tags: text.TextSet
tags
.
TextSet.drawing: passes.Drawing<WgslStruct<{
position: Vec4f;
uv: Vec2f;
bounds: Vec4f;
color: Vec4f;
label: U32;
glyph: U32;
local: Vec2f;
}>, {
label: number;
color: v4f;
}>

Draws all labels when added to a canvas or scene pass description. It tests depth without writing it.

drawing
);
const tags: text.TextSet
tags
.
TextSet.labels: TgpuBuffer<WgslArray<WgslStruct<{
position: Vec3f;
color: Vec4f;
}>>> & StorageFlag

Holds label anchors and colours, initially at the origin and white. Use TypeGPU patch to upload selected fields, or move and setLabel to write from a kernel.

labels
.
TgpuBuffer<WgslArray<WgslStruct<{ position: Vec3f; color: Vec4f; }>>>.patch(data: Record<number, {
position?: InferInput<Vec3f> | undefined;
color?: InferInput<Vec4f> | undefined;
} | undefined> | InferInput<WgslStruct<{
position: Vec3f;
color: Vec4f;
}>>[] | undefined): void
patch
({ 0: {
position: [number, number, number]
position
: [330, 128, 0.5],
color: [number, number, number, number]
color
: [1, 1, 1, 1] } });
// When the value changes, draw it into the page before the passes that sample it
const tags: text.TextSet
tags
.
TextSet.write(label: number, text: string, options: Options): Layout

Lays out and uploads only the specified label. Use write(label, '') to empty it. Returns the layout, valid until the next write. Throws for a label outside the set or an em value that is not greater than 0.

write
(0, '42', {
Options.em: number

Sets positive units per em. World text uses world units. Text placed with screen or pinned uses points, scaled by the text set pixelRatio.

em
: 180,
Options.align?: "right" | "left" | "center" | undefined

Sets the anchor position along each line. Default center.

align
: 'right' });
const paint: passes.Passes<{
readonly ink: typeof passes.color;
}>
paint
.
Passes<{ readonly ink: typeof color; }>.record(frame: Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly ink: typeof passes.color;
}> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
const frame: Frame
frame
,
const drawn: passes.Drawn
drawn
);
// Sample it from another shader, such as a floor's
const
const ink: TgpuTextureView<WgslTexture2d<F32>>
ink
=
const page: targets.Targets<{
readonly ink: {
readonly format: "rgba8unorm";
readonly sampled: true;
};
}>
page
.
Targets<{ readonly ink: { readonly format: "rgba8unorm"; readonly sampled: true; }; }>.textures: {
readonly ink: targets.Texture<{
readonly format: "rgba8unorm";
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
ink: targets.Texture<{
readonly format: "rgba8unorm";
readonly sampled: true;
}>
ink
.
TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.createView(): TgpuTextureView<WgslTexture2d<F32>> (+3 overloads)
createView
();

The jelly slider draws its value this way and samples it from the floor under the jelly.

A drawing of one pipeline is a plain object, a passes.Drawing<Vertex, Surface>:

Field Default
Vertex required A struct whose position is in clip space. Its other fields reach surfaceOf interpolated, where position is the pixel’s.
at(vertexIndex, instanceIndex) required Makes one Vertex.
draw(pass) required Records its draw into the pass, which holds the pipeline the description built, bound to indices when it gives them.
surfaceOf(vertex) needed for colour Its surface, which every output’s write reads.
color needed for colour Its own output into passes.color, such as passes.shaded.
indices none An index buffer its draw reads, bound to each pipeline built for it. drawIndexed throws without.
label none Names its pipelines. The kit’s drawings have one; scene.add({ ...sparks.drawing, label: 'sparks' }) renames it.
blend none The blend of the color target.
translucent false Draws it as a translucent layer, in any order.
writeMask every channel The write mask of the color target. 0 writes no colour target and no output, for a pass of depth alone.
depth { depthWriteEnabled: true, depthCompare: 'less' } WebGPU’s depth-stencil state without its format. A blended drawing that tests the depth without writing it gives depthWriteEnabled: false.
depthOf(surface) none A depth of its own for each pixel, such as the point an impostor shows, with the description’s bias added. Left out without a depth target.
cutout(vertex) none True where the pixel is cut out of the shape, discarded before surfaceOf. Into depth alone it runs without surfaceOf unless depthOf does.
invariant false Computes position alike in every pipeline built from this vertex, so a later pass can test the depth an earlier one wrote for equal.
flat none Fields of the vertex that reach the pixels flat, the same across a primitive. Integers always do.
linear none Fields of the vertex interpolated in screen space without perspective, such as a distance across a shape extruded on screen.
primitive WebGPU’s The pipeline’s primitive state, such as { cullMode: 'back' }.
alphaToCoverage false Covers the share of samples the color output’s alpha gives, when multisampled.
sampleMask(vertex, surface) every sample The samples each pixel writes when multisampled, bit i for sample i, such as the share one drawing hands to another. Takes no alphaToCoverage, so fold coverage into the mask.
inject() none Fills what its shaders read, before what is piped into the description, which wins.
initAsync() none Compiles what it needs besides the pipeline, such as its kernels.

passes.fullScreen is the Vertex and at of one triangle that covers the screen at depth 0, drawn with draw(3).

  • Each description a drawing is added to builds a pipeline of its own, for its targets, jitter, samples and fills. A renderer gives its drawing, scene.add(particles.drawing), and holds no pipeline.
  • Every target in a description has the same sample count. passes.create reads it once to build pipelines. To change MSAA, create another target set and description, then add each drawing again. Destroy the old description to free its compound drawings’ per-view work.
  • A drawing whose surface can’t feed an output fails to type-check at add, naming the output, until without leaves it out.
  • add returns a passes.Drawn. drawn.draw(pass) records into a pass from begin. drawn.destroy() removes it from the description’s compilation list and makes its draw throw.
  • scene.destroy() destroys every drawing added to it and to the descriptions pipe, without and instead made from it. The targets stay yours.

color requires an output. Passing a function such as color: (s) => s.color fails to type-check at add. passes.shaded writes the surface’s color field as it is. Any other colour is an output of your own whose write reads the surface:

// The surface's colour, premultiplied for `pipelines.blend.over`
const
const premultiplied: passes.Output<{
readonly color: d.v4f;
}, unknown>
premultiplied
=
import passes
passes
.
function output<d.Vec4f, {
readonly color: d.v4f;
}, unknown, undefined>(schema: d.Vec4f, spec: {
readonly clear?: d.v4f | undefined;
readonly varyings?: undefined;
readonly vary?: ((current: unknown, previous: unknown) => undefined) | undefined;
readonly previous?: boolean;
readonly write: (surface: {
readonly color: d.v4f;
}, carried: undefined) => d.v4f;
}): passes.Output<{
readonly color: d.v4f;
}, unknown>

Defines how a pass writes one target from renderer data. write takes the renderer's surface, and its parameter type declares the fields it needs. For vertex data, supply varyings and vary. vary runs per vertex, and its interpolated result reaches write. With previous: true, vary also receives the previous frame's vertex. Throws if vary has no varyings schema, previous has no vary, or vary takes two parameters without previous: true.

@param ― schema what the target holds per pixel, such as d.vec2f for an rg16float target

@param ― spec write, which gives the value at a pixel, and what it clears to and carries from the vertex

@returns ― an output to give a target in passes.create

output
(
import d
d
.
const vec4f: d.Vec4f
vec4f
, {
write: (surface: {
readonly color: d.v4f;
}, carried: undefined) => d.v4f
write
: (
surface: {
readonly color: d.v4f;
}
surface
: { readonly
color: d.v4f
color
:
import d
d
.
export v4f

Interface representing its WGSL vector type counterpart: vec4f or vec4. A vector with 4 elements of type f32

v4f
}) => {
'use gpu';
return
import d
d
.
const vec4f: d.Vec4f
(v0: AnyNumericVec3Instance, w: number) => d.v4f (+9 overloads)
vec4f
(
surface: {
readonly color: d.v4f;
}
surface
.
color: d.v4f
color
.
xyz: d.v3f
xyz
*
surface: {
readonly color: d.v4f;
}
surface
.
color: d.v4f
color
.
v4f.w: number
w
,
surface: {
readonly color: d.v4f;
}
surface
.
color: d.v4f
color
.
v4f.w: number
w
);
},
});
const
const veil: passes.Drawn
veil
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
}>
scene
.
Passes<{ readonly hdr: typeof passes.color; }>.add<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
readonly color: d.v4f;
}>(this: passes.Passes<passes.Fed<{
readonly color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
readonly color: d.v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
({ ...
const drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
readonly color: d.v4f;
}>
drawing
,
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { readonly color: d.v4f; }>.color?: passes.Output<{
readonly color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}> | undefined

Supplies the output for the color target when the description has one.

color
:
const premultiplied: passes.Output<{
readonly color: d.v4f;
}, unknown>
premultiplied
,
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { readonly color: d.v4f; }>.blend?: GPUBlendState | undefined

Sets blending for the color target. Default none.

blend
:
import pipelines
pipelines
.
const blend: Readonly<{
add: Readonly<{
color: GPUBlendComponent;
alpha: GPUBlendComponent;
}>;
over: Readonly<{
color: GPUBlendComponent;
alpha: GPUBlendComponent;
}>;
straight: Readonly<{
color: GPUBlendComponent;
alpha: GPUBlendComponent;
}>;
}>

Provides blend states for pipeline targets.

blend
.
over: Readonly<{
color: GPUBlendComponent;
alpha: GPUBlendComponent;
}>

Composites premultiplied colour over the target. The fragment returns vec4f(rgb * a, a).

over
});

A renderer with several pipelines or per-view resources supplies a passes.Compound object with build(into). Per-view resources can include a list of objects visible to a camera. Each description calls build once, so the shadow and scene get separate pipelines. build creates them with into.pipeline(drawing) and returns a passes.Built with draw, initAsync and an optional destroy for per-view cleanup. Instances renderers use this form.

These drawings share a vertex function. Their two pipelines draw a fill, then an outline:

const
const outlined: passes.Compound<Seen, {
position: d.v4f;
}>
outlined
:
import passes
passes
.
interface Compound<S = never, X = never>

Builds several pipelines or resources for each description, such as a list of visible objects. Each description calls build with itself. The drawing creates its pipelines through into.pipeline.

Compound
<
type Seen = {
readonly color: d.v4f;
}
Seen
,
import d
d
.
type Infer<T> = T extends {
readonly [$repr]: infer TRepr;
} ? TRepr : T
export Infer

Extracts the inferred representation of a resource. For inferring types as seen by the GPU, see

InferGPU

@example type A = Infer // => number type B = Infer<WgslArray> // => number[] type C = Infer<Atomic> // => number

Infer
<typeof
const Corner: d.WgslStruct<{
position: d.Vec4f;
}>
Corner
>> = {
Compound<Seen, { position: v4f; }>.build(into: passes.Passes): passes.Built
build
(
into: passes.Passes<passes.Writes>
into
) {
const
const filling: TgpuRenderPipeline<never>
filling
=
into: passes.Passes<passes.Writes>
into
.
Passes<Writes>.pipeline<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>(drawing: passes.Shaders<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>, from?: WithBinding): TgpuRenderPipeline

Builds a pipeline from drawing using from and the description's piped fills. from defaults to the root with the fills given to beneath. Compound drawings use this method, and their initAsync compiles the resulting pipelines.

pipeline
(
const fill: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>
fill
);
const
const rimming: TgpuRenderPipeline<never>
rimming
=
into: passes.Passes<passes.Writes>
into
.
Passes<Writes>.pipeline<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>(drawing: passes.Shaders<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>, from?: WithBinding): TgpuRenderPipeline

Builds a pipeline from drawing using from and the description's piped fills. from defaults to the root with the fills given to beneath. Compound drawings use this method, and their initAsync compiles the resulting pipelines.

pipeline
(
const rim: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
}>, Seen>
rim
);
return {
Built.draw(pass: TgpuRenderCommands, layer: number): void

Records the drawing into a pass. layer is the layer the pass draws into, 0 without layers, for per-layer work such as a visible list for each.

draw
(
pass: TgpuRenderCommands
pass
) {
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.setPipeline(pipeline: TgpuRenderPipeline): void

Sets the current

TgpuRenderPipeline

for subsequent draw calls

setPipeline
(
const filling: TgpuRenderPipeline<never>
filling
);
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(4,
const count: number
count
);
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.setPipeline(pipeline: TgpuRenderPipeline): void

Sets the current

TgpuRenderPipeline

for subsequent draw calls

setPipeline
(
const rimming: TgpuRenderPipeline<never>
rimming
);
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(4,
const count: number
count
);
},
async
Built.initAsync(): Promise<void>
initAsync
() {
await
var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.
PromiseConstructor.all<[Promise<void>, Promise<void>]>(values: [Promise<void>, Promise<void>]): Promise<[void, void]> (+1 overload)

Creates a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when any Promise is rejected.

@param ― values An array of Promises.

@returns ― A new Promise.

all
([
const filling: TgpuRenderPipeline<never>
filling
.
TgpuRenderPipeline<never>.initAsync(): Promise<void>

Immediately resolves the pipeline, then awaits device.createRenderPipelineAsync(). NOTE: it is not necessary to initialize pipelines manually.

initAsync
(),
const rimming: TgpuRenderPipeline<never>
rimming
.
TgpuRenderPipeline<never>.initAsync(): Promise<void>

Immediately resolves the pipeline, then awaits device.createRenderPipelineAsync(). NOTE: it is not necessary to initialize pipelines manually.

initAsync
()]);
},
};
},
};
const
const drawn: passes.Drawn
drawn
=
const scene: passes.Passes<{
readonly color: typeof passes.color;
}>
scene
.
Passes<{ readonly color: typeof passes.color; }>.add<Seen, {
position: d.v4f;
}>(this: passes.Passes<passes.Fed<Seen, {
position: d.v4f;
}>>, drawing: passes.Compound<Seen, {
position: d.v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
(
const outlined: passes.Compound<Seen, {
position: d.v4f;
}>
outlined
);

For a createRenderPipeline of your own, into.stages(drawing) gives a drawing’s stages, targets and depth state to spread into it.

In a description with layers, into.layers is how many there are, for per-layer work such as a visible list for each. The built draw(pass, layer) receives the layer of the pass it draws into, to pick that layer’s work.

passes.output(schema, spec) defines the value each renderer writes per pixel to one target:

  • write(surface, carried) runs per pixel and returns a value of schema. Its first parameter types the required surface data. (surface: { id: number }) requires an id, so only surfaces with that field can write it.
  • vary(vertex, before) runs per vertex and returns a varyings struct. The rasteriser interpolates it for write’s carried parameter. With previous: true, before holds last frame’s vertex. The renderer’s vertex code compiles again with history.previously to read last frame’s camera and other temporal fills.
  • clear is what the target holds where nothing drew, zero by default. The color target clears to the description’s clear option instead.
  • Integers go between the stages flat.
// Where the surface at each pixel was last frame, in UV
const
const Clips: d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}>
Clips
=
import d
d
.
struct<{
now: d.Vec4f;
before: d.Vec4f;
}>(props: {
now: d.Vec4f;
before: d.Vec4f;
}): d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}>
export struct

Creates a struct schema that can be used to construct GPU buffers. Ensures proper alignment and padding of properties (as opposed to a d.unstruct schema). The order of members matches the passed in properties object.

@example const CircleStruct = d.struct({ radius: d.f32, pos: d.vec3f });

@param ― props Record with string keys and TgpuData values, each entry describing one struct member.

struct
({
now: d.Vec4f
now
:
import d
d
.
const vec4f: d.Vec4f
vec4f
,
before: d.Vec4f
before
:
import d
d
.
const vec4f: d.Vec4f
vec4f
});
const
const motion: passes.Output<unknown, {
position: d.v4f;
}>
motion
=
import passes
passes
.
function output<d.Vec2f, unknown, {
position: d.v4f;
}, d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}>>(schema: d.Vec2f, spec: {
readonly clear?: d.v2f | undefined;
readonly varyings?: d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}> | undefined;
readonly vary?: ((current: {
position: d.v4f;
}, previous: {
position: d.v4f;
}) => {
now: d.v4f;
before: d.v4f;
}) | undefined;
readonly previous?: boolean;
readonly write: (surface: unknown, carried: {
now: d.v4f;
before: d.v4f;
}) => d.v2f;
}): passes.Output<unknown, {
position: d.v4f;
}>

Defines how a pass writes one target from renderer data. write takes the renderer's surface, and its parameter type declares the fields it needs. For vertex data, supply varyings and vary. vary runs per vertex, and its interpolated result reaches write. With previous: true, vary also receives the previous frame's vertex. Throws if vary has no varyings schema, previous has no vary, or vary takes two parameters without previous: true.

@param ― schema what the target holds per pixel, such as d.vec2f for an rg16float target

@param ― spec write, which gives the value at a pixel, and what it clears to and carries from the vertex

@returns ― an output to give a target in passes.create

output
(
import d
d
.
const vec2f: d.Vec2f
vec2f
, {
varyings?: d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}> | undefined
varyings
:
const Clips: d.WgslStruct<{
now: d.Vec4f;
before: d.Vec4f;
}>
Clips
,
previous?: boolean | undefined

Passes the previous frame's vertex as the second argument to vary. Without it, the second argument is zero. This must be explicit because tgpu.fn and pipe hide the parameters of vary. Default false.

previous
: true,
vary?: ((current: {
position: d.v4f;
}, previous: {
position: d.v4f;
}) => {
now: d.v4f;
before: d.v4f;
}) | undefined
vary
: (
now: {
position: d.v4f;
}
now
: {
position: d.v4f
position
:
import d
d
.
export v4f

Interface representing its WGSL vector type counterpart: vec4f or vec4. A vector with 4 elements of type f32

v4f
},
before: {
position: d.v4f;
}
before
: {
position: d.v4f
position
:
import d
d
.
export v4f

Interface representing its WGSL vector type counterpart: vec4f or vec4. A vector with 4 elements of type f32

v4f
}) => {
'use gpu';
return
const Clips: d.WgslStruct
(props?: {
now: d.v4f;
before: d.v4f;
} | undefined) => {
now: d.v4f;
before: d.v4f;
}
Clips
({
now: d.v4f
now
:
now: {
position: d.v4f;
}
now
.
position: d.v4f
position
,
before: d.v4f
before
:
before: {
position: d.v4f;
}
before
.
position: d.v4f
position
});
},
write: (surface: unknown, carried: {
now: d.v4f;
before: d.v4f;
}) => d.v2f
write
: (
_surface: unknown
_surface
: unknown,
clips: {
now: d.v4f;
before: d.v4f;
}
clips
) => {
'use gpu';
return
const uvOf: (clip: d.v4f) => d.v2f
uvOf
(
clips: {
now: d.v4f;
before: d.v4f;
}
clips
.
before: d.v4f
before
) -
const uvOf: (clip: d.v4f) => d.v2f
uvOf
(
clips: {
now: d.v4f;
before: d.v4f;
}
clips
.
now: d.v4f
now
);
},
});
const
const id: passes.Output<{
id: number;
}, unknown>
id
=
import passes
passes
.
function output<d.U32, {
id: number;
}, unknown, undefined>(schema: d.U32, spec: {
readonly clear?: number | undefined;
readonly varyings?: undefined;
readonly vary?: ((current: unknown, previous: unknown) => undefined) | undefined;
readonly previous?: boolean;
readonly write: (surface: {
id: number;
}, carried: undefined) => number;
}): passes.Output<{
id: number;
}, unknown>

Defines how a pass writes one target from renderer data. write takes the renderer's surface, and its parameter type declares the fields it needs. For vertex data, supply varyings and vary. vary runs per vertex, and its interpolated result reaches write. With previous: true, vary also receives the previous frame's vertex. Throws if vary has no varyings schema, previous has no vary, or vary takes two parameters without previous: true.

@param ― schema what the target holds per pixel, such as d.vec2f for an rg16float target

@param ― spec write, which gives the value at a pixel, and what it clears to and carries from the vertex

@returns ― an output to give a target in passes.create

output
(
import d
d
.
const u32: d.U32
export u32

A schema that represents an unsigned 32-bit integer value. (equivalent to u32 in WGSL)

Can also be called to cast a value to an u32 in accordance with WGSL casting rules.

@example const value = u32(); // 0

@example const value = u32(7); // 7

@example const value = u32(3.14); // 3

@example const value = u32(-1); // 4294967295

@example const value = u32(-3.1); // 0

u32
, {
clear?: number | undefined

Sets the value where nothing drew, as a value of schema. A drawing's color writes into the description's color target, which uses the description's clear instead. Default zero.

clear
: 0xffffffff, // nothing here
write: (surface: {
id: number;
}, carried: undefined) => number
write
: (
surface: {
id: number;
}
surface
: {
id: number
id
: number }) => {
'use gpu';
return
surface: {
id: number;
}
surface
.
id: number
id
;
},
});

passes.color marks the target for each renderer’s colour. passes.depth marks the depth target. A description allows at most one of each and leaves unlisted targets untouched.

scene.without('id') omits the id output and its varyings for drawings that can’t supply it. scene.instead({ motion: skyMotion }) writes an output of the drawing’s own into that target. Both draw into the pass scene.begin starts:

const embers = scene.without('id').add(sparks.drawing);
const sky = scene.without('id').instead({ motion: skyMotion }).add(skyDrawing);
Target What the drawing writes there
passes.color Its own color, through its blend and writeMask.
passes.depth Its depth, or depthOf’s, as its depth state says: tested and written by default.
An output The output’s write, from its surface and the output’s varyings. Outputs don’t blend: a blended drawing replaces the value wherever it draws, its transparent corners too.
An output instead replaces The replacement’s write.
An output without leaves out, opaque The output’s clear, as if nothing drew there.
An output without leaves out, with a blend Nothing: what is under it stays.

The kit’s drawings:

Drawing Vertex Surface Blend Depth
An instances renderer instances.Corner instances.Lit none, or as its blend says written; tested only when translucent
particles.drawing particles.Corner particles.Seen add, or as its blend says tested only
A lines set’s drawing lines.Corner lines.Seen over, or as its blend says tested only; written with opaque
trails.drawing lines.Corner lines.Seen add, or as its blend says tested only
A text set’s drawing text.Corner text.Seen over, or as its blend says tested only

Draw what tests the depth without writing it after the opaque drawings. Impostors draw through an instances renderer.

jelliesTranslucent jellies in any draw order; tap one and it flashes.

Every bell, oral arm and tentacle is a translucent drawing. Turn off oit to draw them into a description without the two targets: they blend over in draw order, and the moon jelly behind the sea nettle covers it.

Blending translucent drawings over each other looks right only when they draw from far to near. That needs sorting every frame, and still fails where two surfaces cross. A drawing with translucent: true needs no order. Give the description two more targets, one marked passes.accumulation and one marked passes.revealage. Each translucent pixel adds its colour into the first, weighted so that nearer layers count most, and multiplies the share of what lies behind it that still shows into the second. scene.composite(frame) then lays the average over the colour target in a pass of its own:

import {
import passes
passes
,
import targets
targets
} from '@typegpu/kit';
const
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
=
import targets
targets
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}, options?: targets.Options): targets.Targets<...>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
, {
hdr: {
readonly format: "rgba16float";
readonly sampled: true;
}
hdr
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
accum: {
readonly format: "rgba16float";
readonly sampled: true;
}
accum
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
reveal: {
readonly format: "r16float";
readonly sampled: true;
}
reveal
: {
format: "r16float"
format
: 'r16float',
sampled: true
sampled
: true },
depth: {
readonly format: "depth24plus";
}
depth
: {
format: "depth24plus"
format
: 'depth24plus' },
});
const
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>
scene
=
import passes
passes
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}, {
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>(root: TgpuRoot, screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>, writes: {
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}, options?: passes.TargetOptions<...> | undefined): passes.Passes<...> (+1 overload)

Describes the targets and outputs for scene passes. With a surface such as the canvas, writes only each renderer's colour. With a target set, writes colour into the target marked color, depth into the target marked depth, and other outputs into their named targets. Multisampled targets resolve according to resolve. Targets with layers draw one pass per layer, and every target the description draws into needs the same layers. add builds a renderer's drawing. begin starts a pass. pipe supplies fills such as a camera.

@param ― screen the surface, or the targets, which give the formats; each one the description names is drawn into

@param ― writes what fills each target, by its key in screen

@returns ― a description you destroy, which holds the pipelines it builds

create
(
const root: TgpuRoot
root
,
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly accum: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly reveal: {
readonly format: "r16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
, {
hdr: typeof passes.color
hdr
:
import passes
passes
.
const color: typeof passes.color

Marks the target that receives each renderer's colour.

color
,
accum: passes.Output<unknown, {
readonly position: d.v4f;
}>
accum
:
import passes
passes
.
const accumulation: passes.Output<unknown, {
readonly position: d.v4f;
}>

Marks the target that translucent drawings add their colour into, weighted by their distance from the eye, so that the nearest layers count most. Use an rgba16float target with sampled: true, beside targets marked passes.color and passes.revealage. Clears to zero.

accumulation
,
reveal: passes.Output<unknown, unknown>
reveal
:
import passes
passes
.
const revealage: passes.Output<unknown, unknown>

Marks the target where translucent drawings multiply the share of what lies behind them that shows through. Use an r16float or r8unorm target with sampled: true, beside targets marked passes.color and passes.accumulation. Clears to one.

revealage
,
depth: typeof passes.depth
depth
:
import passes
passes
.
const depth: typeof passes.depth

Marks the depth target.

depth
,
})
.
Passes<{ readonly hdr: typeof color; readonly accum: Output<unknown, { readonly position: d.v4f; }>; readonly reveal: Output<unknown, unknown>; readonly depth: typeof depth; }>.pipe(fill: Inject): passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>

Adds fill after existing fills and returns a description of the same passes. Piped fills take precedence over a drawing's own. For example, passes.create(…).pipe(view.inject()) uses the camera from view.

pipe
(
const view: cameras.OrbitCamera
view
.
CameraBase.inject(): Inject

Fills cameras.current for the pipelines created from the configuration it is piped into.

inject
());
// The opaque ground first, then the translucent bells
const
const drawn: passes.Drawn[]
drawn
= [
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly accum: Output<unknown, { readonly position: d.v4f; }>; readonly reveal: Output<unknown, unknown>; readonly depth: typeof depth; }>.add<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>(this: passes.Passes<passes.Fed<Seen, {
position: d.v4f;
uv: d.v2f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
(
const ground: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>
ground
),
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly accum: Output<unknown, { readonly position: d.v4f; }>; readonly reveal: Output<unknown, unknown>; readonly depth: typeof depth; }>.add<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>(this: passes.Passes<passes.Fed<Seen, {
position: d.v4f;
uv: d.v2f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
({ ...
const bells: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, Seen>
bells
,
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, Seen>.translucent?: boolean | undefined

Draws the color output, premultiplied by its alpha, as a translucent layer. With targets marked passes.accumulation and passes.revealage, it adds into them in any order and composite lays the result over the colour target. Elsewhere it blends over the colour target in draw order. Tests depth without writing it, so draw it after the opaque drawings. Takes no blend, and a description of depth alone refuses it. Default false.

translucent
: true })];
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly accum: Output<unknown, { readonly position: d.v4f; }>; readonly reveal: Output<unknown, unknown>; readonly depth: typeof depth; }>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const drawn: passes.Drawn[]
drawn
);
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly accum: passes.Output<unknown, {
readonly position: d.v4f;
}>;
readonly reveal: passes.Output<unknown, unknown>;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly accum: Output<unknown, { readonly position: d.v4f; }>; readonly reveal: Output<unknown, unknown>; readonly depth: typeof depth; }>.composite(frame: frames.Frame | TgpuCommandEncoder, options?: Timed): void

Lays what translucent drawings added to the targets marked passes.accumulation and passes.revealage over the colour target, or over its resolve destination, in a pass of its own. Call it after the pass that drew them and before anything reads the colour. Records nothing while enabled is false. Throws without those targets.

composite
(
frame: frames.Frame
frame
);
});
  • A translucent drawing’s color output is premultiplied, d.vec4f(rgb * alpha, alpha). Colour with an alpha of 0 adds light, as a glow does.
  • It tests the depth that opaque drawings wrote before it and writes none. Draw it after them, in any order among the translucent ones.
  • Opaque drawings leave the two targets alone. Outputs such as motion take a translucent drawing’s value as they take a blended one’s.
  • In a description without the two targets, the same drawing blends over the colour target in draw order. The jellies keep a second description to turn the targets off.
  • composite reads both targets as textures, so each needs sampled: true. It draws over the colour target, or over its resolve destination when it resolves, and throws in a description without the targets.
  • An instances renderer with blend: 'translucent' or 'clear' draws translucent.

pipe(fill) adds a fill to every pipeline built from the returned description. It applies after the drawing’s fill and takes precedence. passes.create(…).pipe(view.inject()) uses view as its camera. A shadow map uses a description of depth alone, viewed from the sun.

beneath(fill) adds a fill that applies before the drawing’s fill, as a default the drawing can override. scene.beneath(light.inject()) lights every drawing that doesn’t fill the lighting’s hooks itself. Fills given to beneath and to pipe each apply in call order.

inject() returns the description’s fills, those given to beneath and then the piped ones. A compound drawing that builds pipelines from its own configuration, such as an instances renderer, starts from inject() and applies its own fills over it, so beneath lights it too.

A line two points wide or a label pinned beside a star needs the size of what the pass draws into, which differs between the canvas, a low-resolution target and a shadow map. Every description fills passes.pixels in each pipeline and kernel it builds. It holds the drawn region’s size in pixels and its pixelRatio, the pixels a point takes:

import {
import cameras
cameras
,
import passes
passes
} from '@typegpu/kit';
/** Where a world point lands on the target, moved `offset` points right and up. */
const
const besideInPoints: (world: d.v3f, offset: d.v2f) => d.v4f

Where a world point lands on the target, moved offset points right and up.

besideInPoints
= (
world: d.v3f
world
:
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
,
offset: d.v2f
offset
:
import d
d
.
export v2f

Interface representing its WGSL vector type counterpart: vec2f or vec2. A vector with 2 elements of type f32

v2f
) => {
'use gpu';
const
const view: {
size: d.v2f;
pixelRatio: number;
}
view
=
import passes
passes
.
const pixels: TgpuAccessor<d.WgslStruct<{
size: d.Vec2f;
pixelRatio: d.F32;
}>>

Holds the region the pass draws into, in every pipeline and kernel a description builds. Each description writes it as a pass begins, when the region has changed. Drawings that size things in pixels or points read it, such as lines and screen text.

pixels
.
TgpuAccessor<WgslStruct<{ size: Vec2f; pixelRatio: F32; }>>.$: {
size: d.v2f;
pixelRatio: number;
}
$
;
const
const clip: d.v4f
clip
=
import cameras
cameras
.
const current: TgpuAccessor<d.WgslStruct<{
viewProjection: d.Mat4x4f;
position: d.Vec3f;
right: d.Vec3f;
up: d.Vec3f;
}>>

Provides the camera for a pipeline. A camera's inject() fills it with the camera uniform.

current
.
TgpuAccessor<WgslStruct<{ viewProjection: Mat4x4f; position: Vec3f; right: Vec3f; up: Vec3f; }>>.$: {
viewProjection: d.m4x4f;
position: d.v3f;
right: d.v3f;
up: d.v3f;
}
$
.
viewProjection: d.m4x4f

Transforms world coordinates to clip space.

viewProjection
*
import d
d
.
const vec4f: d.Vec4f
(v0: AnyNumericVec3Instance, w: number) => d.v4f (+9 overloads)
vec4f
(
world: d.v3f
world
, 1);
return
import d
d
.
const vec4f: d.Vec4f
(v0: AnyNumericVec2Instance, v1: AnyNumericVec2Instance) => d.v4f (+9 overloads)
vec4f
(
const clip: d.v4f
clip
.
xy: d.v2f
xy
+ ((
offset: d.v2f
offset
* 2 *
const view: {
size: d.v2f;
pixelRatio: number;
}
view
.
pixelRatio: number

Holds pixels per point: the surface's pixelRatio, scaled with a target's resolution, so a one-point line keeps its size in a low-resolution target. 1 for targets that follow a size without a ratio, such as a shadow map.

pixelRatio
) /
const view: {
size: d.v2f;
pixelRatio: number;
}
view
.
size: d.v2f

Holds the width and height of the drawn region in pixels.

size
) *
const clip: d.v4f
clip
.
v4f.w: number
w
,
const clip: d.v4f
clip
.
zw: d.v2f
zw
);
};
  • Over a surface, size is the surface’s and pixelRatio its pixelRatio. Over targets, size is the drawn region and pixelRatio the source’s, scaled by the region, so a point keeps its size at a lower resolution or through targets.scaled. A source without a ratio, such as a shadow map’s fixed size, has a pixelRatio of 1.
  • begin and record write it when the region has changed. A pipeline from pipeline() drawn into a pass you begin yourself, or a kernel built from inject() in a frame where the description doesn’t begin, reads the region of the last begin.
  • Each description holds its own uniform, even beside another over the same targets. A pipeline that reads it binds 1 uniform.
  • Descriptions also fill two slots: passes.sampleCount with the samples per pixel, and passes.depthOnly with whether they draw into depth alone. A drawing reads them to cut its own edges where there is one sample, or to leave out what only shows in colour, such as an antialiased edge in a shadow map.

A drawing’s shaders read buffers, textures and samplers through accessors, which its inject() fills. The description builds each pipeline from that fill, so a draw binds no group of yours:

const
const tints: TgpuAccessor<d.WgslArray<d.Vec4f>>
tints
=
const tgpu: {
const: typeof import("node_modules/typegpu/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/tgpuUnstable");
}

@module ― typegpu

tgpu
.
accessor: <d.WgslArray<d.Vec4f>>(schema: d.WgslArray<d.Vec4f>, defaultValue?: DataAccessorIn<NoInfer<d.WgslArray<d.Vec4f>>> | undefined) => TgpuAccessor<d.WgslArray<d.Vec4f>> (+1 overload)
accessor
(
import d
d
.
arrayOf<d.Vec4f>(elementType: d.Vec4f, elementCount: number): d.WgslArray<d.Vec4f> (+2 overloads)
export arrayOf

@location ― . Wrap align/size in a struct instead, e.g. d.arrayOf(d.struct({ value: d.align(16, d.u32) }), n).

arrayOf
(
import d
d
.
const vec4f: d.Vec4f
vec4f
, 4));
const
const picture: TgpuAccessor<d.WgslTexture2d<d.F32>>
picture
=
const tgpu: {
const: typeof import("node_modules/typegpu/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/tgpuUnstable");
}

@module ― typegpu

tgpu
.
accessor: <d.WgslTexture2d<d.F32>>(schema: d.WgslTexture2d<d.F32>, defaultValue?: TextureAccessorIn<NoInfer<d.WgslTexture2d<d.F32>>> | undefined) => TgpuAccessor<d.WgslTexture2d<d.F32>> (+1 overload)
accessor
(
import d
d
.
texture2d<d.F32>(sampleType: d.F32): d.WgslTexture2d<d.F32> (+1 overload)
export texture2d
texture2d
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
));
const
const smooth: TgpuAccessor<d.WgslSampler>
smooth
=
const tgpu: {
const: typeof import("node_modules/typegpu/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/tgpuUnstable");
}

@module ― typegpu

tgpu
.
accessor: <d.WgslSampler>(schema: d.WgslSampler, defaultValue?: DataAccessorIn<NoInfer<d.WgslSampler>> | undefined) => TgpuAccessor<d.WgslSampler> (+1 overload)
accessor
(
import d
d
.
function sampler(): d.WgslSampler
export sampler
sampler
());
const
const tintBuffer: TgpuReadonly<d.WgslArray<d.Vec4f>>
tintBuffer
=
const root: TgpuRoot
root
.
TgpuRoot.createReadonly<d.WgslArray<d.Vec4f>>(typeSchema: d.WgslArray<d.Vec4f>, initial?: ((buffer: TgpuBuffer<NoInfer<d.WgslArray<d.Vec4f>>>) => void) | d.InferInput<NoInfer<d.WgslArray<d.Vec4f>>> | undefined): TgpuReadonly<d.WgslArray<d.Vec4f>> (+1 overload)

Allocates memory on the GPU, allows passing data between host and shader. Read-only on the GPU, optimized for large data. For a general-purpose buffer, use

TgpuRoot.createBuffer

.

@param ― typeSchema The type of data that this buffer will hold.

@param ― initial Either initial value of the buffer, or an initializer to execute on the mapped buffer. (optional)

createReadonly
(
import d
d
.
arrayOf<d.Vec4f>(elementType: d.Vec4f, elementCount: number): d.WgslArray<d.Vec4f> (+2 overloads)
export arrayOf

@location ― . Wrap align/size in a struct instead, e.g. d.arrayOf(d.struct({ value: d.align(16, d.u32) }), n).

arrayOf
(
import d
d
.
const vec4f: d.Vec4f
vec4f
, 4));
const
const image: TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
image
=
const root: TgpuRoot
root
.
TgpuRoot.createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}>
createTexture
({
size: [512, 512]

The width, height, and depth or layer count of the texture.

size
: [512, 512],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm' }).
TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const
const view: TgpuTextureView<d.WgslTexture2d<d.F32>>
view
=
const image: TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
image
.
TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.createView<d.WgslTexture2d<d.F32>>(schema: d.WgslTexture2d<d.F32>, viewDescriptor?: (TgpuTextureViewDescriptor & {
sampleType?: "float" | "unfilterable-float" | undefined;
}) | undefined): TgpuTextureView<d.WgslTexture2d<d.F32>> (+3 overloads)
createView
(
import d
d
.
texture2d<d.F32>(sampleType: d.F32): d.WgslTexture2d<d.F32> (+1 overload)
export texture2d
texture2d
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
));
const
const sampler: TgpuFixedSampler
sampler
=
const root: TgpuRoot
root
.
TgpuRoot.createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler
({
WgslSamplerProps.magFilter?: GPUFilterMode | undefined

Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel.

magFilter
: 'linear',
WgslSamplerProps.minFilter?: GPUFilterMode | undefined

Specifies the sampling behavior when the sample footprint is larger than one texel.

minFilter
: 'linear' });
const
const backdrop: passes.Drawn
backdrop
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
}>
scene
.
Passes<{ readonly hdr: typeof passes.color; }>.add<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
color: d.v4f;
}>(this: passes.Passes<passes.Fed<{
color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
color: d.v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
({
...
import passes
passes
.
const fullScreen: {
Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>;
at: (vertexIndex: number, _instanceIndex: number) => {
position: d.v4f;
uv: d.v2f;
};
}

Provides Vertex and at for a renderer that covers the screen with one triangle at depth 0. Draw it with draw(3). Use { ...passes.fullScreen, surfaceOf, color, draw }.

fullScreen
,
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.surfaceOf?: ((vertex: {
position: d.v4f;
uv: d.v2f;
}) => {
color: d.v4f;
}) | undefined

Computes data at a pixel from the interpolated vertex. position is the pixel position. Required for descriptions that write colour and for depthOf.

surfaceOf
: (
corner: {
position: d.v4f;
uv: d.v2f;
}
corner
:
import d
d
.
type Infer<T> = T extends {
readonly [$repr]: infer TRepr;
} ? TRepr : T
export Infer

Extracts the inferred representation of a resource. For inferring types as seen by the GPU, see

InferGPU

@example type A = Infer // => number type B = Infer<WgslArray> // => number[] type C = Infer<Atomic> // => number

Infer
<typeof
import passes
passes
.
const fullScreen: {
Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>;
at: (vertexIndex: number, _instanceIndex: number) => {
position: d.v4f;
uv: d.v2f;
};
}

Provides Vertex and at for a renderer that covers the screen with one triangle at depth 0. Draw it with draw(3). Use { ...passes.fullScreen, surfaceOf, color, draw }.

fullScreen
.
type Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>
Vertex
>) => {
'use gpu';
const
const band: number
band
=
import std
std
.
function min(fst: number, ...rest: number[]): number (+1 overload)
export min
min
(
import d
d
.
function u32(v?: number | boolean): number
export u32

A schema that represents an unsigned 32-bit integer value. (equivalent to u32 in WGSL)

Can also be called to cast a value to an u32 in accordance with WGSL casting rules.

@example const value = u32(); // 0

@example const value = u32(7); // 7

@example const value = u32(3.14); // 3

@example const value = u32(-1); // 4294967295

@example const value = u32(-3.1); // 0

u32
(
corner: {
position: d.v4f;
uv: d.v2f;
}
corner
.
uv: d.v2f
uv
.
v2f.y: number
y
* 4), 3);
return
const Seen: d.WgslStruct
(props?: {
color: d.v4f;
} | undefined) => {
color: d.v4f;
}
Seen
({
color: d.v4f
color
:
import std
std
.
textureSample<d.texture2d<d.F32>>(texture: d.texture2d<d.F32>, sampler: d.sampler, coords: d.v2f, offset?: d.v2i): d.v4f (+8 overloads)
export textureSample
textureSample
(
const picture: TgpuAccessor<d.WgslTexture2d<d.F32>>
picture
.
TgpuAccessor<WgslTexture2d<F32>>.$: d.texture2d<d.F32>
$
,
const smooth: TgpuAccessor<d.WgslSampler>
smooth
.
TgpuAccessor<WgslSampler>.$: d.sampler
$
,
corner: {
position: d.v4f;
uv: d.v2f;
}
corner
.
uv: d.v2f
uv
) *
const tints: TgpuAccessor<d.WgslArray<d.Vec4f>>
tints
.
TgpuAccessor<WgslArray<Vec4f>>.$: d.v4f[]
$
[
const band: number
band
]! });
},
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.color?: passes.Output<{
color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}> | undefined

Supplies the output for the color target when the description has one.

color
:
import passes
passes
.
const shaded: passes.Output<{
readonly color: d.v4f;
}, unknown>

Writes the surface's color unchanged as a renderer's color output.

shaded
,
Drawing<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.inject?(): Inject

Fills shader accessors over the fills given to the description's beneath and under those piped into it, which take precedence.

inject
: () => (
cfg: Configurable
cfg
) =>
cfg: Configurable
cfg
.
Withable<Configurable>.with<d.WgslArray<d.Vec4f>>(accessor: TgpuAccessor<d.WgslArray<d.Vec4f>>, value: DataAccessorIn<NoInfer<d.WgslArray<d.Vec4f>>>): Configurable (+2 overloads)
with
(
const tints: TgpuAccessor<d.WgslArray<d.Vec4f>>
tints
,
const tintBuffer: TgpuReadonly<d.WgslArray<d.Vec4f>>
tintBuffer
)
.
Withable<Configurable>.with<d.WgslTexture2d<d.F32>>(accessor: TgpuAccessor<d.WgslTexture2d<d.F32>>, value: TextureAccessorIn<NoInfer<d.WgslTexture2d<d.F32>>>): Configurable (+2 overloads)
with
(
const picture: TgpuAccessor<d.WgslTexture2d<d.F32>>
picture
, () =>
const view: TgpuTextureView<d.WgslTexture2d<d.F32>>
view
.
TgpuTextureView<WgslTexture2d<F32>>.$: d.texture2d<d.F32>
$
)
.
Withable<Configurable>.with<d.WgslSampler>(accessor: TgpuAccessor<d.WgslSampler>, value: DataAccessorIn<NoInfer<d.WgslSampler>>): Configurable (+2 overloads)
with
(
const smooth: TgpuAccessor<d.WgslSampler>
smooth
, () =>
const sampler: TgpuFixedSampler
sampler
.
TgpuSampler.$: d.sampler
$
),
Drawing<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.draw(pass: TgpuRenderCommands): void

Records a draw into the pass, on which the description has set the pipeline it built. That pipeline binds indices if supplied. drawIndexed throws without an index buffer. A group the drawing sets with pass.setBindGroup stays for later drawings in the pass that read its layout, so give such a layout to one drawing.

draw
: (
pass: TgpuRenderCommands
pass
) =>
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3),
});
  • Shaders can read tintBuffer.$ and view.$ without accessors. The resources become fixed bindings in each pipeline’s automatic group.
  • A kernel of your own reads them the same way, created from root.pipe(fill), with scene.inject() piped in too when it reads the camera.
  • WebGPU forbids read-write storage in a vertex stage. Fill an accessor that a kernel writes and a vertex stage reads with byStage(buffer), read-write in compute and read-only elsewhere.
  • cfg.with takes a slot or accessor and its value. Passing a bind group as cfg.with(group) fails with TS2554.

A resource you swap without new pipelines, such as a texture that follows the canvas, goes in a bindings.layout part. Share the part with bindings.share before passes.create, and give the description the shared layout as shared. Every pass it begins then sets the shared group:

import {
import bindings
bindings
} from '@typegpu/kit';
const
const backdropBindings: bindings.Layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
backdropBindings
=
import bindings
bindings
.
function layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>(entries: {
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}): bindings.Layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>

Declares bindings for module shaders from the entries that tgpu.bindGroupLayout takes. Define the layout once beside the shaders. A part made with bind can bind its resources directly. Call share before creating pipelines to put the part in a shared layout.

@param ― entries the bindings, as tgpu.bindGroupLayout takes them

@returns ― a layout whose bind makes a part from resources

layout
({
picture: {
readonly texture: d.WgslTexture2d<d.F32>;
}
picture
: {
texture: d.WgslTexture2d<d.F32>
texture
:
import d
d
.
texture2d<d.F32>(sampleType: d.F32): d.WgslTexture2d<d.F32> (+1 overload)
export texture2d
texture2d
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
) },
smooth: {
readonly sampler: "filtering";
}
smooth
: {
sampler: "filtering"
sampler
: 'filtering' },
});
const
const part: bindings.Bound<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
part
=
const backdropBindings: bindings.Layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
backdropBindings
.
Layout<{ readonly picture: { readonly texture: WgslTexture2d<F32>; }; readonly smooth: { readonly sampler: "filtering"; }; }>.bind(resources: bindings.Resources<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>, options?: bindings.BindOptions): bindings.Bound<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>

Binds one set of resources, using the same inputs as root.createBindGroup.

bind
({
picture: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{
size: readonly number[];
format: GPUTextureFormat;
dimension?: "2d" | undefined;
sampleCount?: 1 | undefined;
}>) | TgpuTextureView<d.WgslTexture<WgslTextureProps>>
picture
:
const image: TgpuTexture<{
size: [number, number];
format: "rgba8unorm";
}> & SampledFlag
image
,
smooth: TgpuSampler | GPUSampler
smooth
:
const sampler: TgpuFixedSampler
sampler
});
const
const shared: bindings.Shared
shared
=
import bindings
bindings
.
function share(root: TgpuRoot, parts: Record<string, bindings.Part>): bindings.Shared

Combines parts from modules or your own code in one layout. Call it before creating pipelines. Set its group on each pass with pass.setBindGroup(shared.layout, shared.group()), or give it to passes.create as shared, which sets it in every pass it begins. Every pipeline in that pass that reads a part then uses the shared group.

@param ― parts parts from any modules and your own, by key

@returns ― a layout you set on each pass, with the group for the parts' resources

share
(
const root: TgpuRoot
root
, {
backdrop: bindings.Bound<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
backdrop
:
const part: bindings.Bound<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
part
}); // before the pipelines that read it
const
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
}>
scene
=
import passes
passes
.
function create<{
hdr: {
format: "rgba16float";
};
}, {
readonly hdr: typeof passes.color;
}>(root: TgpuRoot, screen: targets.Targets<{
hdr: {
format: "rgba16float";
};
}>, writes: {
readonly hdr: typeof passes.color;
}, options?: passes.TargetOptions<{
hdr: {
format: "rgba16float";
};
}> | undefined): passes.Passes<{
readonly hdr: typeof passes.color;
}> (+1 overload)

Describes the targets and outputs for scene passes. With a surface such as the canvas, writes only each renderer's colour. With a target set, writes colour into the target marked color, depth into the target marked depth, and other outputs into their named targets. Multisampled targets resolve according to resolve. Targets with layers draw one pass per layer, and every target the description draws into needs the same layers. add builds a renderer's drawing. begin starts a pass. pipe supplies fills such as a camera.

@param ― screen the surface, or the targets, which give the formats; each one the description names is drawn into

@param ― writes what fills each target, by its key in screen

@returns ― a description you destroy, which holds the pipelines it builds

create
(
const root: TgpuRoot
root
,
const screen: targets.Targets<{
hdr: {
format: "rgba16float";
};
}>
screen
, {
hdr: typeof passes.color
hdr
:
import passes
passes
.
const color: typeof passes.color

Marks the target that receives each renderer's colour.

color
}, {
Options.shared?: bindings.Shared | undefined

Binds a layout from bindings.share in every pass begin and record start, and fills its parts in every pipeline the description builds. Call bindings.share before passes.create and before any other pipeline that reads its parts. Default none.

shared
});
const
const backdrop: passes.Drawn
backdrop
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
}>
scene
.
Passes<{ readonly hdr: typeof color; }>.add<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
color: d.v4f;
}>(this: passes.Passes<passes.Fed<{
color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}>>, drawing: passes.Drawing<d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>, {
color: d.v4f;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
({
...
import passes
passes
.
const fullScreen: {
Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>;
at: (vertexIndex: number, _instanceIndex: number) => {
position: d.v4f;
uv: d.v2f;
};
}

Provides Vertex and at for a renderer that covers the screen with one triangle at depth 0. Draw it with draw(3). Use { ...passes.fullScreen, surfaceOf, color, draw }.

fullScreen
,
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.surfaceOf?: ((vertex: {
position: d.v4f;
uv: d.v2f;
}) => {
color: d.v4f;
}) | undefined

Computes data at a pixel from the interpolated vertex. position is the pixel position. Required for descriptions that write colour and for depthOf.

surfaceOf
: (
corner: {
position: d.v4f;
uv: d.v2f;
}
corner
:
import d
d
.
type Infer<T> = T extends {
readonly [$repr]: infer TRepr;
} ? TRepr : T
export Infer

Extracts the inferred representation of a resource. For inferring types as seen by the GPU, see

InferGPU

@example type A = Infer // => number type B = Infer<WgslArray> // => number[] type C = Infer<Atomic> // => number

Infer
<typeof
import passes
passes
.
const fullScreen: {
Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>;
at: (vertexIndex: number, _instanceIndex: number) => {
position: d.v4f;
uv: d.v2f;
};
}

Provides Vertex and at for a renderer that covers the screen with one triangle at depth 0. Draw it with draw(3). Use { ...passes.fullScreen, surfaceOf, color, draw }.

fullScreen
.
type Vertex: d.WgslStruct<{
position: d.Vec4f;
uv: d.Vec2f;
}>
Vertex
>) => {
'use gpu';
const
const color: d.v4f
color
=
import std
std
.
textureSample<d.texture2d<d.F32>>(texture: d.texture2d<d.F32>, sampler: d.sampler, coords: d.v2f, offset?: d.v2i): d.v4f (+8 overloads)
export textureSample
textureSample
(
const backdropBindings: bindings.Layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
backdropBindings
.
Layout<{ readonly picture: { readonly texture: WgslTexture2d<F32>; }; readonly smooth: { readonly sampler: "filtering"; }; }>.$: {
readonly picture: d.texture2d<d.F32>;
readonly smooth: d.sampler;
}

Provides shader access to the entries, as a tgpu.bindGroupLayout's $ does.

$
.
picture: d.texture2d<d.F32>
picture
,
const backdropBindings: bindings.Layout<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
backdropBindings
.
Layout<{ readonly picture: { readonly texture: WgslTexture2d<F32>; }; readonly smooth: { readonly sampler: "filtering"; }; }>.$: {
readonly picture: d.texture2d<d.F32>;
readonly smooth: d.sampler;
}

Provides shader access to the entries, as a tgpu.bindGroupLayout's $ does.

$
.
smooth: d.sampler
smooth
,
corner: {
position: d.v4f;
uv: d.v2f;
}
corner
.
uv: d.v2f
uv
,
);
return
const Seen: d.WgslStruct
(props?: {
color: d.v4f;
} | undefined) => {
color: d.v4f;
}
Seen
({
color: d.v4f
color
});
},
Shaders<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.color?: passes.Output<{
color: d.v4f;
}, {
position: d.v4f;
uv: d.v2f;
}> | undefined

Supplies the output for the color target when the description has one.

color
:
import passes
passes
.
const shaded: passes.Output<{
readonly color: d.v4f;
}, unknown>

Writes the surface's color unchanged as a renderer's color output.

shaded
,
Drawing<WgslStruct<{ position: Vec4f; uv: Vec2f; }>, { color: v4f; }>.draw(pass: TgpuRenderCommands): void

Records a draw into the pass, on which the description has set the pipeline it built. That pipeline binds indices if supplied. drawIndexed throws without an index buffer. A group the drawing sets with pass.setBindGroup stays for later drawings in the pass that read its layout, so give such a layout to one drawing.

draw
: (
pass: TgpuRenderCommands
pass
) =>
pass: TgpuRenderCommands
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3),
});
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) =>
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
}>
scene
.
Passes<{ readonly hdr: typeof color; }>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly hdr: typeof passes.color;
}> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const backdrop: passes.Drawn
backdrop
));
const part: bindings.Bound<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>
part
.
Bound<{ readonly picture: { readonly texture: WgslTexture2d<F32>; }; readonly smooth: { readonly sampler: "filtering"; }; }>.replace(resources: Partial<bindings.Resources<{
readonly picture: {
readonly texture: d.WgslTexture2d<d.F32>;
};
readonly smooth: {
readonly sampler: "filtering";
};
}>>): void

Replaces resources without creating pipelines. The next shared group uses the replacements. Throws if a pipeline already binds the resources directly, because that pipeline would keep the old resources.

replace
({
picture?: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{
size: readonly number[];
format: GPUTextureFormat;
dimension?: "2d" | undefined;
sampleCount?: 1 | undefined;
}>) | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | undefined
picture
:
const bigger: TgpuTexture<{
size: [number, number];
format: "rgba8unorm";
}> & SampledFlag
bigger
}); // between frames, keeping the pipeline
  • shared also fills every shared part in the pipelines the description builds, so a drawing needs no inject for them.
  • The share must exist before passes.create, and before any other pipeline that reads its parts. A pipeline built before then holds the part as fixed bindings, and bindings.share throws.
  • A pass you open yourself, outside begin, sets the group with pass.setBindGroup(shared.layout, shared.group()).

begin(frame) starts a pass into every target named by the description. record(frame, drawn) starts a pass with the same options, draws one handle or a list in order, and ends the pass. Create the list at setup. Use begin to choose drawings per frame or set a bind group of your own before drawing.

const
const timing: profiler.Profiler
timing
=
import profiler
profiler
.
function create(root: TgpuRoot, options?: profiler.Options): profiler.Profiler

Times GPU passes with one shared query set and reads results without stalling. Throws unless capacity, samples and staging are integers above 0.

@requires ― timestamp-query optional without it the profiler is inert and its timings stay undefined

@owns ― a query set, 4 buffers: two timestamps per timer, a buffer they resolve into, and staging buffers mapped in turn, as many as staging

@records ― capture after the passes it times; a timer's writes in every frame that records its pass

@returns ― a profiler you create timers on, capture each frame and destroy

create
(
const root: TgpuRoot
root
);
const
const sceneTime: profiler.Timer
sceneTime
=
const timing: profiler.Profiler
timing
.
Profiler.timer(name: string): profiler.Timer

Creates a timer for one pass during setup. Throws when the timer count exceeds capacity.

timer
('scene');
const
const opaque: passes.Drawn[]
opaque
= [
const ground: passes.Drawn
ground
,
const herd: passes.Drawn
herd
];
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
const scene: passes.Passes<Writes>
scene
.
Passes<Writes>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<Writes> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const opaque: passes.Drawn[]
opaque
, {
Timed.timestampWrites?: profiler.TimestampWrites | undefined

Supplies a timer's writes for the passes. Without them, passes run untimed. Default none.

timestampWrites
:
const sceneTime: profiler.Timer
sceneTime
.
Timer.writes(): profiler.TimestampWrites | undefined

Marks the pass for timing in this frame and returns timestamp writes, or undefined without timestamp-query. Only marked passes are read back, because skipped passes keep stale timestamps. Call in every frame that records the pass, as you record it: a timing starts no earlier than the one marked before it. Throws after destroy, even without timestamp support.

writes
() });
const glows: passes.Passes<Writes>
glows
.
Passes<Writes>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<Writes> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const sparks: passes.Drawn
sparks
, {
BeginOptions<Writes>.clear?: boolean | readonly ("hdr" | "depth")[] | undefined

Selects targets to clear. Use true for all, false to preserve all, or a list of target keys to clear. Default true.

clear
: false }); // over what the scene drew
const timing: profiler.Profiler
timing
.
Profiler.capture(frame: frames.Frame): void

Resolves the frame's timestamps and maps them after the submit. Call it after the timed passes. A second call in the same frame records nothing.

capture
(
frame: frames.Frame
frame
);
});
  • Output targets clear to their output’s clear. The colour target uses the description’s clear, which the pass reads at each begin. Depth uses depth.clear, which defaults to 1. Stencil uses stencilClear.
  • clear: false keeps what every target holds, for a later pass such as glows after one that reads the depth. clear: ['hdr'] clears the targets it names and keeps the rest, such as the depth an earlier pass drew.
  • A transient target can’t retain its contents between passes. begin throws if asked to keep it. Set transient: false in its spec to retain contents. Multisampled targets are transient by default.
  • Each pass stores what it drew, storeOp: 'store', except into a transient target, 'discard', which keeps only what it resolves.
  • timestampWrites times the pass with a profiler.
  • A description of targets that resolves into no surface also begins from an encoder in place of the frame.
  • A set below its full resolution gets the viewport of its region.
  • The jitter option moves each vertex where the rasteriser sees it and nowhere else. Outputs read where the vertex is, so motion holds no jitter. Temporal antialiasing sets it.
  • record and composite skip a disabled description; begin does not.
  • initAsync() compiles every pipeline built into the description, and what each drawing added needs, including drawings added while it compiles.

A shadow map in cascades, one per distance, draws the same casters into several layers of one texture, each through its own view. Give targets.create a target with layers, and the description draws a pass into each. cameras.layered holds a view per layer:

import {
const mat4: {
add: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(a: Mat4Arg, b: Mat4Arg, dst?: T | undefined) => T;
aim: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(position: Vec3Arg, target: Vec3Arg, up: Vec3Arg, dst?: T | undefined) => T;
axisRotate: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(m: Mat4Arg, axis: Vec3Arg, angleInRadians: number, dst?: T | undefined) => T;
... 44 more ...;
uniformScaling: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(s: number, dst?: T | undefined) => T;
}

4x4 Matrix functions that default to returning Float32Array

@namespace

mat4
} from 'wgpu-matrix';
import {
import cameras
cameras
,
import passes
passes
,
import targets
targets
} from '@typegpu/kit';
const
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
= {
width: number
width
: 1024,
height: number
height
: 1024,
pixelRatio: number
pixelRatio
: 1 };
const
const maps: targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>
maps
=
import targets
targets
.
function create<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
, {
depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
}
depth
: {
format: "depth16unorm"
format
: 'depth16unorm',
layers: 3
layers
: 3,
sampled: true
sampled
: true },
});
const
const views: cameras.LayeredCamera
views
=
import cameras
cameras
.
function layered(root: TgpuRoot, count: number): cameras.LayeredCamera

Creates a view for each layer of a description drawn into layers, in one uniform array. It keeps no previous views, so cameras.current.$ reads the current view in code compiled with history.previously.

@param ― root the root that owns the uniform

@param ― count the number of layers, the layers of the targets the description draws into

@returns ― views you write and destroy

layered
(
const root: TgpuRoot
root
, 3);
const
const casters: passes.Passes<{
readonly depth: typeof passes.depth;
}>
casters
=
import passes
passes
.
function create<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}, {
readonly depth: typeof passes.depth;
}>(root: TgpuRoot, screen: targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>, writes: {
readonly depth: typeof passes.depth;
}, options?: passes.TargetOptions<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}> | undefined): passes.Passes<{
readonly depth: typeof passes.depth;
}> (+1 overload)

Describes the targets and outputs for scene passes. With a surface such as the canvas, writes only each renderer's colour. With a target set, writes colour into the target marked color, depth into the target marked depth, and other outputs into their named targets. Multisampled targets resolve according to resolve. Targets with layers draw one pass per layer, and every target the description draws into needs the same layers. add builds a renderer's drawing. begin starts a pass. pipe supplies fills such as a camera.

@param ― screen the surface, or the targets, which give the formats; each one the description names is drawn into

@param ― writes what fills each target, by its key in screen

@returns ― a description you destroy, which holds the pipelines it builds

create
(
const root: TgpuRoot
root
,
const maps: targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>
maps
, {
depth: typeof passes.depth
depth
:
import passes
passes
.
const depth: typeof passes.depth

Marks the depth target.

depth
}, {
Options.bias?: {
readonly constant?: number;
readonly slope?: number;
} | undefined

Adds a depth bias to every pipeline, in depth-format steps and per unit of slope, as depthBias and depthBiasSlopeScale. Use for shadow maps to prevent surfaces from shadowing themselves. Default none.

bias
: {
constant?: number | undefined
constant
: 2,
slope?: number | undefined
slope
: 2 } })
.
Passes<{ readonly depth: typeof depth; }>.pipe(fill: Inject): passes.Passes<{
readonly depth: typeof passes.depth;
}>

Adds fill after existing fills and returns a description of the same passes. Piped fills take precedence over a drawing's own. For example, passes.create(…).pipe(view.inject()) uses the camera from view.

pipe
(
const views: cameras.LayeredCamera
views
.
LayeredCamera.inject(): Inject

Fills cameras.current with the view of the layer drawn, read through passes.layer. Pipe it into a description of targets with as many layers; a pipeline of a description drawn into another number of layers throws as it builds. In other pipelines cameras.current.$ is view 0.

inject
());
const
const drawn: passes.Drawn
drawn
=
const casters: passes.Passes<{
readonly depth: typeof passes.depth;
}>
casters
.
Passes<{ readonly depth: typeof depth; }>.add<{
color: v4f;
}, {
position: v4f;
world: v3f;
normal: v3f;
uv: v2f;
uv1: v2f;
row: number;
}>(this: passes.Passes<passes.Fed<{
color: v4f;
}, {
position: v4f;
world: v3f;
normal: v3f;
uv: v2f;
uv1: v2f;
row: number;
}>>, drawing: passes.Compound<{
color: v4f;
}, {
position: v4f;
world: v3f;
normal: v3f;
uv: v2f;
uv1: v2f;
row: number;
}>): passes.Drawn (+1 overload)

Builds a pipeline for drawing that writes every described output and returns its draw methods. If the drawing cannot supply the fields an output needs, type checking fails with that output's name. Use without to leave it out or instead to replace it.

add
(
const herd: instances.Renderer
herd
);
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
// A wider view for each layer
for (let
let k: number
k
= 0;
let k: number
k
< 3;
let k: number
k
++) {
const
const reach: number
reach
= 8 * 4 **
let k: number
k
;
const
const view: Float32Array<ArrayBufferLike>
view
=
const mat4: {
add: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(a: Mat4Arg, b: Mat4Arg, dst?: T | undefined) => T;
aim: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(position: Vec3Arg, target: Vec3Arg, up: Vec3Arg, dst?: T | undefined) => T;
axisRotate: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(m: Mat4Arg, axis: Vec3Arg, angleInRadians: number, dst?: T | undefined) => T;
... 44 more ...;
uniformScaling: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(s: number, dst?: T | undefined) => T;
}

4x4 Matrix functions that default to returning Float32Array

@namespace

mat4
.
lookAt: <Float32Array<ArrayBufferLike>>(eye: Vec3Arg, target: Vec3Arg, up: Vec3Arg, dst?: Float32Array<ArrayBufferLike> | undefined) => Float32Array<ArrayBufferLike>
lookAt
([20, 40, 20], [0, 0, 0], [0, 1, 0]);
const views: cameras.LayeredCamera
views
.
LayeredCamera.write(layer: number, view: Mat4Arg, projection: Mat4Arg): void

Writes the view of layer from a view matrix and a projection matrix, as a custom camera's write does. Writes nothing when the layer's view is unchanged. Throws for a view that mirrors the world and for a layer out of range.

write
(
let k: number
k
,
const view: Float32Array<ArrayBufferLike>
view
,
const mat4: {
add: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(a: Mat4Arg, b: Mat4Arg, dst?: T | undefined) => T;
aim: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(position: Vec3Arg, target: Vec3Arg, up: Vec3Arg, dst?: T | undefined) => T;
axisRotate: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(m: Mat4Arg, axis: Vec3Arg, angleInRadians: number, dst?: T | undefined) => T;
... 44 more ...;
uniformScaling: <T extends Mat4Arg = Float32Array<ArrayBufferLike>>(s: number, dst?: T | undefined) => T;
}

4x4 Matrix functions that default to returning Float32Array

@namespace

mat4
.
ortho: <BaseArgType>(left: number, right: number, bottom: number, top: number, near: number, far: number, dst?: BaseArgType | undefined) => BaseArgType
ortho
(-
const reach: number
reach
,
const reach: number
reach
, -
const reach: number
reach
,
const reach: number
reach
, 0, 200));
}
const casters: passes.Passes<{
readonly depth: typeof passes.depth;
}>
casters
.
Passes<{ readonly depth: typeof depth; }>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly depth: typeof passes.depth;
}> | undefined): void

Begins a pass, draws drawn or each drawing in a list in order, then ends the pass. Reuse the list to avoid allocating each frame. Call begin yourself when you need to choose drawings per frame. Records nothing while enabled is false.

record
(
frame: frames.Frame
frame
,
const drawn: passes.Drawn
drawn
); // a pass into each layer
});
  • The description builds each pipeline once, for all layers. Each pass sets a uniform holding its layer, which shaders read as passes.layer.$. cameras.layered reads it to give cameras.current.$ the layer’s view. Data of your own per layer can be indexed by it too.
  • record draws a pass into each layer, in order, with the same options. record(frame, drawn, { layer }) draws into one. begin(frame, { layer }) begins one and throws without a layer when there are several.
  • With timestampWrites, the first layer’s pass writes the start and the last layer’s pass writes the end.
  • The description draws as many layers as its targets have, and casters.layers reports the count. Every target it draws into needs the same layers, or passes.create throws naming each target and its count. Translucency targets and resolves aren’t drawn into layers.
  • A render bundle can’t draw into a description of 2 or more layers, and draw throws for one. Record the drawing into the passes that record or begin opens.
  • Drawings of one pipeline, particles, trails and text draw the same way into each layer, through the layer’s view. An instances renderer with cull: true keeps a visible list per layer and culls every layer in one pair of dispatches. Impostors and poses draw through an instances renderer.
  • A kernel built from a layered description’s inject() runs outside its passes, so it fills passes.layer itself, as the instances culling does from each invocation’s y.
  • The layer takes 1 uniform and one of WebGPU’s 4 bind groups in each pipeline that reads passes.layer. With cameras.layered, a caster binds 2 uniforms: the views and the layer.
  • A drawing’s surface reads its vertex’s fields and the pixel’s position, not WebGPU’s other fragment inputs, such as frontFacing.
  • Each output’s varyings go between the stages as <target>_<field>, and a vertex field of that name throws. They count towards WebGPU’s 16 inter-stage variables, with the vertex’s own fields.
  • An output with previous: true runs the renderer’s at twice per vertex, and binds last frame’s uniforms beside this frame’s.
  • Translucent layers that overlap in depth average their colours by weight, so a layer close behind another shows through more than it would in order. The weight suits distances from the eye of about 0.1 to 500.
  • A translucent drawing’s motion is that of the layer drawn last where it shows, so TAA can smear what lies behind it. Leave it out of motion with without('motion') to keep the motion beneath it.
  • Particles, trails and text drawings set a blend and draw over in order. A drawing of your own made from one, without its blend and with translucent: true, draws in any order when its colour is premultiplied.