When true, terrain G-buffer renders as line-list using lineIndexBuffer
instead of triangle-list. Affects indirect-args indexCount written by
update(). Shadow casters keep using triangles.
Procedural-generation feature flags packed into the page-gen uniform.
Bit 0 = erosion, bit 1 = plateaus/dunes. Toggle via setFeatureFlags.
World-generation seed (u32). Folded into the page-gen hash so each value
yields a completely different terrain pattern. Toggle via setSeed.
Bumped whenever the height or splat data is edited in place (brush strokes / undo). Derived consumers (foliage scattering) watch it and re-scatter once edits settle.
ReadonlygeomReadonlyshadowCamera-culled patch list (frustum + Hi-Z) — the G-buffer draw's source.
Indirect args for patchBufferVis.
Active quality preset, as passed to create().
Vertices per patch side (33 = Medium default).
Indices per patch triangle list — for callers building bind groups or draw calls without going through the indirect path.
Texels per VT page side (256 = Medium default).
The bound heightmap texture, or null while in procedural mode. Brush tools write edited regions into it directly.
The bound splat weight textures ([a, b]; either may be null).
World rect the bound heightmap maps onto (origin + extent).
CPU splat weight mirrors ([a, b]), when setSplatmap was given data.
Edit tools mutate these in place; scatterers read them.
The active region source, when the system streams tiled height data.
The CPU height mirror, when setHeightmap was given data.
Number of PBR material layers this system was created with.
True when a hole mask is bound — passes select their discard pipeline variants off this.
The bound hole mask texture, or null when none is set.
CPU hole mask mirror, when setHoleMask was given data. Edit tools
mutate it in place.
World rect the hole mask maps onto (origin + extent).
The bound control map texture, or null when mode 3 is not active.
CPU control-word mirror, when setControlMap was given data.
The bound color map texture, or null when none is set.
CPU color map mirror, when setColorMap was given data.
World rect the color map maps onto (origin + extent).
StaticcreateForce the VT residency to evict; next update() rebakes around the camera.
Re-bake the resident VT pages intersecting a world-space rect — the targeted refresh brush edits use after writing a heightmap/splat region. Pages keep their atlas slots (no residency churn); the bake re-dispatches on the next update. Non-resident pages bake on their normal streaming path when they come into range.
Normalized layer weights at a world XZ point (nearest texel), written
into out (length ≥ layerCount). Returns false without CPU splat data
or outside the splat rect — callers treat that as "base layer only".
Per-frame uniform upload + page streaming. Also resets the indirect args (the LOD compute pass bumps instance_count from zero each frame).
OptionalheightScale: numberFeed (or clear) the previous frame's Hi-Z pyramid for patch occlusion
culling in the LOD compute. Call before update each frame; the
caller keeps texture ownership. viewProj must be the view-projection
the pyramid's depth was rendered with. Pass null while no pyramid is
available (first frame, resize, feature off) — frustum culling still
runs.
Toggle erosion / plateau-dune features and trigger an immediate atlas rebake around the camera so the new formula is visible. No-op when both flags already match.
Swap to a different quality preset at runtime. Destroys and rebuilds the VT atlas, the page-gen / geom / shadow-geom bind groups, and the patch index buffers; resets page residency so the new atlas refills on the next frame. No-op when the requested quality already matches.
Pipelines and bind-group layouts are untouched — they describe binding shapes, not sizes, so they remain valid across the swap.
Safe to call between frames (e.g. from a UI handler). The first frame after the call shows the old atlas's last residency invalidated and the new atlas progressively baking around the camera, same as the initial startup pass.
Set the world-generation seed and rebake all resident pages. No-op when the seed already matches.
Switch the page-gen height source to a heightmap texture and rebake all
resident pages. The texture's R channel is read as normalized height in
[0, 1] and scaled by opts.heightScale (defaults to the current
heightScale); the page-gen normals are still derived from finite
differences of the sampled field, so they stay correct at page seams.
The texture must be sampleable as texture_2d<f32> with a filtering
sampler — r16float / rgba16float / rgba8unorm all work. The caller
keeps ownership; it is bound, not copied. Pair this with a small
worldExtent + bounded: true at create() for a self-contained island.
Switch back to procedural noise generation and rebake.
Switch the height source to a sparse streamed region grid (see
TerrainRegionSource), or back to procedural with null. The
source's ring is advanced inside update each frame; freshly
loaded/evicted regions re-bake the VT pages they overlap and refresh
those pages' culling bounds. heightAt/normalAt answer from the
source's resident CPU mirrors (floor height where nothing is loaded).
The caller keeps ownership of the source.
World-space terrain height at (x, z), or null when no CPU height data
is available (procedural mode, or setHeightmap without data). Points
outside the heightmap rect return the floor height, matching the page-gen
shader.
World-space terrain normal at (x, z) via central differences of
heightAt, or null without CPU height data.
Update one layer's style knobs (tint / metallic / uv repeat). Fields left undefined keep their current value.
Bind authored splat weight textures and switch layer blending to them.
a's RGBA channels weight layers 0-3, b's weight layers 4-7 (omit b
for ≤4 layers). Textures must be sampleable as texture_2d<f32>
(rgba8unorm is the expected format); the caller keeps ownership. The
procedural height/slope rule returns via clearSplatmap.
Optionalb: GPUTextureDetach the authored splatmap and return to procedural layer weights. The caller-supplied textures are not destroyed.
Bind a hole mask (r8unorm, texel ≥ 0.5 = hole) and enable fragment
discard in the raster + shadow passes. The caller keeps texture
ownership. Pass CPU data so holeAt (picker, foliage, physics)
tracks the mask. Note the physics collider and foliage caches are rebuilt
by their owners (they watch dataVersion/editVersion), not here.
Detach the hole mask; terrain renders solid again. The caller-supplied texture is not destroyed.
Bind a control-map splat source (r32uint, one packControlTexel
word per texel) and switch the layer blend to it: two layer taps per
texel regardless of palette size, per-texel uv rotation/scale detiling,
and a per-texel autoshader flag. The caller keeps texture ownership.
The map covers origin/extent (it replaces the weightmap rect).
Bind a painted color map (RGBA; rgb is an overlay multiplier centered at
0.5 — 0.5 gray = neutral, doubled in the shader — and A is the paint
opacity) sampled over its world rect on top of the layer albedo. The
caller keeps texture ownership. Pass CPU data so the editor's color
brush can paint into it.
Detach the color map (albedo renders untinted). The caller-supplied texture is not destroyed.
True when (x, z) falls in a hole (nearest texel of the CPU mirror). Always false without a mask or CPU data, or outside the mask rect.
Autoshader hybrid: where the authored splat weights sum to ~0, the procedural height/slope rule fills in (layers 0-3) instead of the base layer. Only meaningful with an authored splatmap bound.