Primary implementation surface
These routes are generated from canonical source. Their exact status remains separate from implementation availability.
Author scalable procedural planetary bodies in Three.js r185 native WebGPU/TSL with explicit cube-sphere/clipmap selection, conservative error-driven LOD, balanced transitions, shared causal fields, validated normals, instanced/indirect submission, and explicit atmosphere handoff.
These routes are generated from canonical source. Their exact status remains separate from implementation availability.
This skill contributes to the following cross-skill owner graphs.
The planet is a cube-sphere: six quadtree faces whose vertices project to the sphere, displaced by a height field composed of crater, mountain, and biome causes:
$$\mathbf p' = \hat{\mathbf p}\,\big(R + h(\hat{\mathbf p})\big)$$Quadtree LOD splits a patch when its projected screen error exceeds a threshold — geometric error over distance:
$$\tau = \frac{e_{patch}}{d}\cdot\frac{w_{screen}}{2\tan(\phi/2)} > \tau_{max} \Rightarrow \text{split}$$Normals come analytically from the height gradient in the tangent frame rather than post-hoc geometry differencing: $\mathbf n \propto \hat{\mathbf p} - \nabla_{\!s} h$, keeping shading stable across LOD seams. Craters are radial profiles $h_c(r) = f(r/r_c)$ with rim uplift and floor flattening, summed with amplitude-sorted dominance so overlaps read as impact history.
Every image identifies what it proves. Page screenshots demonstrate the published presentation only; generated inputs demonstrate asset channels only; canonical acceptance still requires render-target readback and a schema-v2 bundle.
4 published images
generated asset preview
generated asset preview
generated asset preview
generated asset preview
The complete SKILL.md as loaded by agents — verbatim, rendered.
Build a planet from an explicit surface-mapping and LOD decision, not a fixed recipe. The default globe/orbit path is a streaming cube-sphere quadtree with 2:1-balanced neighbors, continuous LOD morphing, and instanced/indirect patch submission. A local tangent geometry clipmap can own sustained ground-scale views; a hybrid hands it to the global quadtree. The same planet-space causes must drive geometry, normals, material identity, scientific/query outputs, diagnostics, and atmosphere handoff.
Any planet output consumed by dynamics, contact, navigation, water, weather,
or another physics domain must use the route's
physics-domain and interaction contract.
Publish typed PhysicsSignalDescriptor records bound to the active
PhysicsContext through the canonical IDs, physics frame/origin epoch,
transform/chart, clockId/samplePhase, channels, represented-footprint/
filter, validity/perChannelError, residency/cadence/latency, state/resource
version, and missing-channel envelope. Every PhysicsSampleRequest and
returned SampledChannel.actualPhysicsTime, including static/analytic results,
carries a direct canonical PhysicsInstant | PhysicsTimeInterval, never the
generic PhysicsTime wrapper; time is not an extra descriptor field. A
quadtree tile, render LOD, TSL function, or cache texture is never the public
physics ABI.
The planet/body-field owner is the sole state-equation owner for its
physics-facing body, gravity, static coast/bathymetry, and hydrology-analysis
revisions. Its PhysicsGraph stages write provisional versions; exactly one
all-or-none PhysicsCommitGroup publishes each accepted revision with
CommitPublicationLineage. A project coordinator may commit those prepared
versions atomically but never becomes a second owner. Do not expose a new
descriptor revision before that commit appears in PhysicsExecutionLedger.
When committed state is rendered, publish the immutable
PhysicsPresentationCandidate -> CameraViewPublication -> ViewPreparationPublication -> PhysicsPresentationSnapshot -> FrameExecutionRecord chain. The candidate stays view-independent; field
bindings carry independent previous/current provenance and leased state
handles. Camera publication owns render mapping, view preparation owns per-view
LOD/caches/shadows/resets, and the sealed snapshot references binding IDs and
leases rather than copying state or transforms. Never mutate an earlier record
to report a later phase or completion.
Treat cube-face UV, longitude/latitude, geodetic coordinates, and tangent
parameterizations as nonlinear charts, not Cartesian frames. Publish their
metric/Jacobian, domain/seam validity, and chart version; express physical
vectors in a declared orthonormal body/world frame.
When dynamics need gravity, publish a point/time vector signal in m s^-2;
never substitute world -Y, radial up, or a normalized surface normal.
Do not load this skill merely because a scene contains islands. A bounded
archipelago, coastal site, bathymetric model, or isometric land tile whose
planetary curvature, horizon, global geodesy, and orbit-to-ground transition are
outside the visual/error contract belongs to $threejs-procedural-fields plus
$threejs-procedural-geometry, with $threejs-procedural-materials and the
appropriate water skill as consumers. Use this skill only when the body-scale
surface map, curvature, global LOD, georeference, or atmosphere handoff is an
observable cause.
Canonical implementation contract: examples/webgpu-quadtree-planet/.
Run node examples/webgpu-quadtree-planet/validate-planet.mjs after edits.
Legacy WebGL implementation (deprecated, do not extend): examples/procedural-planet-surface/planet-system.js and examples/procedural-planet-surface/terrain-field.js.
WebGPURenderer from three/webgpu, MeshStandardNodeMaterial or
MeshPhysicalNodeMaterial, and TSL from three/tsl.J_center/J_corner = 3*sqrt(3) ~= 5.196; uniform UV
sampling is therefore about 5.196 times denser at a corner. Never call it
uniform. Represent global bodies as six 2:1-balanced face quadtrees with
stable edge/corner ownership and conservative displaced bounds.surfaceDirection from face/patch/grid metadata. Preserve
it separately from displaced position. Validated mapping derivatives feed
projected error and normals. Apply the shared
physical-pixel projected-error contract
to the complete displaced patch support and every active view; altitude or
patch-center distance alone is not an LOD metric.Fn field functions for displacement, material causes,
gradients, queries, and diagnostics. Compute-baked and direct dynamic paths
call the same functions; render nodes may sample their versioned cache
outputs instead of reevaluating them. Do not maintain duplicate field math.
Parity-bearing value-noise corners use the lowbias32-u32-lattice integer
hash family: its multipliers/shifts are an [Authored identity], not a
quality claim. CPU uses Math.imul/>>> 0 wrapping, and TSL uses uint
arithmetic plus the exact same identity constants. Do not use
transcendental hashes for CPU/GPU parity paths.StorageBufferAttribute, StorageInstancedBufferAttribute, and r185
IndirectStorageBufferAttribute/BufferGeometry.setIndirect() where the
target supports the selected indirect command contract. Do not use float
atomics for min/max; reduce floats in workgroup memory or use a proven
ordered-integer encoding.PhysicsSignalDescriptor; the descriptor's analysis revision and error
bounds, not the visible patch level, determine whether a consumer may use it.
The environment/project coordinator publishes the immutable
EnvironmentForcingSnapshot. Planet fields consume its exact committed
version through graph edges; they do not synthesize a second weather state.
$threejs-rain-snow-and-wet-surfaces owns precipitation transport and
receiver-side deposition/splash/ripple/wetness/snow effects, not
meteorological generation.metersPerWorldUnit, surface altitude, and radiometric basis to
$threejs-sky-atmosphere-and-haze.RenderPipeline with node passes for the final stack. Prefer built-in
TRAANode, GTAONode, BloomNode, CSMShadowNode, and TileShadowNode
when they cover the need; custom nodes must beat or extend them. Default to
output-only mrt({ output }); allocate normal, velocity, emissive, or other
attachments only for implemented consumers with measured full-frame cost.Cache-tile gutters are not fixed. Derive the source-support radius from maximum domain-warp displacement plus the largest reconstruction, derivative-stencil, and projected anisotropic-footprint radius, then map the gutter through cross-face ownership.
Submission is part of the algorithm: one indexed grid is reused for every patch at a given topology. Bin visible patches by the four-bit transition-edge mask and submit at most one instanced/indirect draw per non-empty mask/material group. One draw per patch is a diagnostic implementation, not the production mobile architecture.
Read references/planet-field-and-atmosphere-systems.md for the complete field contract, quadtree LOD policy, parity harness, crater model, material assembly, atmosphere handoff, diagnostics, and performance budgets.
Initialize the renderer before allocating compute or storage resources:
await renderer.init();
if ( renderer.backend.isWebGPUBackend !== true ) {
throw new Error( "threejs-procedural-planets requires a native WebGPU backend" );
}
Any change to physics state/equations, native cadence or coupling, represented
band/footprint/filter, physical error bound, conserved inventory, stable-ID/RNG/
event policy, or physics residency is an exact QualityTransition, not render
LOD. Declare source/destination PhysicsQualityStateDescriptors; prepare
without publication; commit a gated ConservativeStateMap, inventory and
ID/RNG/event-cursor mappings atomically at a step boundary; increment the
quality epoch; and retain the old leases until the declared completion join.
Reject the transition when no conservative/error-bounded map exists.
Numeric labels: [Derived] follows from equations/representation; [Gated] is an acceptance bound; [Measured] names target evidence; [Authored] is a starting visual/quality choice.
The following are [Authored] workload trials, not device classes, budgets, or measured claims:
| Trial | Shared grid side | Active patches | Dirty compute policy |
|---|---|---|---|
| full-detail | [Authored] 33-65 | [Authored] 120-480 | [Authored] 1-4 dispatches/update |
| budgeted | [Authored] 17-33 | [Authored] 80-240 | [Authored] 0-2 dispatches/update |
| minimum-resident | [Authored] 17-33 | [Authored] 48-160 | [Authored] 0-1 amortized dispatch/update |
Keep the far field static. Rebuild only newly visible/dirty patch tiles,
body-identity changes, or LOD-frontier crossings. Report the [Derived]
triangle count activePatches * 2 * (gridSide - 1)^2, cache bytes, indirect
bytes, field evaluations, and overdraw; active-patch count alone hides cost.
The [Derived] upper bound is 16 transition-mask draws per body/material
group, not a universal scene draw budget. The product declares full-frame GPU,
CPU-submit, presented-frame p95, and peak-live-byte budgets, then validates the
compiled scene. Avoid runtime CPU readback; parity readback belongs to
validation.
SRGBColorSpace. Calibrated reflectance,
radiance, elevation, or spectral datasets retain their declared linear/data
encoding; do not relabel them sRGB because they look like color.NoColorSpace/linear data.HalfFloatType until the single tone-map owner.RenderPipeline.outputColorTransform or an explicit renderOutput() node.
Materials and effects must not double-convert.normalize(cube) is equal-area, and do not select an
equal-area mapping without Jacobian and inverse/seam tests.PhysicsContext, body/world frame, origin
epoch, analysis revision, validity, footprint, or error bound does not match;
never convert a missing or ambiguous planet sample to a plausible zero.physicsOriginEpoch, body-field
source/state revision, stable identity, or SI values.Validate at fixed cameras and [Authored] at least three seeds:
PhysicsGraph stage/edge/execution rows, commit-group atomicity, and
publication lineage for every physics-facing body/gravity/coast/hydrology
revision;$threejs-sky-atmosphere-and-haze.Use $threejs-choose-skills for multi-system preflight when planets are part of
a larger scene. Local islands and coastal scenes without observable planetary
curvature/global LOD route to $threejs-procedural-fields and
$threejs-procedural-geometry, not here. Use $threejs-procedural-fields for reusable field bundles
without a complete body, $threejs-procedural-materials for standalone
material authoring, $threejs-ambient-contact-shading for custom GTAO
work beyond the built-in node, $threejs-scalable-real-time-shadows for
large-world shadow policy, $threejs-image-pipeline for shared gbuffer,
velocity, and output ownership, $threejs-visual-validation for screenshot
and GPU proof, $threejs-exposure-color-grading for metering and tone-map
ownership, $threejs-water-optics for water volume optics, $threejs-volumetric-clouds
for cloud volumes, $threejs-rain-snow-and-wet-surfaces for precipitation
transport and receiver effects, and $threejs-sky-atmosphere-and-haze for scattering
independent of planet generation. This skill owns the coupled planetary surface
and its LOD/parity architecture. For a planetary ocean, it owns the static
reference surface, coastline, bathymetry, seabed classes, and their error
metadata; the water skill owns the time-varying free surface, flow/wave state,
foam, and optics. The environment/project coordinator owns the shared
EnvironmentForcingSnapshot; neither the planet nor rain skill independently
generates meteorology.
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.