Builtin Library
- ..
- README.md3.7 KB
- bindings.yaml1.8 KB
- shader.wgsl13.2 KB
README.md
terrain_layer_weights
Evaluates a material layer stack's rules into two RGBA weight textures — layers 0-3 in one, 4-7 in the other, with the eight shares at a texel summing to one.
One thread per destination weight texel. The dispatch is per tile: a tile writes the texels whose centres fall inside its interior, reading the field through its own apron-inclusive buffer. Because every read is placed from the field minimum and the texel size in world metres — never from the tile's own origin — the texels one tile writes agree exactly with its neighbour's along the seam.
The six inputs
| input | unit | where it comes from |
|---|---|---|
height | metres, world Y | the height channel, bilinear |
slope | degrees, 0 flat / 90 vertical | central difference of height over gradientStep metres |
curvature | 1/metres, + gully / − ridge | Laplacian of height, magnitude ≈ 1/radius |
mask | 0..1 | a bound mask.<name> channel, bilinear |
noise | 0..1 | terrain_fbm's gradient noise over world position |
channel | the channel's own stored values | any bound field channel, bilinear |
slope and curvature are derived here rather than stored, so they cost no
channel and can never fall behind the ground they describe.
mask and channel both read a named channel through the same four slots and
the same bilinear tap; they differ in what the band is written against. A mask
channel holds 0..1, so its band is in that range. A channel band is in the
values the channel stores — cubic metres of deposited sediment, metres of water
depth, whatever the op that wrote it produces — with no rescaling on the way in.
That is what lets a layer put sand where the water actually dropped it and wet
shore where water actually stands.
A rule is a band, whatever it reads
Every rule carries min, max, softness and jitter in the unit of its own
input. A layer covers the ground by its strength times the product of its
rules; a layer with no rules covers unconditionally. invert takes the
complement of the band, which is how "anywhere but here" is written.
softness is a feather half-width and jitter is how far noise is allowed to
move the value before it is banded — metres on a height rule, degrees on a slope
rule. Each rule draws its jitter from its own noise offset, so two rules on one
layer do not wander in step.
The layers are a stack
Working from the top down, each layer takes its coverage share of whatever is still showing. A cliff rule that fully passes therefore leaves nothing of the grass under it, a layer at half coverage lets half the layer below through, and whatever no layer claimed goes to layer 0 — the ground the stack stands on. The eight shares add to one by construction, with nothing divided by a sum, and an unclaimed texel is a surface rather than a hole.
Rules are numbered bottom-up across the whole stack and each layer reads its own range of them, so covering downward moves no rule's noise offset.
Bindings
params carries the whole stack: four head lanes, eight layer lanes, then three
lanes per rule. height is the field's height tile. chan0..chan3 are the
field channels the stack's rules name, in sorted order — a slot no rule reads is
bound to the height tile and never sampled. Four is what the kernel declares; a
compute stage carries eight storage buffers and params and height take two,
so six is the ceiling a stack could be given.
weightsLo and weightsHi are rgba8 storage targets, which is the widest
format a material slot can sample: a material reads every slot through a
filtering sampler, and the 32-bit float formats are not filterable.