Procedural Vegetation

Compile procedural vegetation for Three.js WebGPU/TSL. Use for dense grass and ground-cover populations, structured tree growth and rooted wind, or terrain-aware ecological placement.

Image: final design. Source lab: structured-ash-growth.

$threejs-procedural-vegetation 3 primary targets 2 flagships 1 secondary surface accepted runtime evidence Latest skill update commit 2ce13bc ↗ SKILL.md on GitHub ↗ raw (for agents) ↗

Evidence reports

Source hashes, claim verdicts, promoted same-lab media, fixed routes, exact tier contracts, and current limitations.

The approach, mathematically

Trees grow by recursive branching with authored distributions: each child branch takes a fraction of parent length and radius following the pipe-model area law:

$$r_{parent}^{\,\eta} = \sum_i r_{child,i}^{\,\eta}, \qquad \eta \approx 2\text{–}3$$

Wind is rooted: displacement grows from anchor to tip so plants bend instead of sliding. A branch point at normalized height $u$ sways as

$$\Delta \mathbf x(u, t) = u^2\, A\, \big(\sin(\omega t + \phi_{plant}) + n(t)\big)\,\hat{\mathbf w}$$

with per-plant phase from a position hash so a meadow never moves in lockstep. Grass runs as compute-updated instances; chunked LOD swaps blade geometry for cards by distance band, with the density field shared between placement (CPU) and shading (GPU) under the field-parity contract.

Accepted primary labs

Only schema-v2 labs with accepted runtime and evidence contracts appear here. Other source directories remain visible through the demo registry without being promoted to runnable proof.

Preview and evidence ledger

Every image identifies what it proves. Page screenshots demonstrate the published presentation only; generated inputs demonstrate asset channels only; rendering acceptance still requires same-lab readback and a schema-v2 bundle.

Accepted runtime evidence available30 published images
Native WebGPU runtime evidence preview

Native WebGPU Structured Ash Growth

Accepted
visualCorrectness
PASS
mechanismCorrectness
PASS
performanceCompliance
NOT_CLAIMED
gpuAttribution
NOT_CLAIMED
lifecycleStability
PASS
visualError
PASS
  • Performance and GPU attribution remain NOT_CLAIMED without named-hardware timestamps.
  • Evidence captures were produced from the live lab browserEntry demo surface.
Native WebGPU runtime evidence preview

Native WebGPU Dense Grass

Accepted
visualCorrectness
INSUFFICIENT_EVIDENCE
mechanismCorrectness
PASS
performanceCompliance
NOT_CLAIMED
gpuAttribution
NOT_CLAIMED
lifecycleStability
PASS
visualError
PASS
  • Performance and GPU attribution remain NOT_CLAIMED unless a hardware performance lane is present.
  • Promoted media are native-WebGPU correctness readbacks bound by the accepted release-bundle ledger.
Native WebGPU runtime evidence preview

Host-Owned Planet, Terrain, Dense Grass, and Ash Integration

Accepted
visualCorrectness
PASS
mechanismCorrectness
PASS
performanceCompliance
NOT_CLAIMED
gpuAttribution
NOT_CLAIMED
lifecycleStability
PASS
visualError
PASS
  • Performance and GPU attribution remain NOT_CLAIMED unless a hardware performance lane is present.
  • Promoted media are native-WebGPU correctness readbacks bound by the accepted release-bundle ledger.

The full skill

The complete SKILL.md as loaded by agents, rendered verbatim.

Procedural Vegetation

Build vegetation as a compiler: stable environmental causes become immutable placement/topology records, while wind and interaction remain separately owned dynamic state. The canonical path uses Three.js r185 WebGPURenderer, TSL, NodeMaterial, and workload-selected compute/storage.

1. Define the observable and owners

Classify every requested result before selecting APIs:

Branch Requested observable Vegetation owns
dense population grass, flowers, ground cover, repeated shrubs/trees placement identity, pages, representations, deformation bindings
tree growth trunks, roots, branches, foliage, rooted wind growth hierarchy, geometry, structural response, LOD
terrain ecology populations caused by terrain or site fields species response, candidate conflicts, stable acceptance

Name the coordinate frame, world unit, characteristic plant scale, target cameras/extents, update frequency, output owner, and external field owners. Terrain, weather, water, contact, and lighting remain with their routed owners; vegetation consumes versioned samples from them.

This step is complete when every requested observable has one owner and every external input names its producer, units, frame/chart, support/filter, revision, validity, error, and update cadence.

2. Select representations by population and projected error

Workload Default representation
one or a few close trees CPU/worker growth compile into indexed buffers
repeated trees or shrubs compatible species variants instanced in spatial pages, then geometry LOD and impostors
dense grass or ground cover shared strip/clump geometry with implicit, compact CPU, or storage-backed placement
changing placement or topology compute only the changing records, followed by bounded compaction

Choose compute from measured changed-data volume, dispatch cost, traffic, and residency. Static CPU-generated vegetation can be the lowest-cost GPU result. For every near/mid/far range, record the representation, transition error, expanded bound, shadow proxy, static bytes, dynamic bytes, and submitted work.

This step is complete when each visible range has exactly one primary representation and every transition has an unjittered physical-pixel error gate, hysteresis/dwell, and simultaneous-memory budget.

3. Compile the selected branch

Dense populations

  1. Partition the domain into deterministic chunks with global IDs, fixed seeds, half-open ownership, conservative deformed bounds, and a visible bounds/LOD diagnostic.
  2. Compare implicit reconstruction, clump records, compact CPU attributes, and storage records. Count the actual aligned stride, duplicate LOD data, and hot vertex reads. In r185, computeAsync() waits for initialization before enqueue; it is not evidence that GPU work has completed.
  3. Keep placement and species identity immutable after spawn. Derive safe variation from stable integer hashes; update only wind, touch, wetness, snow, or other selected dynamic fields.
  4. Cull by spatial page before draw submission. Use near geometry, mid nested density thinning, and far cluster/impostor representations. A visibility mask that still submits every vertex is an appearance mask, not culling.
  5. Expand each page bound by terrain displacement, plant height, and maximum active deformation. Display, shadow, and picking consume that same bound.

Dense compilation is complete when equal inputs reproduce equal IDs, chunk order cannot change owned plants, placement bytes and dynamic bytes are separate, and invisible pages cease contributing submitted geometry.

Terrain ecology

When terrain, substrate, exposure, water, disturbance, light, or site assets affect placement, read terrain-ecology-and-placement.md. Apply hard eligibility before suitability, then select either Matérn-II/local maximum or global priority-greedy semantics explicitly. Preserve chunk halos, stable winner keys, and nested LOD thinning ranks exactly as that reference defines them.

Ecology compilation is complete when every accepted plant resolves its field revisions, eligibility, response factors, candidate/winner identity, asset, and chunk owner; exclusions and seam checks have zero violations.

Structured trees

When generating trunks, branches, roots, leaves, or hierarchical wind, read tree-growth-and-wind.md. Compile an iterative growth hierarchy with rotation-minimizing frames, explicit twist, species allometry, validated junctions, arc-length bark UVs, stable leaf bases, and shared display/shadow deformation.

Tree compilation is complete when the queue terminates inside declared budgets, all branch IDs are unique, frames and junctions pass their continuity/mesh gates, and foliage roots, normals, UVs, and bounds are finite and reproducible.

4. Bind dynamic state and handoffs

When wind, water, weather, contacts, loading, or another simulation owner feeds vegetation, define a handoff with units, frame/origin, interval or sample instant, cadence/sample phase, producer/consumer/version, footprint/filter, validity/staleness/error, and rate-versus-integrated semantics.

Vegetation owns structural response: root constraints, analytic bend or modal state, leaf flutter, touch/load state, bounds, and LOD projection. It does not own the air/water/contact cause. Recurrent state advances at a fixed step or at the routed simulation stage; render samples immutable previous/current states for one stable plant/page identity. Presentation transforms those states into the current view without mutating placement.

One-way visual deformation consumes a source and returns no physical reaction. A two-way route sends reactions through the authoritative solver named by the handoff. GPU-resident state remains GPU-resident through frame-critical work; CPU decisions use an analytic mirror, compact dirty ranges, or conservative bounds with declared age/error.

This step is complete when each dynamic field has one state owner, a precise sample/application time, a stable identity/version, a bounded update domain, and an explicit reset rule for creation, removal, teleport, slot reuse, topology change, LOD discontinuity, provider discontinuity, and resize.

5. Render and present once

Initialize before allocating WebGPU resources:

import { WebGPURenderer } from 'three/webgpu';

const renderer = new WebGPURenderer({ antialias: false });
await renderer.init();
if (renderer.backend.isWebGPUBackend !== true) {
  throw new Error('WebGPU backend unavailable for the canonical vegetation path.');
}
  • Use MeshStandardNodeMaterial for grass and bark; use MeshPhysicalNodeMaterial when leaf transmission/wax response is required.
  • Use alphaTest or alphaHash for foliage. forceSinglePass is appropriate when a validated double-sided card does not need separate back-face lighting.
  • Decode color/albedo as sRGB. Normal, roughness, density, alpha, wind, LUT, and other data fields remain linear/NoColorSpace.
  • Keep leaf/grass roots fixed in the position function. Reuse that function for visible and cast-shadow geometry.
  • Cull and reduce geometry/alpha coverage before adding AO, bloom, or temporal filtering. Request only MRT signals a consumer uses.
  • Keep HDR buffers linear until the one tone-map/output-conversion owner presents the frame.

This step is complete when visible, shadow, depth, and motion paths resolve the same plant identity and deformation state, all colors/data use the declared spaces, and exactly one component owns tone mapping and output conversion.

6. Verify causes, cost, and lifecycle

Inspect final/no-post output plus branch-specific diagnostics:

dense: chunk bounds, submitted pages, density rank, LOD/impostor state,
       static versus dynamic storage, projected alpha layers
ecology: input fields, exclusions, response factors, candidate conflicts,
         chunk halo/ownership, accepted and rejected causes
trees: branch levels/frames/junctions, bark UVs, leaf roots/normals,
       wind displacement, swept bounds, shadow parity

Record visible/submitted pages and instances, rejected-but-processed vertices, mean/p95 alpha layers, shadowed work, aligned storage bytes, dynamic-field traffic/cadence, compile/update time, whole-frame and paired-marginal CPU/GPU p50/p95, peak live bytes, and sustained target behaviour.

Exercise fixed-seed replay, changed chunk order, camera traversal, LOD transitions, wind/contact impulses, provider discontinuity, resize, slot reuse, and disposal. Failure signatures include habitat moving with render LOD, species changes from seed variation, roots drifting, frame helices, flat card normals, placement regenerating per frame, offscreen pages dominating submission, shadow deformation diverging, or resources/state surviving their owner's disposal.

Verification is complete when every selected branch passes its causal, determinism, geometry, transition, output, budget, reset, and disposal checks; unselected branches require no payload or evidence.

Routing boundary

Use $threejs-procedural-fields for shared environmental fields, $threejs-procedural-geometry for generic mesh emission, $threejs-procedural-materials for reusable PBR identities, $threejs-scalable-real-time-shadows for custom shadow systems, and $threejs-image-pipeline for final HDR/post/output ownership. This skill owns vegetation placement, growth topology, foliage, population representations, and rooted structural response.

Secondary provider surfaces

Preserved concept proxies and generated-asset previews. They are excluded from primary completion counts and link to the canonical lab through the schema-v2 registry.