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().record→encoder
pipe().composite→encoder
beneath().record→encoder
beneath().composite→encoder
add().draw→render
without().record→encoder
without().composite→encoder
instead().record→encoder
instead().composite→encoder
record→encoder
composite→encoder
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.
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.
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
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(
constroot:TgpuRoot
root,
constscreen: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:typeofpasses.color
hdr:
import passes
passes.
constcolor:typeofpasses.color
Marks the target that receives each renderer's colour.
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(
constview: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
constCorner: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.
@param ― props Record with string keys and TgpuData values,
each entry describing one struct member.
struct({
position:d.Vec4f
position:
import d
d.
constvec4f:d.Vec4f
vec4f,
world:d.Vec3f
world:
import d
d.
constvec3f:d.Vec3f
vec3f});
const
constSeen: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.
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.
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.
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
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,
consttriangles: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:
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
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(
constroot:TgpuRoot
root,
constfont: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.
constscreen:(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
constpaint:passes.Passes<{
readonly ink:typeofpasses.color;
}>
paint=
import passes
passes.
functioncreate<{
readonly ink:{
readonly format:"rgba8unorm";
readonly sampled:true;
};
},{
readonly ink:typeofpasses.color;
}>(root:TgpuRoot,screen:targets.Targets<{
readonly ink:{
readonly format:"rgba8unorm";
readonly sampled:true;
};
}>,writes:{
readonly ink:typeofpasses.color;
},options?:passes.TargetOptions<{
readonly ink:{
readonly format:"rgba8unorm";
readonly sampled:true;
};
}>|undefined):passes.Passes<{
readonly ink:typeofpasses.color;
}>(+1overload)
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(
constroot:TgpuRoot
root,
constpage:targets.Targets<{
readonly ink:{
readonly format:"rgba8unorm";
readonly sampled:true;
};
}>
page,{
ink:typeofpasses.color
ink:
import passes
passes.
constcolor:typeofpasses.color
Marks the target that receives each renderer's colour.
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(
consttags: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);
consttags: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.
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.
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(
constframe:Frame
frame,
constdrawn:passes.Drawn
drawn);
// Sample it from another shader, such as a floor's
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`
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.
constvec4f: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
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.
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
constoutlined:passes.Compound<Seen,{
position:d.v4f;
}>
outlined:
import passes
passes.
interfaceCompound<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<
typeSeen={
readonly color:d.v4f;
}
Seen,
import d
d.
typeInfer<T>=Textends{
readonly[$repr]:inferTRepr;
}?TRepr:T
export Infer
Extracts the inferred representation of a resource.
For inferring types as seen by the GPU, see
InferGPU
@exampletype A = Infer // => number
type B = Infer<WgslArray> // => number[]
type C = Infer<Atomic> // => number
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(
constfill:passes.Drawing<d.WgslStruct<{
position:d.Vec4f;
}>,Seen>
fill);
const
constrimming: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.
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(
constoutlined: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
constClips: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.
@param ― props Record with string keys and TgpuData values,
each entry describing one struct member.
struct({
now:d.Vec4f
now:
import d
d.
constvec4f:d.Vec4f
vec4f,
before:d.Vec4f
before:
import d
d.
constvec4f:d.Vec4f
vec4f});
const
constmotion:passes.Output<unknown,{
position:d.v4f;
}>
motion=
import passes
passes.
functionoutput<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;
readonlywrite:(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.
constvec2f:d.Vec2f
vec2f,{
varyings?:d.WgslStruct<{
now:d.Vec4f;
before:d.Vec4f;
}>|undefined
varyings:
constClips: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
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.
constu32: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.
@exampleconst value = u32(); // 0
@exampleconst value = u32(7); // 7
@exampleconst value = u32(3.14); // 3
@exampleconst value = u32(-1); // 4294967295
@exampleconst 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:
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.
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:
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
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(
constroot:TgpuRoot
root,
constscreen: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:typeofpasses.color
hdr:
import passes
passes.
constcolor:typeofpasses.color
Marks the target that receives each renderer's colour.
color,
accum:passes.Output<unknown,{
readonly position:d.v4f;
}>
accum:
import passes
passes.
constaccumulation: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.
constrevealage: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.
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(
constview: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
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.
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.
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.
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.
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. */
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
constview:{
size:d.v2f;
pixelRatio:number;
}
view=
import passes
passes.
constpixels: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.
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)/
constview:{
size:d.v2f;
pixelRatio:number;
}
view.
size:d.v2f
Holds the width and height of the drawn region in pixels.
size)*
constclip:d.v4f
clip.
v4f.w: number
w,
constclip: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:
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)
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.
constfullScreen:{
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 }.
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.
typeInfer<T>=Textends{
readonly[$repr]:inferTRepr;
}?TRepr:T
export Infer
Extracts the inferred representation of a resource.
For inferring types as seen by the GPU, see
InferGPU
@exampletype A = Infer // => number
type B = Infer<WgslArray> // => number[]
type C = Infer<Atomic> // => number
Infer<typeof
import passes
passes.
constfullScreen:{
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 }.
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.
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
constbackdropBindings:bindings.Layout<{
readonly picture:{
readonly texture:d.WgslTexture2d<d.F32>;
};
readonly smooth:{
readonly sampler:"filtering";
};
}>
backdropBindings=
import bindings
bindings.
functionlayout<{
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
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(
constroot:TgpuRoot
root,{
backdrop:bindings.Bound<{
readonly picture:{
readonly texture:d.WgslTexture2d<d.F32>;
};
readonly smooth:{
readonly sampler:"filtering";
};
}>
backdrop:
constpart:bindings.Bound<{
readonly picture:{
readonly texture:d.WgslTexture2d<d.F32>;
};
readonly smooth:{
readonly sampler:"filtering";
};
}>
part});// before the pipelines that read it
const
constscene:passes.Passes<{
readonly hdr:typeofpasses.color;
}>
scene=
import passes
passes.
functioncreate<{
hdr:{
format:"rgba16float";
};
},{
readonly hdr:typeofpasses.color;
}>(root:TgpuRoot,screen:targets.Targets<{
hdr:{
format:"rgba16float";
};
}>,writes:{
readonly hdr:typeofpasses.color;
},options?:passes.TargetOptions<{
hdr:{
format:"rgba16float";
};
}>|undefined):passes.Passes<{
readonly hdr:typeofpasses.color;
}>(+1overload)
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(
constroot:TgpuRoot
root,
constscreen:targets.Targets<{
hdr:{
format:"rgba16float";
};
}>
screen,{
hdr:typeofpasses.color
hdr:
import passes
passes.
constcolor:typeofpasses.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.
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.
constfullScreen:{
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 }.
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.
typeInfer<T>=Textends{
readonly[$repr]:inferTRepr;
}?TRepr:T
export Infer
Extracts the inferred representation of a resource.
For inferring types as seen by the GPU, see
InferGPU
@exampletype A = Infer // => number
type B = Infer<WgslArray> // => number[]
type C = Infer<Atomic> // => number
Infer<typeof
import passes
passes.
constfullScreen:{
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 }.
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.
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.
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.
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.
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.
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.
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.
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
consttiming: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.
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:
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
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(
constroot:TgpuRoot
root,3);
const
constcasters:passes.Passes<{
readonly depth:typeofpasses.depth;
}>
casters=
import passes
passes
.
functioncreate<{
readonly depth:{
readonly format:"depth16unorm";
readonly layers:3;
readonly sampled:true;
};
},{
readonly depth:typeofpasses.depth;
}>(root:TgpuRoot,screen:targets.Targets<{
readonly depth:{
readonly format:"depth16unorm";
readonly layers:3;
readonly sampled:true;
};
}>,writes:{
readonly depth:typeofpasses.depth;
},options?:passes.TargetOptions<{
readonly depth:{
readonly format:"depth16unorm";
readonly layers:3;
readonly sampled:true;
};
}>|undefined):passes.Passes<{
readonly depth:typeofpasses.depth;
}>(+1overload)
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(
constroot:TgpuRoot
root,
constmaps:targets.Targets<{
readonly depth:{
readonly format:"depth16unorm";
readonly layers:3;
readonly sampled:true;
};
}>
maps,{
depth:typeofpasses.depth
depth:
import passes
passes.
constdepth:typeofpasses.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.
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(
constviews: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
constdrawn:passes.Drawn
drawn=
constcasters:passes.Passes<{
readonly depth:typeofpasses.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(+1overload)
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.
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.
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,
constdrawn: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.