Hides the card in every pass, as in instances.define.
records
capture→encoder
atlas.capture(encoder) once while loading, after what moves the subject's poses and before the passes that draw the atlas.
owns
5 textures ·3 buffers ·1 or 2 samplers ·5 to 8 pipelines ·mipmaps
The atlas's colours and its normals with depth, the multisampled targets that draw them, the subject's sphere, the extents it is fitted from and its pieces; the atlas's sampler, and the pool's the first time a capture binds its textures; four kernels that fit the sphere, a pipeline for each look of the subject's meshes, one-sided or two-sided, masked or not, that capture it; the mipmaps of each atlas texture.
lifecycle
✓destroy()✓[Symbol.dispose]
injects
definition
The atlas that Impostor and kinds made by define read, for a renderer piped atlas.inject(sampling).
binds
1 storage
The subject's sphere, in the impostors' renderer's pipelines.
1 storage
The kind's device rows, where its surface reads the captured phase, beside the host rows its transform reads.
Drag to compare six tree meshes on the left with one impostor card on the right. Select 'nearest' to see view changes, larger with fewer views; blended and parallax smooth transitions, and the atlas highlights sampled views.
Distant models can spend thousands of triangles on a few pixels. An impostor draws a model as one camera-facing card, using captures nearest the viewing direction. It receives lighting, casts shadows and supports culling. Its drawing cost depends on covered pixels rather than model triangles.
Bakes a shape into the next free ranges in a compute pass. With encoder, it records there;
otherwise, it submits at once. Each shape needs its own pipeline, so add shapes while
loading. Throws when the pool is full.
Bakes a shape into the next free ranges in a compute pass. With encoder, it records there;
otherwise, it submits at once. Each shape needs its own pipeline, so add shapes while
loading. Throws when the pool is full.
Uploads each mesh into the next free ranges and decodes images in the background. Each image
decodes once per pool and format. The first skinned mesh allocates a joint-and-weight buffer
for the full vertex capacity. Throws if the pool is full, the model has no meshes, its
arrays disagree or encoded images have no decoder.
add(
import impostors
impostors.
constCARD:meshPool.ModelData<{}>
This model is the card every atlas draws on: add it to the pool once, with
pool.add(impostors.CARD).meshes[0], give the mesh to each create and instances of it to the
cards. Count it in the pool's room, as in meshPool.roomFor([horse, impostors.CARD]).
Creates an atlas that capture fills with views around subject. Each view stores textured
colour, coverage, normal and depth. A model is captured whole; a piece list places each mesh.
Back faces receive light from their side on double-sided meshes, and masked meshes apply their
alpha cutoff.
Capture after shape baking in the same encoder or an earlier submission. Wait for
model.ready to include model textures; otherwise, capture uses untextured factors. Invalid
view counts or sizes, empty subjects, meshes or a card from another pool, invalid poses and
excess texture layers throw.
@param ― pool the mesh pool that holds the subject and the card
@param ― subject a mesh, a model, or a list of pieces, each a mesh of pool
@returns ― an atlas you capture into an encoder and destroy
create(
constroot:TgpuRoot
root,
constpool:meshPool.MeshPool<{}>
pool,
[
{
Piece.mesh: meshPool.Mesh
Selects a mesh from the pool supplied to the capture.
mesh:
consttrunk:meshPool.Mesh
trunk,
Piece.position?: Triple |undefined
Sets the mesh origin in subject space. Default [0, 0, 0].
position:[0,0.9,0],
Piece.color?: Triple |undefined
Sets the mesh colour in linear colour space. Default the mesh material colour, which is
white for shapes.
color:[0.07,0.04,0.02]},
{
Piece.mesh: meshPool.Mesh
Selects a mesh from the pool supplied to the capture.
mesh:
constcrown:meshPool.Mesh
crown,
Piece.position?: Triple |undefined
Sets the mesh origin in subject space. Default [0, 0, 0].
position:[0,3,0],
Piece.color?: Triple |undefined
Sets the mesh colour in linear colour space. Default the mesh material colour, which is
white for shapes.
color:[0.11,0.23,0.02]},
],
{
Options.card: meshPool.Mesh
Selects the card mesh the atlas draws on: impostors.CARD added to the same pool. Atlases
share one card.
Records the subject bounds, captured views and atlas mipmaps into encoder. The atlas stays
blank until submission executes these commands. Capture again after poses or textures
change. Throws after destroy.
capture(
constloading:TgpuCommandEncoder
loading);
constloading:TgpuCommandEncoder
loading.
TgpuCommandEncoder.submit(): void
Finishes the recording and submits the resulting command buffer to the device queue
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
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.
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()).
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(
constrenderer:instances.Renderer
renderer);
const
constcast:passes.Drawn
cast=
constlight: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(+1overload)
Builds a caster's depth pipeline with the shadow's bias and returns its draw methods.
add(
constrenderer:instances.Renderer
renderer);
The renderer flushes, culls, casts shadows and draws like an instances renderer. Opaque impostors require pass descriptions with depth.
Capture a mesh, model or list of pieces. Each piece references a pool mesh with position, rotation, scale and a colour that multiplies its textures.
Every atlas draws on one card: add impostors.CARD to the pool once and give its mesh to each impostors.create, which allocates the atlas and pipelines. atlas.capture(encoder) records the bounding-sphere kernels, one pass per view and the atlas’s mipmaps. The atlas stays blank until you submit that encoder.
Views form a grid with views entries per side over the upper hemisphere. Use hemisphere: false to cover the whole sphere. Each view stores colour, coverage, normal and depth.
Captures preserve mesh rendering settings. Double-sided meshes show back faces lit from that side. Masked meshes keep their cutouts.
Capture after shape baking, either in the same encoder or after submitting the bake encoder. Await model.ready first to include textures. Recapture when the subject changes.
Creation throws if views is outside 2 to 16, size is not a power of two from 16 to 512, the subject has no meshes, or a mesh or the card belongs to another pool.
To capture animation, give a piece a pose from options.poses, a set of poses. An array of poses creates one atlas phase per pose. A row’s phase selects which to draw. The stampede captures six phases of a horse gallop:
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
Sizes a pool to hold exactly items: models such as impostors.CARD, their meshes, shapes, and
counts. Spread it into the options: meshPool.create(root, meshPool.roomFor([...])). It keeps a
second uv set when one of the meshes carries uvs1.
@param ― items what the pool will hold
@returns ― the capacity, vertices and indices they take, and uvs1: true when a mesh needs it
roomFor([
consthorse:gltf.ModelData<never>
horse,
import impostors
impostors.
constCARD:meshPool.ModelData<{}>
This model is the card every atlas draws on: add it to the pool once, with
pool.add(impostors.CARD).meshes[0], give the mesh to each create and instances of it to the
cards. Count it in the pool's room, as in meshPool.roomFor([horse, impostors.CARD]).
Uploads each mesh into the next free ranges and decodes images in the background. Each image
decodes once per pool and format. The first skinned mesh allocates a joint-and-weight buffer
for the full vertex capacity. Throws if the pool is full, the model has no meshes, its
arrays disagree or encoded images have no decoder.
Uploads each mesh into the next free ranges and decodes images in the background. Each image
decodes once per pool and format. The first skinned mesh allocates a joint-and-weight buffer
for the full vertex capacity. Throws if the pool is full, the model has no meshes, its
arrays disagree or encoded images have no decoder.
add(
import impostors
impostors.
constCARD:meshPool.ModelData<{}>
This model is the card every atlas draws on: add it to the pool once, with
pool.add(impostors.CARD).meshes[0], give the mesh to each create and instances of it to the
cards. Count it in the pool's room, as in meshPool.roomFor([horse, impostors.CARD]).
CARD).
Model.meshes: readonly meshPool.Mesh[]
meshes[0]!;
const
constgallop:poses.ClipData
gallop=
import poses
poses.
functionclip(file:{
readonly clips:readonlyposes.ClipData[];
},name:string):poses.ClipData
export clip
Returns the clip named name among a file's clips. Throws listing the names the file has.
@param ― file what gltf.read returns, or anything holding clips
Creates poses of skin that play named clips, for example { idle: general.clips[6], walk }. An entry that is an array of clips is a line, its clips sampled at one phase and mixed by
mix. It bakes clips at hz keys per second and blends between adjacent keys during playback.
Call animate each frame to compute joints in model space before drawing instances. The skin
must have 1 to 256 joints in parent-first order, with 16-float inverse binds. Invalid joint
data, capacity, bake rate, clips, lines of fewer than two clips, more than three layers, a layer
named base or a layer joint the skin lacks throw.
@param ― skin the joints, as gltf.read returns them in a model's skin
@param ― clips the clips and lines its poses play, by the names add and play take
@returns ― poses you animate every frame and destroy
create(
constroot:TgpuRoot
root,
consthorse:gltf.ModelData<never>
horse.
ModelData<never>.skin?:poses.SkinData|undefined
Provides the skin used by meshes in the default scene. When present, every mesh has joints
and weights. An unskinned mesh follows the joint it is attached to.
skin!,{
gallop:poses.ClipData| readonly poses.ClipData[]
gallop},{
Options<L extends string = string>.capacity: number
Limits the pose count to an integer from 1 to 65 535.
Adds a pose playing clip on its base from time on the clock passed to animate. Its
layers play nothing. Ignores layer, weight and fade. Throws if the set is full or the
clip was not supplied at creation.
add('gallop',0,{
Play<never>.from?: number |undefined
Sets the starting offset within the clip or cycle in seconds. Default 0.
from:(
constgallop:poses.ClipData
gallop.
ClipData.duration: number
Gives the time of the last key in seconds.
duration*
i: number
i)/6,
Play<never>.speed?: number |undefined
Scales playback speed. A value of 1 uses the original speed, 0 pauses and negative values
play backwards. Default 1.
Creates an atlas that capture fills with views around subject. Each view stores textured
colour, coverage, normal and depth. A model is captured whole; a piece list places each mesh.
Back faces receive light from their side on double-sided meshes, and masked meshes apply their
alpha cutoff.
Capture after shape baking in the same encoder or an earlier submission. Wait for
model.ready to include model textures; otherwise, capture uses untextured factors. Invalid
view counts or sizes, empty subjects, meshes or a card from another pool, invalid poses and
excess texture layers throw.
@param ― pool the mesh pool that holds the subject and the card
@param ― subject a mesh, a model, or a list of pieces, each a mesh of pool
@returns ― an atlas you capture into an encoder and destroy
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((
mesh:meshPool.Mesh
mesh)=>({
mesh:meshPool.Mesh
mesh,
pose:poses.Id[]
pose:
constphases:poses.Id[]
phases})),
{
Options.card: meshPool.Mesh
Selects the card mesh the atlas draws on: impostors.CARD added to the same pool. Atlases
share one card.
Uploads changes and computes every pose joint at time, with one workgroup per pose. Record
this once per frame in a compute pass before drawing, also while paused, so last frame's
joints stay one frame old.
animate(
constposing:TgpuComputePass
posing,0);// pose before capture in the same encoder
constposing:TgpuComputePass
posing.
TgpuComputePass.end(): void
Completes the recording of this compute pass
end();
constatlas:impostors.Atlas
atlas.
Atlas.capture(encoder: TgpuCommandEncoder): void
Records the subject bounds, captured views and atlas mipmaps into encoder. The atlas stays
blank until submission executes these commands. Capture again after poses or textures
change. Throws after destroy.
capture(
constloading:TgpuCommandEncoder
loading);
constloading:TgpuCommandEncoder
loading.
TgpuCommandEncoder.submit(): void
Finishes the recording and submits the resulting command buffer to the device queue
submit();
Capture bounds include posed vertices from every phase.
Poses must be live and meshes must have joints. All pose arrays must have the same nonzero length. A single pose or unposed piece repeats across phases.
The card faces the camera through the subject centre. Its bounds fit the projected subject box to reduce unused pixels.
Cards use instance fields. Row color multiplies atlas colour. Roughness, metallic and emission come from the row.
Each pixel shades at the captured subject point, so light, fog and shadows use that position. The shadow pass writes its depth 12 atlas texels farther from the light, so a card doesn’t shadow itself where its views disagree.
The kind’s coverage reads the captured coverage. With multisampling, coverage selects a fraction of pixel samples. Without it, pixels below half coverage are omitted.
Cards that overlap, such as a forest, draw best with prepass: true on their renderer: depth first, then each visible pixel shades once. With blend: 'translucent', one draw composites row opacity times captured coverage over the background without writing depth.
cull: true tests the sphere around the captured subject.
Use impostors.define to add kind fields and choose who writes transforms, as with instances.define. Device fields also include phase, indexed from 0. Values beyond the atlas phase count select the last phase. Kernels can move cards and select phases:
Defines an instance kind that draws an atlas with custom host and device fields. Its device
fields include a zero-based phase, initially 0. Values beyond the captured range select the
last phase. Inject the atlas into the renderer. Instance colour multiplies atlas colour;
roughness, metallic and emission control shading as for a mesh.
@param ― name a label for ids and WGSL, as table.define takes it
@returns ― a kind to give instances.create as kind
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
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.
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.
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:
constmove:TgpuComputeFn<{
gid:d.BuiltinGlobalInvocationId;
}>
move});
To read a simulation’s own buffer instead, give define a place that returns the card’s transform and a visible that hides a card in every pass, as for instances. The card faces the camera from that transform, and culling follows it.
Hover a horse to see its name, click it to follow, or click the ground for a thunderclap. Change the hand-off distance or tint cards to see where impostors replace skinned meshes.
The atlas has six gallop phases and four walk phases, each with 25 views at 64 texels. Each horse selects the phase matching its stride. Hovered and followed horses keep skinned meshes. Renderers cull horses outside the camera and sun views.
Destroy an unused atlas with atlas.destroy(). The card stays in the pool for other atlases. After destruction, capture and inject throw The atlas was destroyed.