Skip to content

@typegpu/kitinstances

Instances

Draw lit copies of mesh-pool meshes with one row per instance and one draw per mesh.

kit.instances

module

instances.create(root, pool, { kind?, capacity, history, … }) → HistoryInstances

instances.create(root, pool, { kind?, capacity, … }) → Instances

instances.define(name, options?) → Kind

rootborrows
the root
poolneeds
the mesh pool whose meshes it draws
kind?takes
a kind from instances.define
HistoryInstancesreturns
a set of instances you flush every frame and destroy
Instancesreturns
a set of instances you flush every frame and destroy
nametakes
a label for ids and WGSL
Kindreturns
a kind to give instances.create as kind
GPU functions
rotatefacing
schemas
PlacementSphereShadedCornerLit
helpers
Instance
types
MovedInstanceOfVertexKindAnyKindIdValuesFieldsRendererOptionsRendererInstancesHistoryInstances
Optionscreate · 4 fields
kind?

K= a plain kind with a transform and material

Selects a kind from instances.define.

capacity

number

Limits the number of rows.

defaults?

Values<K>= none: the identity transform, the mesh's material and zero for custom fields

Sets values for fields that add omits.

history?

boolean= false

Keeps last frame's rows, as a table's history does, so motion follows every instance that moves, whether the CPU or a kernel moves it.

KindOptionsdefine · 13 fields
host?

H & Base= none

Adds fields written on the CPU, as in table.define.

device?

D & Base= none

Adds fields written by GPU kernels.

transform?

M= 'host'

Stores position, rotation and scale in device fields when set to 'device', so kernels can write them.

place?

(instance: InstanceOf<H, D, M>) => Placement= the instance position, rotation and scale

Returns the instance transform from custom data, such as a simulation buffer.

visible?

(instance: InstanceOf<H, D, M>) => boolean= always

Controls visibility in every renderer and pass, including shadows, without removing the instance.

pose?

(instance: InstanceOf<H, D, M>) => number= none, which uses the bind pose

Selects the pose that moves the vertices by their joints.

deform?

(vertex: Vertex, instance: InstanceOf<H, D, M>) => d.v3f= none, which uses the mesh or posed position

Moves a vertex in object space before the instance transform.

deformShadow?

boolean= true

Controls whether the shadow pass applies deform.

bounds?

(instance: InstanceOf<H, D, M>, base: Sphere) => Sphere= base

Returns the world-space sphere for culling.

carry?

(vertexIndex: number, instance: InstanceOf<H, D, M>) => d.v4f= none, which omits four floats per vertex and sets carried to zero

Returns four values to interpolate between vertices and pass to material or surface as carried.

material?

( point: Point, instance: InstanceOf<H, D, M>, base: Material, carried: d.v4f, ) => Material= base

Returns the material at a point.

surface?

( point: Point, instance: InstanceOf<H, D, M>, base: Material, carried: d.v4f, ) => Shaded= none, which uses the mesh surface

Replaces the mesh surface at each pixel, as an impostor does.

coverage?

( point: Point, instance: InstanceOf<H, D, M>, base: Material, carried: d.v4f, ) => number= none: the instance covers every pixel it rasterises, and opaque renderers keep early depth testing

Returns how much of the pixel the instance covers, from 0 to 1, to cut holes in its shape, such as lace, or leaves on a card.

records
  • flushencoder
  • renderer().cullcompute

What each description built of a renderer, in its pass; flush() once a frame, before them, uploads what changed; a culling renderer's cull in a compute pass after the flush.

owns

a table ·2 buffers ·culling buffers ·culling pipelines ·bind groups

The rows, the live ones per mesh and, once a render bundle draws them, their draws; with culling, a uniform of how many rows it lists from; without indirect-first-instance, a uniform and a bind group per mesh with instances; and a culling renderer's 3 buffers and 2 kernels for each description it is added to, which own its pipelines, colour, with a depth pipeline before it for a kind with a surface, or depth alone.

lifecycle

destroy()[Symbol.dispose]

injects
  • definition

    Its kind's table, which your kernels read and write.

binds
  • 1 storage

    A field of its kind's table, per half, as a table's getters bind.

  • 1 uniform

    The mesh of an indirect draw, without indirect-first-instance.

  • 1 storage

    A renderer's vertex stage, the live rows per mesh or a culling renderer's visible rows.

  • 2 storage · 1 uniform

    A culling renderer's marking kernel, where place, visible and bounds run: the listing, its scratch and the listing's length.

needs
  • cameras

    As renderer(options.eye); fills a hook in its pipelines.

  • lighting

    As renderer(options.light); fills a hook and accessors in its pipelines.

  • meshPool

    As pool; fills accessors in its pipelines.

requires
  • indirect-first-instanceoption

    cull: true, and a render bundle, draw indirectly; without it, each indirect draw binds a group holding its mesh, or draws through a pipeline per mesh where the pipeline has no group left. A renderer drawn into a pass without cull draws directly and needs none.

Change the count to add boxes and spheres without increasing the two draws. Positions update every frame, while live lists update only after the count changes.

Drawing each object separately spends CPU time on JavaScript calls, especially on phones. Store a transform and material per object in a set of instances: a table whose rows are meshes from a mesh pool. Its renderer lights and draws the live rows with one draw per mesh. Adding instances increases data without increasing draws.

import {
import instances
instances
,
import lighting
lighting
,
import materials
materials
} from '@typegpu/kit';
const
const root: TgpuRoot
root
= await
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
.
init: (options?: InitOptions) => Promise<TgpuRoot>

Requests a new GPU device and creates a root around it. If a specific device should be used instead, use

@see ― initFromDevice. *

@example

When given no options, the function will ask the browser for a suitable GPU device.

const root = await tgpu.init();

@example

If there are specific options that should be used when requesting a device, you can pass those in.

const adapterOptions: GPURequestAdapterOptions = ...;
const deviceDescriptor: GPUDeviceDescriptor = ...;
const root = await tgpu.init({ adapter: adapterOptions, device: deviceDescriptor });

init
();
const
const light: lighting.Lighting
light
=
import lighting
lighting
.
function create<{
readonly settings: {
readonly sunDirection: [0.4, 1, 0.3];
};
}>(root: TgpuRoot, options?: ({
readonly settings: {
readonly sunDirection: [0.4, 1, 0.3];
};
} & lighting.Options & {
readonly settings: {
readonly sunDirection: [0.4, 1, 0.3];
};
}) | undefined): lighting.Lighting

Creates lighting with a sun, sky and fog. It can also read point lights from a table or a function and cast shadows. Pipe its injection into each pipeline that uses it. Throws if points names no source or more than one, a light function has neither count nor candidates, a table comes with count, or candidates.ranges is anything other than a positive integer.

@injects ― hook the shading hooks its options name: reflect, ambient, fog, sunShadow and attenuation

@injects ― definition the sun, sky and fog, the shadows and the point lights, which shading reads

@binds ― 1 uniform: shading.shade, the sun, sky and fog

@binds ― 2 storage, 1 uniform: shading.shade with a table of point lights

@binds ― 3 storage, 1 uniform: shading.shade with a table of lights whose positions are on the device, the table's two parts

@binds ― 1 uniform: shading.shade with points.light or points.spot, plus what the function binds

@binds ― 0 storage: shading.shade with points.candidates, plus what their functions bind, 2 storage for a neighbour grid's range and slot

@binds ― 1 uniform: shading.shade with a shadow, the sun's light space and cascades, beside the depth array and its comparison sampler

@binds ― 1 uniform: shading.shade with pointShadow, each shadow's light, layers and views, beside their depth array and the comparison sampler

@owns ― 1 to 3 buffers, a sampler, targets, a cameras.layered, passes: the sun, sky and fog; with a shadow, its light space, the views of its cascades, a comparison sampler, the depth array and the passes that draw it; with pointShadow, the same for the lights' faces

@records ― shadow.record and pointShadow.record with what was added to them, before the passes that shade

@param ― options.shadow the sun's shadow, with a depth pass per cascade

@param ― options.pointShadow shadows that cast gives to lights of points.table, with a depth pass per face

@param ― options.points point lights from a table or a 'use gpu' function. Every lit point visits each slot up to the table's highest live one, or count with a function, unless candidates names the slots that may reach it

@returns ― lighting you destroy

create
(
const root: TgpuRoot
root
, {
settings: {
readonly sunDirection: [0.4, 1, 0.3];
} & ((Partial<d.InferInput<d.WgslStruct<{
sunDirection: d.Vec3f;
sunIntensity: d.F32;
sunColor: d.Vec3f;
skyIntensity: d.F32;
skyTop: d.Vec3f;
fogDensity: d.F32;
skyBottom: d.Vec3f;
fogFalloff: d.F32;
fogColor: d.Vec3f;
skyReflection: d.F32;
fogStart: d.F32;
}>>> | undefined) & {
readonly sunDirection: [0.4, 1, 0.3];
})

Sets initial sun, sky and fog values over defaults. Default defaults, which has no fog.

settings
: {
sunDirection: [0.4, 1, 0.3]
sunDirection
: [0.4, 1, 0.3] } });
const
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
=
import passes
passes
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
};
readonly depth: {
readonly format: "depth24plus";
};
}, {
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>(root: TgpuRoot, screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
};
readonly depth: {
readonly format: "depth24plus";
};
}>, writes: {
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}, options?: passes.TargetOptions<{
readonly hdr: {
readonly format: "rgba16float";
};
readonly depth: {
readonly format: "depth24plus";
};
}> | 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 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
,
depth: typeof passes.depth
depth
:
import passes
passes
.
const depth: typeof passes.depth

Marks the depth target.

depth
})
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.pipe(fill: Inject): passes.Passes<{
readonly hdr: typeof passes.color;
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
())
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.beneath(fill: Inject): passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>

Adds fill after the fills given to earlier beneath calls and returns a description of the same passes. A drawing's own fills take precedence over these, and piped fills over both, so beneath supplies defaults such as a lighting. A compound drawing that passes its own from to pipeline gets them by starting from with inject().

beneath
(
const light: lighting.Lighting
light
.
Lighting.inject(): Inject

Fills the shading hooks and resources for pipelines created from the configuration you pipe it into.

inject
());
const
const things: instances.Instances<Plain>
things
=
import instances
instances
.
function create<Plain>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<Plain>): instances.Instances<Plain> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 256 });
const
const drawn: passes.Drawn
drawn
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.add<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.v2f;
row: number;
}>(this: passes.Passes<passes.Fed<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.v2f;
row: number;
}>>, drawing: passes.Compound<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.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 things: instances.Instances<Plain>
things
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
());
const things: instances.Instances<Plain>
things
.
Instances<Plain>.add(mesh: meshPool.Mesh | Pick<meshPool.Model, "meshes">, values?: {
readonly position?: FieldInput<d.Vec3f>;
readonly rotation?: FieldInput<d.Vec4f>;
readonly scale?: number | FieldInput<d.Vec3f>;
readonly color?: FieldInput<d.Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<d.Vec3f>;
readonly opacity?: number;
} | ((mesh: meshPool.Mesh, index: number) => {
readonly position?: FieldInput<d.Vec3f>;
readonly rotation?: FieldInput<d.Vec4f>;
readonly scale?: number | FieldInput<d.Vec3f>;
readonly color?: FieldInput<d.Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<d.Vec3f>;
readonly opacity?: number;
}) | undefined): IdOf<...>

Adds an instance of a mesh, model or group of meshes from the pool. Each mesh uses a row, and all rows move and change together under one id. values may be a function of each mesh, to give a model's meshes values of their own. Throws if a mesh belongs to another pool, the group is empty, a posed kind receives a mesh without joints or the set is full.

add
(
const box: meshPool.Mesh
box
, {
position?: d.InferInput<d.Vec3f> | ArrayLike<number> | undefined
position
: [0, 0.5, 0], ...
import materials
materials
.
const glossy: (color: d.v3f, roughness: number) => {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}

Creates a dielectric with specular highlights, such as paint, plastic or wet stone.

glossy
(
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(0.62, 0.24, 0.16), 0.4) });
const
const moon: IdOf<Plain>
moon
=
const things: instances.Instances<Plain>
things
.
Instances<Plain>.add(mesh: meshPool.Mesh | Pick<meshPool.Model, "meshes">, values?: {
readonly position?: FieldInput<d.Vec3f>;
readonly rotation?: FieldInput<d.Vec4f>;
readonly scale?: number | FieldInput<d.Vec3f>;
readonly color?: FieldInput<d.Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<d.Vec3f>;
readonly opacity?: number;
} | ((mesh: meshPool.Mesh, index: number) => {
readonly position?: FieldInput<d.Vec3f>;
readonly rotation?: FieldInput<d.Vec4f>;
readonly scale?: number | FieldInput<d.Vec3f>;
readonly color?: FieldInput<d.Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<d.Vec3f>;
readonly opacity?: number;
}) | undefined): IdOf<...>

Adds an instance of a mesh, model or group of meshes from the pool. Each mesh uses a row, and all rows move and change together under one id. values may be a function of each mesh, to give a model's meshes values of their own. Throws if a mesh belongs to another pool, the group is empty, a posed kind receives a mesh without joints or the set is full.

add
(
const ball: meshPool.Mesh
ball
, {
scale?: number | d.InferInput<d.Vec3f> | ArrayLike<number> | undefined

Sets one scale factor for all axes or a separate factor per axis.

scale
: 0.5, ...
import materials
materials
.
const glow: (color: d.v3f, strength: number) => {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}

Creates an emissive material that gives off strength times color and reflects almost nothing.

glow
(
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(1, 0.85, 0.6), 2) });
const
const orbit: HostField<d.Vec3f, "Instance">
orbit
=
const things: instances.Instances<Plain>
things
.
Instances<Plain>.fields: instances.Fields<Plain>

Provides one handle per field, which writes without allocating. Keep a handle outside a loop instead of reading fields.x inside it.

fields
.
position: HostField<d.Vec3f, "Instance">
position
;
const
const loop: frames.Frames
loop
=
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 orbit: HostField<d.Vec3f, "Instance">
orbit
.
function set(id: RowId<"Instance">, x: number, y: number, z: number): void
set
(
const moon: IdOf<Plain>
moon
, 2 *
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.cos(x: number): number

Returns the cosine of a number.

@param ― x A numeric expression that contains an angle measured in radians.

cos
(
frame: frames.Frame
frame
.
Frame.time: number

Reports seconds since the first submitted frame.

time
), 1.5, 2 *
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.sin(x: number): number

Returns the sine of a number.

@param ― x A numeric expression that contains an angle measured in radians.

sin
(
frame: frames.Frame
frame
.
Frame.time: number

Reports seconds since the first submitted frame.

time
));
const things: instances.Instances<Plain>
things
.
Instances<Plain>.flush(encoder?: TgpuCommandEncoder): void

Uploads changed rows. When instances are added or removed, it also uploads live rows per mesh and updates draw counts. Call this once per frame before drawing. HistoryInstances take the frame's encoder and throw without it.

flush
();
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.record(frame: frames.Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly hdr: typeof passes.color;
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
);
});
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
(
const loop: frames.Frames
loop
);

things.renderer() returns a drawing, lit by the lighting its pass description gives through beneath. scene.add builds pipelines for its pass description and returns the draw commands. Each mesh uses a direct draw. Meshes with matching side, mask and texture settings share a pipeline. This needs no optional device feature. A finished look for model scenes draws one set of glTF models with shadows, ambient occlusion, TAA and bloom.

things.add(mesh, values) returns an id. Every value is optional:

Field Default
position the origin world space
rotation none a unit quaternion, [x, y, z, w]
scale 1 one factor, or one per axis
color the mesh’s linear
roughness, metallic the mesh’s
emission the mesh’s linear
opacity the mesh’s alpha under a blend or clear renderer
import {
const quat: {
create: (x?: number, y?: number, z?: number, w?: number) => Float32Array<ArrayBufferLike>;
fromValues: (x?: number, y?: number, z?: number, w?: number) => Float32Array<ArrayBufferLike>;
set: <T extends QuatArg = Float32Array<ArrayBufferLike>>(x: number, y: number, z: number, w: number, dst?: T | undefined) => T;
fromAxisAngle: <T extends QuatArg = Float32Array<ArrayBufferLike>>(axis: Vec3Arg, angleInRadians: number, dst?: T | undefined) => T;
toAxisAngle: <T extends Vec3Arg = Float32Array<ArrayBufferLike>>(q: QuatArg, dst?: T | undefined) => {
angle: number;
axis: T;
};
... 30 more ...;
sqlerp: <T extends QuatArg = Float32Array<ArrayBufferLike>>(a: QuatArg, b: QuatArg, c: QuatArg, d: QuatArg, t: number, dst?: T | undefined) => T;
}

Quaternion functions that default to returning Float32Array

@namespace

quat
} from 'wgpu-matrix';
const
const crate: IdOf<Plain>
crate
=
const things: instances.Instances<Plain>
things
.
Instances<Plain>.add(mesh: meshPool.Mesh | Pick<meshPool.Model, "meshes">, values?: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
} | ((mesh: meshPool.Mesh, index: number) => {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
}) | undefined): IdOf<...>

Adds an instance of a mesh, model or group of meshes from the pool. Each mesh uses a row, and all rows move and change together under one id. values may be a function of each mesh, to give a model's meshes values of their own. Throws if a mesh belongs to another pool, the group is empty, a posed kind receives a mesh without joints or the set is full.

add
(
const box: meshPool.Mesh
box
, {
position?: ArrayLike<number> | InferInput<Vec3f> | undefined
position
: [3, 0.5, 0],
color?: ArrayLike<number> | InferInput<Vec3f> | undefined
color
: [0.4, 0.3, 0.2] });
const things: instances.Instances<Plain>
things
.
Instances<Plain>.write(id: IdOf<Plain>, values: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
}): void

Writes the supplied fields and keeps the rest. At the next flush, device fields written here overwrite kernel writes.

write
(
const crate: IdOf<Plain>
crate
, {
rotation?: ArrayLike<number> | InferInput<Vec4f> | undefined

Sets rotation as a unit quaternion [x, y, z, w].

rotation
:
const quat: {
create: (x?: number, y?: number, z?: number, w?: number) => Float32Array<ArrayBufferLike>;
fromValues: (x?: number, y?: number, z?: number, w?: number) => Float32Array<ArrayBufferLike>;
set: <T extends QuatArg = Float32Array<ArrayBufferLike>>(x: number, y: number, z: number, w: number, dst?: T | undefined) => T;
fromAxisAngle: <T extends QuatArg = Float32Array<ArrayBufferLike>>(axis: Vec3Arg, angleInRadians: number, dst?: T | undefined) => T;
toAxisAngle: <T extends Vec3Arg = Float32Array<ArrayBufferLike>>(q: QuatArg, dst?: T | undefined) => {
angle: number;
axis: T;
};
... 30 more ...;
sqlerp: <T extends QuatArg = Float32Array<ArrayBufferLike>>(a: QuatArg, b: QuatArg, c: QuatArg, d: QuatArg, t: number, dst?: T | undefined) => T;
}

Quaternion functions that default to returning Float32Array

@namespace

quat
.
fromAxisAngle: <ArrayLike<number> | InferInput<Vec4f>>(axis: Vec3Arg, angleInRadians: number, dst?: ArrayLike<number> | InferInput<Vec4f> | undefined) => ArrayLike<number> | InferInput<Vec4f>
fromAxisAngle
([0, 1, 0],
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.PI: number

Pi. This is the ratio of the circumference of a circle to its diameter.

PI
/ 4) });
const things: instances.Instances<Plain>
things
.
Instances<Plain>.write(id: IdOf<Plain>, values: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
}): void

Writes the supplied fields and keeps the rest. At the next flush, device fields written here overwrite kernel writes.

write
(
const crate: IdOf<Plain>
crate
, {
emission?: ArrayLike<number> | InferInput<Vec3f> | undefined
emission
: [2, 0.4, 0] });
const things: instances.Instances<Plain>
things
.
function remove(id: RowId<"Instance">): void

Frees the row slot and makes its id stale.

remove
(
const crate: IdOf<Plain>
crate
);
  • A row starts with its mesh’s material. Shapes default to white chalk. Models use the file’s factors, multiplied by textures. Supplied values and the set’s defaults replace factors. To tint relative to the file, start with mesh.material.
  • Spread a materials preset into the values, for example { position, ...materials.glossy(color, 0.3), opacity: 0.2 }.
  • write changes only supplied fields. undefined leaves a field unchanged. write and remove take effect at the next flush. Removal invalidates the id, and has(id) checks whether it is live.
  • In shaders, instances.rotate(q, v) rotates v by a unit quaternion. instances.facing(direction) turns +z toward direction with +y up. facing also runs on the CPU.

The set is a table of its kind, and everything a table offers works on it. Field handles write without allocating, live() spreads into a picker, neighbour grid or live lists, and idAt names the instance at a slot the GPU found:

const
const crates: instances.Instances<Plain>
crates
=
import instances
instances
.
function create<Plain>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<Plain>): instances.Instances<Plain> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 1024,
Options<Plain>.defaults?: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
} | undefined

Sets values for fields that add omits. They replace the mesh's material factors. Default none: the identity transform, the mesh's material and zero for custom fields.

defaults
: {
roughness?: number | undefined
roughness
: 0.8 } });
const
const crate: IdOf<Plain>
crate
=
const crates: instances.Instances<Plain>
crates
.
Instances<Plain>.add(mesh: meshPool.Mesh | Pick<meshPool.Model, "meshes">, values?: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
} | ((mesh: meshPool.Mesh, index: number) => {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
}) | undefined): IdOf<...>

Adds an instance of a mesh, model or group of meshes from the pool. Each mesh uses a row, and all rows move and change together under one id. values may be a function of each mesh, to give a model's meshes values of their own. Throws if a mesh belongs to another pool, the group is empty, a posed kind receives a mesh without joints or the set is full.

add
(
const box: meshPool.Mesh
box
);
const
const spin: HostField<Vec4f, "Instance">
spin
=
const crates: instances.Instances<Plain>
crates
.
Instances<Plain>.fields: instances.Fields<Plain>

Provides one handle per field, which writes without allocating. Keep a handle outside a loop instead of reading fields.x inside it.

fields
.
rotation: HostField<Vec4f, "Instance">
rotation
; // keep the handle outside the loop
const spin: HostField<Vec4f, "Instance">
spin
.
function set(id: RowId<"Instance">, x: number, y: number, z: number, w: number): void
set
(
const crate: IdOf<Plain>
crate
, 0,
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.SQRT1_2: number

The square root of 0.5, or, equivalently, one divided by the square root of 2.

SQRT1_2
, 0,
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.SQRT1_2: number

The square root of 0.5, or, equivalently, one divided by the square root of 2.

SQRT1_2
);
const
const hits: picker.Picker
hits
=
import picker
picker
.
function create(root: TgpuRoot, camera: cameras.CameraBase, options: picker.Options): picker.Picker

Finds a candidate under a screen point on the GPU. Projects every candidate with the camera and keeps the one within reach with the best rank. Throws unless capacity is an integer from 1 to 2^24.

@injects ― per-instance found, for shaders that act on the pick in the same frame

@binds ― 1 storage: found, the pick's key

@owns ― 3 buffers, a pipeline, a readback: the pick's key, the pointer and the settings; the readback brings the key to the CPU

@records ― pick once in a frame that picks, in a compute pass after whatever moves the candidates; result.capture(frame) after that pass, which copies what a pick found.

@param ― camera the camera the candidates are drawn with

@param ― options.position where each candidate is; it, radius, alive and rank carry the fills of what they read, such as Star.position.pipe(stars.inject())

@returns ― a picker you destroy

create
(
const root: TgpuRoot
root
,
const view: cameras.OrbitCamera
view
, {
...
const crates: instances.Instances<Plain>
crates
.
function live(): Live

Returns the capacity and live test for live lists, a grid, a picker or state machines. Use liveLists.create(root, { ...coins.live(), draws }).

live
(), // the capacity and the live test
Options.size: SizeSource

Supplies the view size at each pick, such as the canvas surface. pixelRatio scales reach from screen points to pixels. Without it, one point equals one pixel.

size
,
Options.position: (i: number) => v3f

Returns the candidate center in world space.

position
:
import instances
instances
.
const Instance: Plain

The plain kind, with a transform and material, that a set without kind stores. Its getters read a plain set in shaders filled by the set's inject().

Instance
.
position: Getter<Vec3f>
position
.
Getter<Vec3f>.pipe(transform: (cfg: Configurable) => Configurable): Getter<Vec3f>

Applies a configuration transform to the slots and accessors this function reads, as root.pipe does to a pipeline's.

pipe
(
const crates: instances.Instances<Plain>
crates
.
function inject(): Inject

Fills the definition's accessors with this table's buffers.

inject
()),
});
// Once a pick is read back
const
const slot: number | null | undefined
slot
=
const hits: picker.Picker
hits
.
Picker.result: Readback<number | null>

Reads the picked candidate index to the CPU, or null if nothing was found. Capture after the picker pass, then call take() or await next(). Without hz, each pick requests a copy for the next capture.

result
.
Readback<number | null>.take(): number | null | undefined

Returns latest once per completed copy, then undefined until the next copy completes. Each value goes to one caller. Callers sharing a readback split the values between them.

take
();
if (typeof
const slot: number | null | undefined
slot
=== 'number')
const crates: instances.Instances<Plain>
crates
.
Instances<Plain>.write(id: IdOf<Plain>, values: {
readonly position?: FieldInput<Vec3f>;
readonly rotation?: FieldInput<Vec4f>;
readonly scale?: number | FieldInput<Vec3f>;
readonly color?: FieldInput<Vec3f>;
readonly roughness?: number;
readonly metallic?: number;
readonly emission?: FieldInput<Vec3f>;
readonly opacity?: number;
}): void

Writes the supplied fields and keeps the rest. At the next flush, device fields written here overwrite kernel writes.

write
(
const crates: instances.Instances<Plain>
crates
.
Instances<Plain>.idAt(slot: number): IdOf<Plain>

Returns the id of the instance that holds slot, such as a slot a picker found.

idAt
(
const slot: number
slot
), {
emission?: ArrayLike<number> | InferInput<Vec3f> | undefined
emission
: [1, 0.6, 0] });
  • A set without a kind stores instances.Instance rows, whose getters its shaders read.
  • buffers, slotOf(id) and clear() also work as on a table. count counts instances, while capacity and span count rows.
  • things.add(model) adds one row per mesh under one id. write, field handles and remove act on every row of the model. idAt gives the model’s id for any of its slots, and count counts it once. A field handle’s get reads the model’s first mesh.
  • Use things.add({ meshes }) to group any pool meshes, including a character and held items.
  • Pass a function of each mesh to give a model’s meshes values of their own, such as a coat colour per part: things.add(horse, (mesh, i) => ({ color: coats[i] })).
  • defaults sets values for fields add omits, including a kind’s own fields.
  1. Call things.flush() to upload changed rows. When instances are added or removed, it also uploads per-mesh live lists. A set with history is typed HistoryInstances, whose flush takes the frame’s encoder.
  2. Run any kernels that move the set.
  3. Call renderer.cull(pass) in a compute pass for a culling renderer.
  4. For a shadow, call light.shadow.record(frame, [cast]). Create cast = light.shadow.add(renderer) while loading.
  5. Call drawn.draw(pass) in the scene pass or use scene.record(frame, drawn). Direct rendering uses one drawIndexed per mesh with instances. Culling uses one drawIndexedIndirect per mesh the set has used. Meshes sharing a pipeline and textures draw consecutively with the pipeline and groups set once.

Await scene.initAsync() and light.shadow.initAsync() while loading to compile renderer pipelines. Otherwise each pipeline compiles on its first draw. The GPU debug panel names pipelines by kind, with qualifiers such as cast, cover for a prepass, two-sided or masked.

Outputs such as antialiasing over time’s motion run the renderer’s vertex code a second time with last frame’s rows. Create the set with history: true to keep them, as a table does. Each instance then moves in the motion output, whether write or a kernel moved it:

const
const school: instances.HistoryInstances<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">>
school
=
import instances
instances
.
function create<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">> & {
readonly history: true;
}): instances.HistoryInstances<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<Kind<"Fish", {}, { velocity: Vec3f; }, "device">>.kind?: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device"> | undefined

Selects a kind from instances.define. Default a plain kind with a transform and material.

kind
:
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
,
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 1024,
history: true

Keeps last frame's rows, as a table's history does, so motion follows every instance that moves, whether the CPU or a kernel moves it. create then returns HistoryInstances, whose flush takes the frame's encoder. Default false.

history
: 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 school: instances.HistoryInstances<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">>
school
.
HistoryInstances<Kind<"Fish", {}, { velocity: Vec3f; }, "device">>.flush(encoder: TgpuCommandEncoder): void

Uploads changed rows, as Instances.flush does, and records into encoder the copies that keep last frame's rows. Call this once per frame before drawing.

flush
(
frame: frames.Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
); // keeps last frame's rows, then uploads
// ... kernels that move the school, then the passes
});

Without history, the motion output sees only the camera move.

things.renderer(options) draws the set. Add it to multiple pass descriptions to build pipelines for each. Multiple renderers can draw the same set. drawn.destroy() removes a drawing from its description and frees its resources.

Option Default
light none A lighting in place of the one the description gives through beneath; a renderer whose shade reads none needs neither
blend 'opaque' 'translucent' covers what is drawn by each instance’s opacity and writes no depth; 'clear' is glass
transmit none Under 'clear', the share of each colour behind that shows through: a tint
textured true false ignores mesh textures and masks, drawing textured meshes with their factors alone
specularAntialiasing true false keeps sharp highlights on flat-shaded faces
cull false true draws into each description only what its camera may see
from 0 Draws only the instances at least this far from eye; a number or a 'use gpu' function of the row’s slot
to every distance Draws only the instances nearer than this to eye, as from
fade 0 Metres around from and to across which it hands its samples over
eye none The camera from and to measure from; a renderer with either needs it
shade shading.shade Computes outgoing light from the material. Supply unlit, toon or debug shading. A blend: 'clear' renderer always uses shadeClear
prepass false true draws an opaque renderer’s depth first, with coverage and masks alone, then shades where the depth is equal

With cull: true, each pass draws only instances its camera may see. The scene uses view, and the shadow uses the sun. Record renderer.cull(pass) after things.flush() and movement kernels, before shadow and scene passes:

const
const renderer: instances.Renderer
renderer
=
const things: instances.Instances<Plain>
things
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
({
RendererOptions.cull?: boolean | undefined

Enables GPU culling against each pass camera using spheres around mesh boxes. Call cull each frame to list visible instances in set order. Throws if the kind has deform without bounds. Default false.

cull
: true });
const
const drawn: passes.Drawn
drawn
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; 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 renderer: instances.Renderer
renderer
);
const
const cast: passes.Drawn
cast
=
const light: lighting.LightingOf<{
readonly shadow: {};
}>
light
.
shadow: Shadow | (Cascades & Shadow)

Provides the sun shadow when enabled in the options. Throws after destroy.

shadow
.
ShadowPasses.add<{
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 caster's depth pipeline with the shadow's bias and returns its draw methods.

add
(
const renderer: instances.Renderer
renderer
); // each keeps a list of its own
// After things.flush() each frame
const
const culling: TgpuComputePass
culling
=
const frame: Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
.
TgpuCommandEncoder.beginComputePass(descriptor?: TgpuComputePassDescriptor): TgpuComputePass

Begins recording a compute pass

beginComputePass
();
const renderer: instances.Renderer
renderer
.
Renderer.cull(pass: TgpuComputePass): void

Records visible-instance lists for each enabled description that contains this renderer. Call this after flush() and any kernels that move instances, before drawing. Throws unless the renderer has cull: true.

cull
(
const culling: TgpuComputePass
culling
);
const culling: TgpuComputePass
culling
.
TgpuComputePass.end(): void

Completes the recording of this compute pass

end
();
const light: lighting.LightingOf<{
readonly shadow: {};
}>
light
.
shadow: Shadow | (Cascades & Shadow)

Provides the sun shadow when enabled in the options. Throws after destroy.

shadow
.
SunShadow.record(frame: Frame | TgpuCommandEncoder, casters: passes.Drawn | readonly passes.Drawn[], options?: ShadowRecordOptions): void

Clears the map in a depth pass per cascade that redraw picks and draws the casters built by add. Call this while recording each frame, before drawing shaded surfaces. When disabled, it draws nothing and makes every point sunlit. A frame that draws no cascade writes a timer's timestamps from an empty compute pass.

record
(
const frame: Frame
frame
, [
const cast: passes.Drawn
cast
]);
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.record(frame: Frame | TgpuCommandEncoder, drawn: passes.Drawn | readonly passes.Drawn[], options?: passes.BeginOptions<{
readonly hdr: typeof passes.color;
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
(
const frame: Frame
frame
,
const drawn: passes.Drawn
drawn
);

Culling reads draw counts written by GPU kernels and uses indirect draws. Request indirect-first-instance with tgpu.init({ device: { optionalFeatures: ['indirect-first-instance'] } }) to share pipelines across meshes without a group per mesh. Without the feature, each indirect draw binds a group that holds its mesh, and its pipeline reads the mesh from there. Where a pipeline has no bind group to spare, each mesh gets a pipeline with its mesh compiled in.

  • Test each row with the sphere around its mesh box, scaled and transformed by the row. Model meshes and held items each use their own boxes.
  • Visible rows retain set order across frames so blended objects do not flicker.
  • cull dispatches two kernels over live rows per active pass description. It skips shadow work while shadows are off. Multiple renderers can share a compute pass.
  • In a description with layers, each layer keeps a list of its own, seen through its view. The two kernels dispatch once, over every layer at once, so the work grows with rows times layers and the dispatch count stays the same. Each layer’s pass draws its own list.
  • If deform moves vertices beyond the mesh box, supply a bounds sphere.
  • Use cameras.sees(cameras.current.$, center, radius) for the same visibility test in your shaders, such as a live lists alive callback.
Change the fade around 7 m from the bright eye marker. One renderer draws nearby spheres and another draws distant boxes, splitting pixels across the fade and culling from the view above.

Use less detail for distant objects. A culling renderer with from and to draws instances at least from and less than to metres from eye. Split a set between renderers, or use separate sets for near meshes and distant impostors:

const
const near: {
to: number;
fade: number;
eye: cameras.OrbitCamera;
}
near
= {
to: number
to
: 40,
fade: number
fade
: 8,
eye: cameras.OrbitCamera
eye
:
const view: cameras.OrbitCamera
view
};
const
const far: {
from: number;
fade: number;
eye: cameras.OrbitCamera;
}
far
= {
from: number
from
: 40,
fade: number
fade
: 8,
eye: cameras.OrbitCamera
eye
:
const view: cameras.OrbitCamera
view
};
const
const renderers: instances.Renderer[]
renderers
= [
const trees: instances.Instances<Plain>
trees
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
({
RendererOptions.cull?: boolean | undefined

Enables GPU culling against each pass camera using spheres around mesh boxes. Call cull each frame to list visible instances in set order. Throws if the kind has deform without bounds. Default false.

cull
: true, ...
const near: {
to: number;
fade: number;
eye: cameras.OrbitCamera;
}
near
}),
const cards: instances.Instances<instances.Kind<"Impostor", {}, {
phase: U32;
}, "host">>
cards
.
Instances<Kind<"Impostor", {}, { phase: U32; }, "host">>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
({
RendererOptions.cull?: boolean | undefined

Enables GPU culling against each pass camera using spheres around mesh boxes. Call cull each frame to list visible instances in set order. Throws if the kind has deform without bounds. Default false.

cull
: true, ...
const far: {
from: number;
fade: number;
eye: cameras.OrbitCamera;
}
far
}).
Renderer.pipe(fill: Inject): instances.Renderer

Returns this renderer with fill applied to every pipeline and kernel it builds. The fill runs after lighting and before the pass camera. Use it for resources read by kind callbacks, as in school.renderer().pipe(water.inject()).

pipe
(
const atlas: impostors.Atlas
atlas
.
Atlas.inject(sampling?: impostors.Sampling): Inject

Fills atlas resources for pipelines using Impostor or a kind made by define, read with sampling. Default 'blended'.

inject
()),
];
const
const drawn: passes.Drawn[]
drawn
=
const renderers: instances.Renderer[]
renderers
.
Array<Renderer>.map<passes.Drawn>(callbackfn: (value: instances.Renderer, index: number, array: instances.Renderer[]) => passes.Drawn, thisArg?: any): passes.Drawn[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
renderer: instances.Renderer
renderer
) =>
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; 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
(
renderer: instances.Renderer
renderer
));
const
const casts: passes.Drawn[]
casts
=
const renderers: instances.Renderer[]
renderers
.
Array<Renderer>.map<passes.Drawn>(callbackfn: (value: instances.Renderer, index: number, array: instances.Renderer[]) => passes.Drawn, thisArg?: any): passes.Drawn[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
renderer: instances.Renderer
renderer
) =>
const light: lighting.LightingOf<{
readonly shadow: {};
}>
light
.
shadow: Shadow | (Cascades & Shadow)

Provides the sun shadow when enabled in the options. Throws after destroy.

shadow
.
ShadowPasses.add<{
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 caster's depth pipeline with the shadow's bias and returns its draw methods.

add
(
renderer: instances.Renderer
renderer
));
  • Measure distance from eye to each row’s position. The same distance applies in every pass description, including shadows.
  • from and to can be shader callbacks taking the row slot, with their dependencies filled. Read uniforms to change thresholds without recompiling. Keep from below to for every row.
  • Across fade metres around a threshold, the renderer draws a share of each instance that falls with its distance. Give the adjoining renderer the same fade to draw the rest. With multisampling an instance keeps whole samples, the same ones in every pixel, so the two blend evenly across it in steps of one sample. Without it they split pixels in a 4 × 4 pattern, which shows as a screen door where the two look different. Shadows switch without fading.
  • Fading discards pixels or samples, which prevents early rejection of hidden pixels and increases shading work.

With blend: 'translucent', instances draw translucent from premultiplied colour and their opacity. In a description with translucency targets they need no order; elsewhere they blend over in draw order. They write no depth and cast no shadows. The renderer accepts only pass descriptions with colour. Put blended objects in a separate set and draw them after opaque objects:

const
const solid: instances.Instances<Plain>
solid
=
import instances
instances
.
function create<Plain>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<Plain>): instances.Instances<Plain> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 512 });
const
const ghosts: instances.Instances<Plain>
ghosts
=
import instances
instances
.
function create<Plain>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<Plain>): instances.Instances<Plain> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 4 });
const
const blocks: instances.Renderer
blocks
=
const solid: instances.Instances<Plain>
solid
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
();
// Drawn in this order, the ghosts over the blocks
const
const drawn: passes.Drawn[]
drawn
= [
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; 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 blocks: instances.Renderer
blocks
),
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; 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 ghosts: instances.Instances<Plain>
ghosts
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
({
RendererOptions.blend?: "clear" | "opaque" | "translucent" | undefined

Selects how instances write colour and depth. 'opaque' writes depth. 'translucent' draws from premultiplied opacity, as a drawing with translucent: true does: in any order into a description with translucency targets, over in draw order elsewhere. It leaves depth unchanged and draws only in colour passes, after the opaque renderers. 'clear' draws in the same way but adds reflections at full strength through shading.shadeClear, so glass and clear plastic retain highlights at any opacity. With transmit, it blends over in draw order. Default 'opaque'.

blend
: 'translucent' }))];
const
const casters: passes.Drawn[]
casters
= [
const light: lighting.LightingOf<{
readonly shadow: {};
}>
light
.
shadow: Shadow | (Cascades & Shadow)

Provides the sun shadow when enabled in the options. Throws after destroy.

shadow
.
ShadowPasses.add<{
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 caster's depth pipeline with the shadow's bias and returns its draw methods.

add
(
const blocks: instances.Renderer
blocks
)];

blend: 'clear' draws as 'translucent' does, with shading.shadeClear. Highlights and sky reflections stay bright at any opacity. Opacity scales diffuse light and emission. On metals, it fades only fog.

Use transmit to tint the background through glass. { blend: 'clear', transmit: [0.88, 0.92, 0.94] } transmits those fractions of each channel at any opacity. Opacity controls the milky appearance. The tint belongs to the renderer and is set as the pass blend constant at each draw, so a transmit renderer blends over in draw order.

The renderer supplies an instances.Corner at each vertex and an instances.Lit at each pixel. Outputs use these values, including motion for antialiasing over time. See Passes for target outputs.

A kind adds row fields and replaces shader functions with your own 'use gpu' functions. The fish tank’s fish keep velocity, beat their tails and have pale bellies:

const
const Fish: instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">
Fish
=
import instances
instances
.
function define<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">(name: "Fish", options?: instances.KindOptions<{
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">): instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">

Defines an instance kind with custom fields, transform ownership and callbacks for vertex motion or materials. Each kind uses colour and shadow pipelines per renderer. name brands set ids, as in Id<'Fish'>, and labels the table and WGSL. Throws if both material and surface are supplied, or a custom field duplicates a built-in or reserved name.

@param ― name a label for ids and WGSL

@returns ― a kind to give instances.create as kind

define
('Fish', {
KindOptions<{ belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">.host?: ({
belly: d.Vec3f;
phase: d.F32;
} & {
readonly rotation?: "is a field of every instance" | undefined;
readonly position?: "is a field of every instance" | undefined;
readonly scale?: "is a field of every instance" | undefined;
readonly color?: "is a field of every instance" | undefined;
readonly roughness?: "is a field of every instance" | undefined;
readonly emission?: "is a field of every instance" | undefined;
readonly metallic?: "is a field of every instance" | undefined;
readonly mesh?: "is a field of every instance" | undefined;
readonly opacity?: "is a field of every instance" | undefined;
} & {
...;
}) | undefined

Adds fields written on the CPU, as in table.define. Default none.

host
: {
belly: d.Vec3f
belly
:
import d
d
.
const vec3f: d.Vec3f
vec3f
,
phase: d.F32
phase
:
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
},
KindOptions<{ belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">.device?: ({
velocity: d.Vec3f;
} & {
readonly rotation?: "is a field of every instance" | undefined;
readonly position?: "is a field of every instance" | undefined;
readonly scale?: "is a field of every instance" | undefined;
readonly color?: "is a field of every instance" | undefined;
readonly roughness?: "is a field of every instance" | undefined;
readonly emission?: "is a field of every instance" | undefined;
readonly metallic?: "is a field of every instance" | undefined;
readonly mesh?: "is a field of every instance" | undefined;
readonly opacity?: "is a field of every instance" | undefined;
} & {
...;
}) | undefined

Adds fields written by GPU kernels. Default none.

device
: {
velocity: d.Vec3f
velocity
:
import d
d
.
const vec3f: d.Vec3f
vec3f
},
KindOptions<{ belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">.transform?: "device" | undefined

Stores position, rotation and scale in device fields when set to 'device', so kernels can write them. Default 'host'.

transform
: 'device',
// uv.x runs from the nose to the tail
KindOptions<{ belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">.deform?: ((vertex: instances.Vertex, instance: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}) => d.v3f) | undefined

Moves a vertex in object space before the instance transform. Colour and shadow passes both apply this function. The shadow pass must then read the whole vertex instead of its position alone. Normals remain as the mesh or pose supplies them. Default none, which uses the mesh or posed position.

deform
: (
vertex: {
position: d.v3f;
normal: d.v3f;
uv: d.v2f;
}
vertex
,
fish: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
) => {
'use gpu';
const
const t: number
t
=
vertex: {
position: d.v3f;
normal: d.v3f;
uv: d.v2f;
}
vertex
.
uv: d.v2f
uv
.
v2f.x: number
x
;
const
const beat: number
beat
=
import std
std
.
function sin(value: number): number (+1 overload)
export sin
sin
(
const time: TgpuUniform<d.F32>
time
.
TgpuUniform<F32>.$: number
$
* 10 +
fish: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
.
phase: number
phase
-
const t: number
t
* 5) * 0.14 *
const t: number
t
*
const t: number
t
;
return
vertex: {
position: d.v3f;
normal: d.v3f;
uv: d.v2f;
}
vertex
.
position: d.v3f
position
+
import d
d
.
const vec3f: d.Vec3f
(x: number, y: number, z: number) => d.v3f (+5 overloads)
vec3f
(
const beat: number
beat
, 0, 0);
},
KindOptions<{ belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">.material?: ((point: Point, instance: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}, base: Material, carried: d.v4f) => Material) | undefined

Returns the material at a point. base combines the instance material fields with the mesh textures, as materials.textured does. carried contains interpolated values from carry. Default base.

material
: (
point: {
position: d.v3f;
normal: d.v3f;
view: d.v3f;
uv: d.v2f;
uv1: d.v2f;
}
point
,
fish: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
) => {
'use gpu';
const
const up: number
up
=
import std
std
.
function cos(value: number): number (+1 overload)
export cos
cos
(
point: {
position: d.v3f;
normal: d.v3f;
view: d.v3f;
uv: d.v2f;
uv1: d.v2f;
}
point
.
uv: d.v2f

Holds texture coordinates at the point. A point created with pointAt has zero coordinates.

uv
.
v2f.y: number
y
*
const TAU: number
TAU
);
return
import materials
materials
.
const glossy: (color: d.v3f, roughness: number) => {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}

Creates a dielectric with specular highlights, such as paint, plastic or wet stone.

glossy
(
import std
std
.
mix<d.v3f>(e1: d.v3f, e2: d.v3f, e3: number): d.v3f (+2 overloads)
export mix
mix
(
fish: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
.
belly: d.v3f
belly
,
fish: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
belly: d.v3f;
phase: number;
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
.
color: d.v3f
color
,
import std
std
.
function smoothstep(edge0: number, edge1: number, x: number): number (+1 overload)
export smoothstep
smoothstep
(-0.4, 0.5,
const up: number
up
)), 0.35);
},
});
const
const school: instances.Instances<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>
school
=
import instances
instances
.
function create<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>): instances.Instances<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<Kind<"Fish", { belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">>.kind?: instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device"> | undefined

Selects a kind from instances.define. Default a plain kind with a transform and material.

kind
:
const Fish: instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">
Fish
,
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 4096 });
const school: instances.Instances<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>
school
.
Instances<Kind<"Fish", { belly: Vec3f; phase: F32; }, { velocity: Vec3f; }, "device">>.add(mesh: meshPool.Mesh | Pick<meshPool.Model, "meshes">, values?: instances.Values<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">> | ((mesh: meshPool.Mesh, index: number) => instances.Values<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>) | undefined): IdOf<instances.Kind<"Fish", {
belly: d.Vec3f;
phase: d.F32;
}, {
velocity: d.Vec3f;
}, "device">>

Adds an instance of a mesh, model or group of meshes from the pool. Each mesh uses a row, and all rows move and change together under one id. values may be a function of each mesh, to give a model's meshes values of their own. Throws if a mesh belongs to another pool, the group is empty, a posed kind receives a mesh without joints or the set is full.

add
(
const body: meshPool.Mesh
body
, {
position?: ArrayLike<number> | d.InferInput<d.Vec3f> | undefined
position
: [0, 2, 0],
color?: ArrayLike<number> | d.InferInput<d.Vec3f> | undefined
color
: [0.1, 0.45, 0.95],
belly: [number, number, number]
belly
: [0.95, 0.25, 0.22],
phase: number
phase
: 1.3,
velocity: [number, number, number]
velocity
: [1, 0, 0],
});
  • Call instances.define at module scope without a root. Pass the result to create as kind.
  • The name brands set ids, such as instances.Id<'Fish'>, and names the WGSL.
  • Supply custom fields alongside built-in fields in add and write. Reusing a built-in name such as color or a reserved table name such as host, device, row, alive, span or slotOf is a type error. define also throws.

All functions are optional. instance gives the whole row. Functions can read uniforms and buffers, such as time.$ above:

Function Takes and returns What it replaces
place (instance) => instances.Placement Where the instance is, from data of your own, in every pass, in culling and for from and to. The row’s own transform goes unread.
visible (instance) => bool Whether it draws, in every renderer and pass. A culling renderer leaves it out of its lists; one that doesn’t cull collapses its triangles.
pose (instance) => u32, a pose’s id The mesh as bound: vertices and normals follow the pose’s joints, in every pass, before deform. Poses come from the poses piped into the renderer.
deform (vertex: instances.Vertex, instance) => vec3f Where the vertex is, in object space, in every pass. The normal stays the mesh’s, or the pose’s.
bounds (instance, base: instances.Sphere) => instances.Sphere The sphere a culling renderer tests, in world space; base is the one around the mesh’s box.
carry (vertexIndex: u32, instance) => vec4f Sends interpolated per-vertex data to material and surface as carried. See Carried from each vertex.
material (point: shading.Point, instance, base: shading.Material, carried) => shading.Material What the point is made of; base is the row’s material times the mesh’s textures. Call materials presets here.
surface (point: shading.Point, instance, base: shading.Material, carried) => instances.Shaded Replaces the mesh surface with a shading point and material, as impostors do.
coverage (point: shading.Point, instance, base: shading.Material, carried) => f32 How much of the pixel the instance covers, from 0 to 1, in every pass, shadows included: holes such as lace, or the leaves on a card.
  • With deform, the shadow pass reads 20 bytes per vertex rather than 12, or 28 rather than 20 with a pose. Set deformShadow: false for deformations too small to see in shadows, such as tail motion.
  • A culling renderer of a kind with a deform needs bounds.
  • Supply either material or surface. A custom surface shades at mesh depth and writes its supplied point depth to shadows.
  • coverage runs before material or surface. With multisampling, it selects the share of samples covered; without, pixels below half coverage are omitted. Blended renderers scale opacity by it. A kind without coverage keeps early depth testing, so each mesh draws once and hidden pixels go unshaded.
  • A heavy material or surface that overlaps itself, such as a forest of impostor cards, can take prepass: true on its renderer: the depth goes first, running only coverage and the mesh masks, then the colour shades each visible pixel once. It costs a second pass over the vertices and needs a description with depth.
  • Each kind compiles a colour pipeline per pass description and a depth pipeline for shadows. Put per-instance differences in row fields to avoid extra pipelines.

With transform: 'device', the transform joins the kind’s device fields. A kernel created from root.pipe(school.inject()) reads through the kind’s getters and writes Fish.device.$[i]. Dispatch it over school.span after school.flush(), skipping free slots:

const
const swim: TgpuComputeFn<{
gid: d.BuiltinGlobalInvocationId;
}>
swim
=
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
.
computeFn: <{
gid: d.BuiltinGlobalInvocationId;
}>(options: {
in: {
gid: d.BuiltinGlobalInvocationId;
};
workgroupSize: number[];
}) => TgpuComputeFnShell<{
gid: d.BuiltinGlobalInvocationId;
}> (+1 overload)
computeFn
({
workgroupSize: number[]
workgroupSize
: [64],
in: {
gid: d.BuiltinGlobalInvocationId;
}
in
: {
gid: d.BuiltinGlobalInvocationId
gid
:
import d
d
.
const builtin: {
readonly vertexIndex: d.BuiltinVertexIndex;
readonly instanceIndex: d.BuiltinInstanceIndex;
readonly clipDistances: d.BuiltinClipDistances;
readonly position: d.BuiltinPosition;
readonly frontFacing: d.BuiltinFrontFacing;
readonly fragDepth: d.BuiltinFragDepth;
readonly primitiveIndex: d.BuiltinPrimitiveIndex;
readonly sampleIndex: d.BuiltinSampleIndex;
... 11 more ...;
readonly numSubgroups: d.BuiltinNumSubgroups;
}
export builtin
builtin
.
globalInvocationId: d.BuiltinGlobalInvocationId
globalInvocationId
},
})(({
gid: d.v3u
gid
}) => {
'use gpu';
const
const i: number
i
=
gid: d.v3u
gid
.
v3u.x: number
x
;
if (!
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
.
alive: TgpuGenericFn
(i: number) => boolean

Tests whether slot i holds a row. Returns false beyond the span.

alive
(
const i: number
i
)) return;
const
const fish: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
=
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
.
device: TgpuAccessor<Rows<DeviceOf<{
velocity: d.Vec3f;
}, "device">>>

Provides GPU-written rows with read-write access in compute pipelines and read-only access in render pipelines.

device
.
TgpuAccessor<Rows<DeviceOf<{ velocity: Vec3f; }, "device">>>.$: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}[]
$
[
const i: number
i
]!;
const fish: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
.
position: d.v3f
position
=
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
.
position: Getter
(i: number) => d.v3f
position
(
const i: number
i
) +
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
.
velocity: Getter
(i: number) => d.v3f
velocity
(
const i: number
i
) *
const step: number
step
;
const fish: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
velocity: d.v3f;
}
fish
.
rotation: d.v4f
rotation
=
import instances
instances
.
const facing: (direction: d.v3f) => d.v4f

Returns a unit quaternion that points mesh +z along direction and keeps +y up. glTF models face +z. direction can have any length.

facing
(
const Fish: instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">
Fish
.
velocity: Getter
(i: number) => d.v3f
velocity
(
const i: number
i
));
});
const
const swimming: TgpuComputePipeline
swimming
=
const root: TgpuRoot
root
.
WithBinding.pipe(transform: (cfg: Configurable) => Configurable): WithBinding
pipe
(
const school: instances.Instances<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">>
school
.
function inject(): Inject

Fills the definition's accessors with this table's buffers.

inject
()).
WithBinding.createComputePipeline<{
gid: d.BuiltinGlobalInvocationId;
}>(descriptor: TgpuComputePipeline.Descriptor<{
gid: d.BuiltinGlobalInvocationId;
}>): TgpuComputePipeline
createComputePipeline
({
compute: TgpuComputeFn<{
gid: d.BuiltinGlobalInvocationId;
}>
compute
:
const swim: TgpuComputeFn<{
gid: d.BuiltinGlobalInvocationId;
}>
swim
});
const pass: TgpuComputePass
pass
.
TgpuComputePass.setPipeline(pipeline: TgpuComputePipeline): void

Sets the current

TgpuComputePipeline

for subsequent dispatches

setPipeline
(
const swimming: TgpuComputePipeline
swimming
);
const pass: TgpuComputePass
pass
.
TgpuComputePass.dispatchWorkgroups(x: number, y?: number, z?: number): void
dispatchWorkgroups
(
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.ceil(x: number): number

Returns the smallest integer greater than or equal to its numeric argument.

@param ― x A numeric expression.

ceil
(
const school: instances.Instances<instances.Kind<"Fish", {}, {
velocity: d.Vec3f;
}, "device">>
school
.
span: number

Reports the highest live slot plus one.

span
/ 64));

add uploads the whole initial row. Kernels then own device fields. Writing those fields from the CPU overwrites kernel values at the next flush.

For motion that follows each fish, create the set with history.

If a simulation has its own position buffer, read it in place instead of copying positions to rows every frame. Fill the dependency through the renderer’s pipe:

const
const bodies: TgpuAccessor<d.WgslArray<d.Vec4f>>
bodies
=
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
, 256)); // xyz is world position; w is heading
const
const Horse: instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">
Horse
=
import instances
instances
.
function define<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">(name: "Horse", options?: instances.KindOptions<{
body: d.U32;
fallen: d.U32;
}, {}, "host">): instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">

Defines an instance kind with custom fields, transform ownership and callbacks for vertex motion or materials. Each kind uses colour and shadow pipelines per renderer. name brands set ids, as in Id<'Fish'>, and labels the table and WGSL. Throws if both material and surface are supplied, or a custom field duplicates a built-in or reserved name.

@param ― name a label for ids and WGSL

@returns ― a kind to give instances.create as kind

define
('Horse', {
KindOptions<{ body: U32; fallen: U32; }, {}, "host">.host?: ({
body: d.U32;
fallen: d.U32;
} & {
readonly rotation?: "is a field of every instance" | undefined;
readonly position?: "is a field of every instance" | undefined;
readonly scale?: "is a field of every instance" | undefined;
readonly color?: "is a field of every instance" | undefined;
readonly roughness?: "is a field of every instance" | undefined;
readonly emission?: "is a field of every instance" | undefined;
readonly metallic?: "is a field of every instance" | undefined;
readonly mesh?: "is a field of every instance" | undefined;
readonly opacity?: "is a field of every instance" | undefined;
} & {
...;
}) | undefined

Adds fields written on the CPU, as in table.define. Default none.

host
: {
body: d.U32
body
:
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
,
fallen: d.U32
fallen
:
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
},
KindOptions<{ body: U32; fallen: U32; }, {}, "host">.place?: ((instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}) => instances.Placement) | undefined

Returns the instance transform from custom data, such as a simulation buffer. All passes use it, including culling and distance limits from from and to. It runs for each vertex in every pass; when it does heavy work, a kernel that writes device rows once a frame costs less. Attach its fills with pipe or the renderer pipe method. Default the instance position, rotation and scale.

place
: (
horse: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}
horse
) => {
'use gpu';
const
const body: d.v4f
body
=
const bodies: TgpuAccessor<d.WgslArray<d.Vec4f>>
bodies
.
TgpuAccessor<WgslArray<Vec4f>>.$: d.v4f[]
$
[
horse: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}
horse
.
body: number
body
]!;
return
import instances
instances
.
function Placement(props?: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
} | undefined): {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
}
export Placement

This schema holds a unit quaternion, position and scale per axis. Instance transforms use world space; joint transforms use parent space.

Placement
({
rotation: d.v4f
rotation
:
import d
d
.
const vec4f: d.Vec4f
(x: number, y: number, z: number, w: number) => d.v4f (+9 overloads)
vec4f
(0,
import std
std
.
function sin(value: number): number (+1 overload)
export sin
sin
(
const body: d.v4f
body
.
v4f.w: number
w
/ 2), 0,
import std
std
.
function cos(value: number): number (+1 overload)
export cos
cos
(
const body: d.v4f
body
.
v4f.w: number
w
/ 2)),
position: d.v3f
position
:
const body: d.v4f
body
.
xyz: d.v3f
xyz
,
scale: d.v3f
scale
:
import d
d
.
const vec3f: d.Vec3f
(xyz: number) => d.v3f (+5 overloads)
vec3f
(1),
});
},
KindOptions<{ body: U32; fallen: U32; }, {}, "host">.visible?: ((instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}) => boolean) | undefined

Controls visibility in every renderer and pass, including shadows, without removing the instance. Culling renderers omit hidden instances from their lists. Other renderers collapse their triangles. Default always.

visible
: (
horse: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}
horse
) => {
'use gpu';
return
horse: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
body: number;
fallen: number;
}
horse
.
fallen: number
fallen
=== 0;
},
});
const
const horses: instances.Instances<instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">>
horses
=
import instances
instances
.
function create<instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">>(root: TgpuRoot, pool: meshPool.MeshPool, options: instances.Options<instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">>): instances.Instances<instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">> (+1 overload)

Creates a set of mesh instances with transforms, materials and optional custom fields. Each instance uses a row, and renderers draw one list of live rows per mesh.

@param ― pool the mesh pool whose meshes it draws

@param ― options.kind a kind from instances.define

@returns ― a set of instances you flush every frame and destroy

create
(
const root: TgpuRoot
root
,
const pool: meshPool.MeshPool<{}>
pool
, {
Options<Kind<"Horse", { body: U32; fallen: U32; }, {}, "host">>.kind?: instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host"> | undefined

Selects a kind from instances.define. Default a plain kind with a transform and material.

kind
:
const Horse: instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">
Horse
,
Options<K extends AnyKind = Plain>.capacity: number

Limits the number of rows. A mesh instance uses one row; a model instance uses one row per mesh.

capacity
: 256 });
const
const renderer: instances.Renderer
renderer
=
const horses: instances.Instances<instances.Kind<"Horse", {
body: d.U32;
fallen: d.U32;
}, {}, "host">>
horses
.
Instances<Kind<"Horse", { body: U32; fallen: U32; }, {}, "host">>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
().
Renderer.pipe(fill: Inject): instances.Renderer

Returns this renderer with fill applied to every pipeline and kernel it builds. The fill runs after lighting and before the pass camera. Use it for resources read by kind callbacks, as in school.renderer().pipe(water.inject()).

pipe
((
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 bodies: TgpuAccessor<d.WgslArray<d.Vec4f>>
bodies
,
const herd: TgpuBuffer<d.WgslArray<d.Vec4f>> & StorageFlag
herd
.
TgpuBuffer<WgslArray<Vec4f>>.as<"readonly">(usage: "readonly"): TgpuReadonly<d.WgslArray<d.Vec4f>>
as
('readonly')));

add and write still accept row position, rotation and scale, but place ignores them. place runs for each vertex in every pass; when it does heavy work, a kernel that writes rows once a frame costs less.

Fill dependencies read by kind functions through the renderer’s pipe. For example, the fish tank reads a noise cache. See shader dependencies:

const
const noise: StaticPerlin3DCache
noise
=
(alias) namespace perlin3d
import perlin3d
perlin3d
.
index.staticCache(options: {
root: TgpuRoot;
size: d.v3u;
}): StaticPerlin3DCache
export index.staticCache

A statically-sized cache for perlin noise generation, which reduces the amount of redundant calculations if sampling is done more than once. If you'd like to change the size of the cache at runtime, see perlin3d.dynamicCacheConfig.

--- Basic usage

@example

const mainFragment = tgpu.fragmentFn({ out: d.vec4f })(() => {
const n = perlin3d.sample(d.vec3f(1.1, 2.2, 3.3));
// ...
});
const cache = perlin3d.staticCache({ root, size: d.vec3u(10, 10, 1) });
const pipeline = root
// Plugging the cache into the pipeline
.pipe(cache.inject())
// ...
.createRenderPipeline({
// ...
});

--- Wrapped coordinates

If the noise generator samples outside of the bounds of this cache, the space is wrapped around.

@example

const cache = perlin3d.staticCache({ root, size: d.vec3u(10, 10, 1) });
// ...
const value = perlin3d.sample(d.vec3f(0.5, 0, 0));
const wrappedValue = perlin3d.sample(d.vec3f(10.5, 0, 0)); // the same as `value`!

staticCache
({
root: TgpuRoot

The root to use for allocating resources.

root
,
size: d.v3u

The size of the cache.

size
:
import d
d
.
const vec3u: d.Vec3u
(x: number, y: number, z: number) => d.v3u (+5 overloads)
vec3u
(16, 16, 32) });
const
const renderer: instances.Renderer
renderer
=
const sand: instances.Instances<Plain>
sand
.
Instances<Plain>.renderer(options?: instances.RendererOptions): instances.Renderer

Creates a renderer for colour and shadow pass descriptions, lit by the lighting each description gives through beneath unless options.light replaces it. Use pipe to fill resources read by kind callbacks.

renderer
().
Renderer.pipe(fill: Inject): instances.Renderer

Returns this renderer with fill applied to every pipeline and kernel it builds. The fill runs after lighting and before the pass camera. Use it for resources read by kind callbacks, as in school.renderer().pipe(water.inject()).

pipe
(
const noise: StaticPerlin3DCache
noise
.
StaticPerlin3DCache.inject(): (cfg: Configurable) => Configurable
inject
());
// No surface lies below the sand, so omit its shadow caster
const
const drawn: passes.Drawn
drawn
=
const scene: passes.Passes<{
readonly hdr: typeof passes.color;
readonly depth: typeof passes.depth;
}>
scene
.
Passes<{ readonly hdr: typeof color; readonly depth: typeof depth; }>.add<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.v2f;
row: number;
}>(this: passes.Passes<passes.Fed<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.v2f;
row: number;
}>>, drawing: passes.Compound<{
color: d.v4f;
}, {
position: d.v4f;
world: d.v3f;
normal: d.v3f;
uv: d.v2f;
uv1: d.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 renderer: instances.Renderer
renderer
);

A custom fill takes a configuration, for example .pipe((cfg) => cfg.with(clock, time)).

base includes mesh textures. Modify only the fields you need. The hex isle adds light where its house atlas has window panes:

const
const House: instances.Kind<"House", {
glow: d.F32;
}, {}, "host">
House
=
import instances
instances
.
function define<"House", {
glow: d.F32;
}, {}, "host">(name: "House", options?: instances.KindOptions<{
glow: d.F32;
}, {}, "host">): instances.Kind<"House", {
glow: d.F32;
}, {}, "host">

Defines an instance kind with custom fields, transform ownership and callbacks for vertex motion or materials. Each kind uses colour and shadow pipelines per renderer. name brands set ids, as in Id<'Fish'>, and labels the table and WGSL. Throws if both material and surface are supplied, or a custom field duplicates a built-in or reserved name.

@param ― name a label for ids and WGSL

@returns ― a kind to give instances.create as kind

define
('House', {
KindOptions<{ glow: F32; }, {}, "host">.host?: ({
glow: d.F32;
} & {
readonly rotation?: "is a field of every instance" | undefined;
readonly position?: "is a field of every instance" | undefined;
readonly scale?: "is a field of every instance" | undefined;
readonly color?: "is a field of every instance" | undefined;
readonly roughness?: "is a field of every instance" | undefined;
readonly emission?: "is a field of every instance" | undefined;
readonly metallic?: "is a field of every instance" | undefined;
readonly mesh?: "is a field of every instance" | undefined;
readonly opacity?: "is a field of every instance" | undefined;
} & {
...;
}) | undefined

Adds fields written on the CPU, as in table.define. Default none.

host
: {
glow: d.F32
glow
:
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
},
KindOptions<{ glow: F32; }, {}, "host">.material?: ((point: shading.Point, instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
glow: number;
}, base: shading.Material, carried: d.v4f) => shading.Material) | undefined

Returns the material at a point. base combines the instance material fields with the mesh textures, as materials.textured does. carried contains interpolated values from carry. Default base.

material
: (
point: {
position: d.v3f;
normal: d.v3f;
view: d.v3f;
uv: d.v2f;
uv1: d.v2f;
}
point
,
house: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
glow: number;
}
house
,
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
) => {
'use gpu';
// Window panes occupy column 6, row 1 of the 8 by 4 atlas
const
const pane: boolean
pane
=
import std
std
.
function all(value: boolean | AnyBooleanVecInstance): boolean
export all

Returns true if each component of value is true.

@example all(vec2b(false, true)) // returns false all(vec3b(true, true, true)) // returns true

all
(
import std
std
.
eq<d.v2f>(lhs: d.v2f, rhs: d.v2f): d.v2b
export eq

Checks component-wise whether lhs == rhs. This function does not return bool, for that use-case, wrap the result in all, or use allEq.

@example eq(vec2f(0.0, 1.0), vec2f(0.0, 2.0)) // returns vec2b(true, false) eq(vec3u(0, 1, 2), vec3u(2, 1, 0)) // returns vec3b(false, true, false) all(eq(vec4i(4, 3, 2, 1), vec4i(4, 3, 2, 1))) // returns true allEq(vec4i(4, 3, 2, 1), vec4i(4, 3, 2, 1)) // returns true

eq
(
import std
std
.
floor<d.v2f>(value: d.v2f): d.v2f (+1 overload)
export floor
floor
(
point: {
position: d.v3f;
normal: d.v3f;
view: d.v3f;
uv: d.v2f;
uv1: d.v2f;
}
point
.
uv: d.v2f

Holds texture coordinates at the point. A point created with pointAt has zero coordinates.

uv
*
import d
d
.
const vec2f: d.Vec2f
(x: number, y: number) => d.v2f (+3 overloads)
vec2f
(8, 4)),
import d
d
.
const vec2f: d.Vec2f
(x: number, y: number) => d.v2f (+3 overloads)
vec2f
(6, 1)));
const
const lit: number
lit
=
import std
std
.
function select(f: number, t: number, cond: boolean): number (+2 overloads)
export select

Returns t if cond is true, and f otherwise. Component-wise if cond is a vector.

@example select(1, 2, false) // returns 1 select(1, 2, true) // returns 2 select(vec2i(1, 2), vec2i(3, 4), true) // returns vec2i(3, 4) select(vec2i(1, 2), vec2i(3, 4), vec2b(false, true)) // returns vec2i(1, 4)

select
(
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
(0),
house: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
glow: number;
}
house
.
glow: number
glow
*
const night: TgpuAccessor<d.F32>
night
.
TgpuAccessor<F32>.$: number
$
,
const pane: boolean
pane
);
const
const glowing: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
glowing
=
import shading
shading
.
const Material: d.WgslStruct
(props?: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
} | undefined) => {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}

This schema describes a surface with the glTF metallic-roughness model.

Material
(
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
);
const glowing: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
glowing
.
emission: d.v3f

Sets the emitted light in linear colour space. Shading adds it after lighting.

emission
=
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
.
emission: d.v3f

Sets the emitted light in linear colour space. Shading adds it after lighting.

emission
+
const WARM: d.v3f
WARM
*
const lit: number
lit
;
return
const glowing: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
glowing
;
},
});

materials.textured(material, point) textures a material made another way, such as a preset, in a fragment shader.

Use carry to read per-vertex data, such as a mesh-pool extra attribute. material and surface receive the interpolated value as their last argument. This example uses vertex colours:

const
const pool: meshPool.MeshPool<{
color: d.Vec4f;
}>
pool
=
import meshPool
meshPool
.
function create<{
color: d.Vec4f;
}>(root: TgpuRoot, options: meshPool.Options<{
color: d.Vec4f;
}>): meshPool.MeshPool<{
color: d.Vec4f;
}>

Creates shared vertex storage and an index buffer, with bounds and textures per mesh. One pipeline can draw any mesh. Each vertex uses 12 bytes for position and 8 for normal and UV coordinates, and 8 for a second uv set with uvs1. Skinned models add 8 bytes for joints and weights. Extras add the size of their struct per vertex.

@injects ― definition the vertices vertexAt, positionAt and uv1At read, the joints and weights influencesAt reads, and the boxes boundsOf reads

@injects ― per-instance the extras pool.extra reads

@binds ― 1 storage: positionAt, the positions

@binds ― 2 storage: vertexAt, the positions and the normals and uvs

@binds ― 1 storage: uv1At, the second uvs, in a pool made with uvs1

@binds ― 1 storage: influencesAt, the joints and weights

@binds ― 1 storage: boundsOf, every mesh's box

@binds ― 1 storage: pool.extra, every vertex's extras

@binds ― 1 uniform: pool.texturesOf(index) for materials, beside its textures and sampler

@submits ― setup a shape added without an encoder bakes in a compute pass of its own, submitted at once, and a model's images generate their mips as they decode

@owns ― 5 to 7 buffers, a uniform per way of reading textures, a pipeline per shape, textures, samplers, bind groups, what images makes: positions, normals and uvs, indices and boxes, second uvs with uvs1, joints and weights once a skinned model comes, and the extras when extra names any; each image decoded once per format it is read in, and a group per set of a mesh's textures

@returns ― a pool you add meshes and models to and destroy

create
(
const root: TgpuRoot
root
, {
Options<E extends Extras = {}>.capacity: number

Limits the number of meshes to at most 256.

capacity
: 16,
Options<{ color: Vec4f; }>.extra?: {
color: d.Vec4f;
} | undefined

Declares custom vertex attributes, for example { tint: d.vec4f }. Model meshes supply their data in extra; shaders read it through pool.extra.tint(i). These attributes use a separate buffer with one struct per vertex. Shapes read as zero. Default none.

extra
: {
color: d.Vec4f
color
:
import d
d
.
const vec4f: d.Vec4f
vec4f
} });
const
const Painted: instances.Kind<"Painted", {}, {}, "host">
Painted
=
import instances
instances
.
function define<"Painted", {}, {}, "host">(name: "Painted", options?: instances.KindOptions<{}, {}, "host">): instances.Kind<"Painted", {}, {}, "host">

Defines an instance kind with custom fields, transform ownership and callbacks for vertex motion or materials. Each kind uses colour and shadow pipelines per renderer. name brands set ids, as in Id<'Fish'>, and labels the table and WGSL. Throws if both material and surface are supplied, or a custom field duplicates a built-in or reserved name.

@param ― name a label for ids and WGSL

@returns ― a kind to give instances.create as kind

define
('Painted', {
KindOptions<{}, {}, "host">.carry?: ((vertexIndex: number, instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
}) => d.v4f) | undefined

Returns four values to interpolate between vertices and pass to material or surface as carried. For example, read an extra attribute with pool.extra.tint(vertexIndex). vertexIndex indexes the pool, as in meshPool.vertexAt. Default none, which omits four floats per vertex and sets carried to zero.

carry
: (
vertexIndex: number
vertexIndex
) => {
'use gpu';
return
const pool: meshPool.MeshPool<{
color: d.Vec4f;
}>
pool
.
MeshPool<{ color: Vec4f; }>.extra: meshPool.ExtraReaders<{
color: d.Vec4f;
}>

Reads the attributes named in extra for pool vertex i. Create calling shaders from root.pipe(pool.inject()).

extra
.
color: (i: number) => d.v4f
color
(
vertexIndex: number
vertexIndex
);
},
KindOptions<{}, {}, "host">.material?: ((point: shading.Point, instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
}, base: shading.Material, carried: d.v4f) => shading.Material) | undefined

Returns the material at a point. base combines the instance material fields with the mesh textures, as materials.textured does. carried contains interpolated values from carry. Default base.

material
: (
_point: {
position: d.v3f;
normal: d.v3f;
view: d.v3f;
uv: d.v2f;
uv1: d.v2f;
}
_point
,
_instance: {
rotation: d.v4f;
position: d.v3f;
scale: d.v3f;
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
mesh: number;
opacity: number;
}
_instance
,
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
,
carried: d.v4f
carried
) => {
'use gpu';
const
const painted: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
painted
=
import shading
shading
.
const Material: d.WgslStruct
(props?: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
} | undefined) => {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}

This schema describes a surface with the glTF metallic-roughness model.

Material
(
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
);
const painted: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
painted
.
color: d.v3f

Sets the diffuse colour of a dielectric or the reflection colour of a metal, in linear colour space.

color
=
base: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
base
.
color: d.v3f

Sets the diffuse colour of a dielectric or the reflection colour of a metal, in linear colour space.

color
*
carried: d.v4f
carried
.
rgb: d.v3f
rgb
;
return
const painted: {
color: d.v3f;
roughness: number;
emission: d.v3f;
metallic: number;
occlusion: number;
}
painted
;
},
});
  • vertexIndex uses pool indices, as meshPool.vertexAt does. Without carry, carried is zero and vertices pass four fewer floats.
  • pool.extra belongs to one pool. Define kinds that read it after creating that pool, and use them only with its meshes.
Member
things.count Live instances. A model counts once.
things.span, things.capacity Rows: the slot range kernels must visit, and the most rows the set holds.
fields, live(), idAt, slotOf, buffers, clear() As on a table, with a model’s rows under one id.
Fish.device The device fields, a storage buffer per set that school.inject() fills, for your kernels to write. A write overwrites them from the CPU.
Fish.position(i), Fish.alive(i) A getter per field, and whether slot i is live, in shaders created from inject().
What
a row 80 bytes plus custom kind fields, or 48 bytes in each part with transform: 'device'. The live list adds 4 bytes per row.
a set 4 bytes per mesh of pool capacity for its list. Drawing through a render bundle adds 20 bytes per mesh for draw arguments.
culling Per pass description and per layer, 8 bytes per row of set capacity and 28 bytes per mesh of pool capacity.
history Twice the row bytes again, for last frame’s rows and the frame’s uploads.

destroy() on a set frees its buffers once nothing draws with them. After it, has is false and remove does nothing.

Message Thrown by
The kind 'Fish' must supply either material or surface, not both. define
'color' is a built-in instance field. Choose another name., or 'span' is reserved by table.define. define
The set is full (1024 rows; a model takes a row per mesh). add
Row id … is stale because its row was removed. write or remove after remove
The mesh belongs to another pool. add
The table 'Fish' keeps history, so flush takes the frame's encoder: flush(frame.encoder). flush without an encoder, on a set with history
Slot 3 holds no row. idAt, for a free slot
The model has no meshes. add
The kind 'Fish' uses pose and requires a mesh with joints. add, for a mesh that isn’t skinned
The kind 'Fish' uses deform. Supply bounds before enabling culling. renderer, with cull: true
A renderer with from or to requires cull: true. renderer
A renderer with from or to requires eye. renderer
Renderer distances require from >= 0, to > from and fade >= 0. …, a RangeError renderer, for a negative from or fade, or a to not beyond from
A renderer with transmit requires blend: 'clear'. renderer
Each transmit channel must be from 0 to 1. Received [1, 1.5, 1]., a RangeError renderer
A renderer with blend: 'translucent' leaves depth alone; …, or 'clear' light.shadow.add, or add on any description of depth alone
A renderer with prepass: true draws into passes with depth. add on a description without depth
This renderer was created without `cull: true`. cull
The instances were destroyed. add, write, flush, inject, renderer, and building, culling or drawing a renderer, after destroy
  • Two sets of one kind with the same renderer options compile a pipeline pair each.
  • Renderers compile a pipeline for each combination of doubleSided, masked and textured present in the pool, including unused meshes. initAsync compiles combinations present at that time. Adding a mesh with another combination, such as an impostor card, causes compilation on its first draw.
  • A renderer draws an alpha: 'blend' material as opaque; blending is the renderer’s blend option.
  • Render bundles cannot set a blend constant. For a transmit renderer in a bundle, set it on the enclosing pass with pass.setBlendConstant([...transmit, 1]).
  • A bundle draws the meshes that had instances when it was recorded. Record it again after a mesh’s first instance, and once a model’s ready resolves.
  • Back-face lighting uses the interpolated normal relative to the eye. A front face can therefore receive back lighting near an edge where that normal turns away.
  • A kind with a surface ignores masks: it says what it covers itself.
  • deform can’t bend the normal or move the uv.
  • facing applies no y rotation for straight-up or straight-down directions. Rotate models that do not face +z when reading them with rotation.