Live concept-proxy screenshot · not canonical evidence

Procedural Buildings and Cities

Build authored procedural buildings, facades, cities, and semantic site-asset assemblies in Three.js r185 WebGPU/TSL. Use for massing grammars and for deterministic placement/compilation of supplied or separately generated ruin, dock, boat, rock, vegetation, and prop families; anchors, sockets, exclusions, exposed-edge analysis, profiles, ornaments, material-slot BatchedMesh or merged BufferGeometry, stable IDs, NodeMaterial identities, spatial paging, LOD, and asset-manifest validation.

$threejs-procedural-buildings-and-cities 1 primary implementation 1 flagship 1 secondary surface native evidence pending Latest skill update commit 9077075 ↗ SKILL.md on GitHub ↗ raw (for agents) ↗

The approach, mathematically

Buildings compile from a massing grammar: boxes join into a footprint, exposed-edge analysis decides where facades, cornices, and trims may exist. Facade subdivision solves an integer bay-count problem per wall:

$$n_{bays} = \operatorname{round}\!\left(\frac{W - 2m}{w_{bay}}\right), \qquad w' = \frac{W - 2m}{n_{bays}}$$

so openings stay near their authored width while filling the wall exactly. Ornament profiles are 2D polylines lofted along edges; arches parameterize as circular or elliptic segments $y = r\sin\theta$ over the opening span. Determinism is a contract: every variant derives from a seed through hash chains $s_{child} = H(s_{parent}, \text{tag})$, so a city block regenerates identically. Output compiles into material-slot batches — facade, glass, trim, roof — for a handful of draw calls per district.

Preview and evidence ledger

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.

Canonical runtime evidence pending1 published image

The full skill

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

Procedural Buildings and Cities

Choose the compiler package before emission: a deterministic grammar produces a validated plan, then emits material-slot BatchedMesh containers or merged indexed BufferGeometry per building/chunk. Do not start from per-primitive scene objects and try to recover semantics later.

Use the pinned Three.js r185 with WebGPURenderer from three/webgpu, TSL from three/tsl, MeshStandardNodeMaterial / MeshPhysicalNodeMaterial material identities, node post through RenderPipeline, and storage/compute APIs only where they beat CPU chunking for city-scale state. Built-in node effects are the first revision-matched comparison baseline; retain them only when their measured quality and cost pass the workload contract.

Required Build Order

settings + seed
  -> mass grammar
  -> plan validation
  -> exposed-surface graph
  -> facade / roof / trim placements
  -> module registry validation
  -> per-material-slot mesh compilation
  -> one compiled building object or chunk batch
  -> WebGPU/TSL materials and node pipeline integration

Read references/grammar-and-mesh-compiler.md before implementing the generator.

For generated terrain, islands, coasts, ruins, docks, boats, rocks, pebbles, flowers, or small scene assemblies, also read references/semantic-site-asset-kits.md. When any asset supplies collision, support, rigid-body, hydrostatic, structural, or interaction semantics, also apply the shared physics-domain and interaction contract.

Legacy implementation (deprecated, do not extend): examples/authored-financial-tower/.

Architecture Rules

  • Keep grammar, validation, placement, and mesh emission as separate phases.
  • Resolve exposed edges before facade placement. Do not decorate hidden internal faces.
  • Treat exposed-edge analysis as trim and ornament authority: cornices, corner joints, parapets, pilasters, plinths, and roof ownership follow surviving intervals, not whole-tier rectangles.
  • Modules own semantic anchors, local frames, construction depth, UV density, and material slots; they do not own global side orientation.
  • Compile by material slot. The default output is one compiled building object with stable slot membership, not an InstancedMesh soup of primitive boxes.
  • Use BatchedMesh when many local module geometries share one material and still need per-part visibility, transforms, sorting, or replacement. Use a merged indexed BufferGeometry per slot when the building is static and only chunk-level culling is needed.
  • In installed r185 WebGPU, BatchedMesh loops one backend draw item per visible multi-draw entry; it reduces scene-object/state management but does not prove draw-call collapse. Merge compatible static slot geometry or instance identical topology when fewer GPU draw items are required, and record actual renderer/backend counts.
  • Use InstancedMesh only for large counts of identical repeated objects whose unique geometry count is small and whose per-instance identity is meaningful. It is not the default compiler architecture for authored facades.
  • Preserve real dimensions for floor height, bay width, trim projection, tile scale, and texture density.
  • Randomness may select among valid designs; it must not repair invalid geometry.
  • Provide topology, exposed-edge, placement, ownership, material-slot, UV density, bounds, draw-call, and triangle diagnostics.

Semantic Site And Coastal Asset Kits

Use the same plan-before-emission architecture for small site assets. The site plan consumes versioned terrain/coast fields plus a registry of semantic asset manifests; it emits placements with stable IDs, explicit anchors, support and exclusion volumes, material slots, LOD representations, and diagnostics. It does not infer meaning from arbitrary mesh bounds after placement.

Physics-facing manifests additionally publish stable ColliderProxy and, when needed, DeformingSupportProxy IDs; PhysicsMaterialId bindings; provider IDs; and versioned RigidBodyProperties or HydrostaticHullProperties. These proxy identities and body properties are independent of render LOD, batching, and runtime instance index. A display hull, building mesh, or bounding box is not a collision, structural, buoyancy, or drag model.

Dynamic transforms publish RigidBodyState and view-independent PresentedStatePair bindings with independent previous/current provenance and leases. Cameras own render mapping through CameraViewPublication; per-view LOD, visibility, shadows, caches, and resets belong to ViewPreparationPublication. A sealed snapshot references candidate binding IDs and leases, and multi-target FrameExecutionRecord entries retire those leases only after every consumer completes.

Required reference families must resolve to a licensed compact asset kit or a tested procedural module/generator. A missing ruin, dock, boat, rock/reef, vegetation, cloud-silhouette, or other identity-bearing family is a blocker, not permission to fabricate boxes, billboard blobs, or unrelated noise.

environment snapshot + seed + authored anchors
  -> candidate/support regions
  -> constraint and clearance validation
  -> deterministic asset/variant selection
  -> semantic placements and adjacency/attachment graph
  -> per-material/per-representation compilation
  -> serialized site plan + runtime package

Place required landmarks and their reservations first, then dependent supports/attachments, then ecology, then optional filler clusters or decals. Every streamed phase uses stable candidate sorting and a conflict/filter halo; generation or chunk load order must not alter owned placements.

Required environment inputs declare units, sign, coordinate frame, filtering, revision, and missing-data behavior for terrain elevation/normal/slope, substrate and semantic regions, signed coast distance and coast frame, still-water depth or bathymetry where relevant, exposure, paths, and authored exclusions. Site assets consume dynamic water/motion hooks but do not solve them.

Asset family Required semantic contract Causal owner outside this compiler
ruin/wall/foundation module graph, corners/openings, support footprint, collapse state, material slots, vegetation sockets low-level profiles/mesh writers route to geometry; materials route to procedural materials
dock/pier/bridge land root, coast tangent/outward normal, deck datum, pile/bed contacts, berth/mooring frames, clearance prism water surface/depth from water; optional motion from motion systems
boat/floating prop hull/waterline frame, conservative swept bound, berth/free-water mode, material slots, RigidBodyProperties, HydrostaticHullProperties, stable collider/support proxy and wake/interaction emitter metadata buoyancy/wave/current state from water or domain solver; transform motion from motion systems
rock/boulder/pebble/debris ground/embed anchor, support normal policy, footprint, cluster group, substrate/coast eligibility topology from procedural geometry; PBR identity from procedural materials
flower/grass/shrub/tree root anchor, ecology/species response, crown/wind bounds, clearance, growth/LOD package placement/growth/wind from procedural vegetation

Do not promote each pebble, flower, plank, or rubble fragment to a scene object. Compile immutable identical topology through spatially paged instancing; merge compatible static unique pieces by material slot; retain BatchedMesh only when replacement, per-part visibility, or identity justifies its measured r185 multi-draw entries. Authored landmark assets preserve individual IDs.

Choose the runtime package from mutability and visibility:

Workload Package Visibility policy
One static close-inspection building Merged indexed geometry per material slot Object/part bounds; no runtime grammar work
Editable building with varied modules BatchedMesh per compatible material family Per-object batch visibility and targeted replacement
Repeated identical modules InstancedMesh or storage-instanced attributes Spatial pages; never one city-wide uncullable batch
Large district Serialized spatial chunks with projected-error LOD and optional occlusion/compute compaction Submit only visible chunks; impostor/proxy far field

GPU visibility is justified only when its scan/compaction plus indirect draw actually removes more submission/vertex work than CPU chunk culling. Every LOD/packing transition uses the shared physical-pixel projected-error contract, including nearest support depth, unjittered projection, hysteresis/dwell, and simultaneous transition memory.

Public API Shape

type BuildingQualityTier = "hero" | "city" | "distant";

function createBuildingPlan(settings: BuildingSettings): BuildingPlan;
function validateBuildingPlan(plan: BuildingPlan): BuildingDiagnostics;
function compileBuilding(
  plan: BuildingPlan,
  materials: BuildingNodeMaterials,
  options: {
    qualityTier: BuildingQualityTier;
    chunkId?: string;
    preferBatchedMesh?: boolean;
  },
): CompiledBuilding;
function disposeCompiledBuilding(compiled: CompiledBuilding): void;

BuildingPlan stays serializable. It must include tiers, footprint pieces, exposed intervals, placements, module usage, ownership rectangles, missing and unused module IDs, overlap pairs, material slot counts, UV meters per repeat, and per-slot triangle budgets.

WebGPU Capability Gate

Architecture generation is CPU deterministic; city-scale visibility, regeneration, LOD masks, and animated signs may use storage buffers or compute. Gate those paths once after renderer initialization:

import { WebGPURenderer } from "three/webgpu";

const renderer = new WebGPURenderer( { antialias: false } );
await renderer.init();

if (renderer.backend.isWebGPUBackend !== true) {
  throw new Error(
    'WebGPU is required for the canonical architecture compiler path; explicit fallback teaching belongs to threejs-compatibility-fallbacks.'
  );
}

Quality tiers are asset and budget tiers:

hero:
  full exposed-edge diagnostics, roofs, trim, ornaments, physical UV scale,
  glass separated, close-inspection geometry

city:
  same grammar and validation, fewer ornament rewrites, chunked material-slot
  batches, coarser roof equipment, no tiny one-off geometry

distant:
  serialized precompiled shells, simplified cornice/roof profiles, baked
  color variation, no dynamic per-building recompute

Materials, Color, and Output

  • Use MeshStandardNodeMaterial for masonry, metals, roof, and ornament; use MeshPhysicalNodeMaterial for glass when transmission, IOR, thickness, or clearcoat matters.
  • Do not put physical transmission on every distant pane. Hero panes may use transmission; mid/far facades use reflection probes/environment response, opaque layered-window materials, or baked interiors selected by projected pane size. Transparent sorting and background capture are part of the cost.
  • Keep one material identity per semantic slot: limestone, granite, terra-cotta, glass, bronze, black-metal, ornament, and roof.
  • LDR base-color/emissive textures encoded as sRGB use SRGBColorSpace; HDR/EXR radiance remains loader-declared linear. Normal, roughness, metalness, masks, IDs, atlas selectors, and diagnostics use NoColorSpace / linear data.
  • Keep HDR buffers as HalfFloatType until tone mapping.
  • The node pipeline owns the only tone-map and output conversion through RenderPipeline.outputColorTransform or an explicit renderOutput() node. Materials and effects must not double-convert.
  • Use pass(scene, camera), mrt() only when several nodes share scene data, and PassNode.setResolutionScale() for reduced-resolution post effects.
  • For image treatment, prefer built-in nodes first: GTAONode for contact grounding, BloomNode for authored emissive signs or interiors, TRAANode for temporal anti-aliasing. Start shadows from an ordinary fitted directional map; route CSM, tiled arrays, or caching through the shadow skill only when coverage/error/invalidation and measured cost require them.

Performance Contract

Record a workload ledger for every compiled representation:

hero building:
  semantic/material slots, V/T, projected facade/profile error,
  compile p50/p95, peak transient bytes, draws after material batching

city block chunk:
  source buildings, visible chunks/instances, submitted and culled V/T,
  metadata bytes, CPU culling/submission or compute-compaction work IDs,
  attachment/overdraw cost
  StorageTexture: only for generated ID/LOD/debug masks that need textureStore()

site asset chunk:
  accepted/rejected placements by constraint, stable asset/variant IDs,
  anchor/clearance/support violations, visible/submitted instances and V/T,
  material/representation buckets, transition overlap, metadata/asset bytes,
  compile/upload/cull p50/p95 and composed paired-marginal evidence

distant skyline:
  sector bounds, projected silhouette error, visible V/T, draws/material slots,
  baked texture bytes and transition hysteresis

Chunk by spatial bounds before city-scale batching. Compute bounds after compilation and after every regeneration. Pool reusable arrays and dispose generated geometries, BatchedMesh objects, textures, and node effects when replacing a district.

Allocate architecture cost from the complete frame and measure contemporaneous whole-frame and paired-marginal p50/p95 GPU time, CPU compile/cull/submission, overdraw, visible/culled triangles, upload traffic, peak resident/transient bytes, and sustained thermal behavior. Geometry/detail levels are selected by projected error and semantic requirements; no building/triangle/draw count is a portable device-class guarantee.

Acceptance

The generated building must survive:

  • silhouette-only view;
  • flat untextured material;
  • grazing light and contact shadowing;
  • close inspection of corners, portals, setbacks, roofs, and exposed-edge trim transitions;
  • fixed-seed fixtures for single tower, compound footprint, courtyard, twin towers, bridge, high ornament density, and minimum-span tiers;
  • seed variation without broken bays, overlapping ownership, hidden-wall decoration, floating ornament, or sliver tiers;
  • triangle, draw-call, material-slot, module-count, bounds, and UV-density reporting.

A semantic site kit must additionally survive chunk-order permutations, terrain/coast revision invalidation, rotated coast-frame fixtures, missing asset and anchor failures, overlap/support/clearance assertions, LOD population and identity checks, waterline/deck/berth diagnostics, and low-end/mobile composed measurement. A visually plausible pile of untracked props is not an accepted site plan.

Replaced Techniques

  • Replaced per-primitive InstancedMesh placement as the default with material-slot BatchedMesh or merged indexed BufferGeometry compilation, because authored buildings need many module shapes, stable material identities, exposed-edge ownership, and explicit mutability/culling policy. Only merged static geometry or identical-topology instancing is presumed to collapse r185 WebGPU draw items; BatchedMesh counts are measured.
  • Replaced whole-tier rectangle decoration with exposed-interval ownership, because compound footprints otherwise decorate hidden walls and break trim at inner and outer corners.
  • Replaced post-compile visual debugging only with serializable plan diagnostics before mesh emission, because invalid massing and ownership must fail before geometry exists.
  • Replaced custom renderer-era material hacks with TSL NodeMaterial identities and node post, because the modern renderer path keeps materials, post, color, and compute in one pipeline.

Routing Boundary

Use $threejs-choose-skills for broad graphics preflight when the work spans materials, shadows, post, validation, and city-scale performance.

Use $threejs-procedural-geometry for reusable profiles, sweeps, rings, arches, frames, or low-level mesh writers without a building grammar.

Use $threejs-procedural-materials for procedural masonry, atlas filtering, derivative normals, weathering, and per-slot material fields.

Use $threejs-procedural-fields for terrain/coast/support/exposure fields, $threejs-procedural-vegetation for plant ecology and growth, and $threejs-water-optics or $threejs-procedural-motion-systems for dynamic water and transform state consumed by docks/boats. This compiler owns semantic assembly, anchors, attachments, exclusions, stable asset selection, and the site-plan package; it does not own water simulation, buoyancy physics, plant growth, or generic rock mesh generation.

Structural deformation, fracture progression, collision resolution, rigid-body dynamics, buoyancy, and fluid/structure coupling remain owned by the selected external/domain solver. The site compiler serializes the canonical proxy, property, provider, and adapter IDs; the solver participates in the shared PhysicsGraph and exchanges canonical samples/interactions. Do not add a site-local timestep, force accumulator, or mesh-bound collision callback.

Use $threejs-scalable-real-time-shadows for CSM/tiled shadow budgets and diagnostics.

Use $threejs-ambient-contact-shading, $threejs-exposure-color-grading, and $threejs-image-pipeline for node post stack ownership beyond architecture-specific guidance.

This skill owns massing, facade semantics, architectural modules, validation, and building-plan compilation.