Threejs procedural vegetation
Skill linegel/threejs-complete-set-of-skill/skills/threejs-procedural-vegetation
25 expert agent skills for ambitious Three.js WebGPU/TSL scenes — procedural oceans, clouds, planets, water optics, image pipelines, and screenshot-backed visual validation. For Claude Code, Codex, Cursor, and any skill-aware agent.
npx -y skills add linegel/threejs-complete-set-of-skill --skill threejs-procedural-vegetationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
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.
SKILL.md
10.2 KB, as published. Nobody here has run it
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
- Partition the domain into deterministic chunks with global IDs, fixed seeds,
half-open ownership, conservative deformed bounds, and a visible bounds/LOD
diagnostic.
A world-anchored record identity is
(generatorSchemaVersion, globalSeedWords, stableSpeciesIdWords, biasedWorldCellWords, candidateOrdinal). A hash is only a compact label, priority, or random lane; full-tuple equality owns identity and resolves hash collisions. A species or functional-group ID is immutable rather than its position in a registry. Adding another population family or changing chunk traversal cannot renumber existing records. - 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. - 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.
- 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.
- 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
MeshStandardNodeMaterialfor grass and bark; useMeshPhysicalNodeMaterialwhen leaf transmission/wax response is required. - Use
alphaTestoralphaHashfor foliage.forceSinglePassis 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.