@call-me-sensei/toonlab 0.4.19 → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/NPM-LIBRARY.md +230 -0
  2. package/README.md +78 -36
  3. package/agents/PROMPTS.md +91 -0
  4. package/agents/README.md +9 -14
  5. package/agents/claude/CLAUDE.md +8 -0
  6. package/agents/codex/AGENTS.md +161 -0
  7. package/agents/cursor/toonlab.mdc +37 -0
  8. package/agents/references/mcp-asset-discovery.md +12 -9
  9. package/agents/references/runtime-entry-points.md +5 -4
  10. package/agents/skills/claude/asset-sourcing/SKILL.md +9 -6
  11. package/agents/skills/claude/rock-ground-shaders/SKILL.md +16 -0
  12. package/agents/skills/claude/vegetation-sky/SKILL.md +7 -4
  13. package/agents/skills/codex/asset-sourcing/SKILL.md +9 -6
  14. package/agents/skills/codex/rock-ground-shaders/SKILL.md +16 -0
  15. package/agents/skills/codex/vegetation-sky/SKILL.md +7 -4
  16. package/cli/toonlab.mjs +3 -2
  17. package/database/fal-patina.mjs +131 -0
  18. package/database/generation-service.mjs +108 -7
  19. package/database/migrations/0007_creation_revisions.sql +80 -0
  20. package/database/migrations/0008_creation_revision_hardening.sql +98 -0
  21. package/database/migrations/0009_creation_revision_delete_integrity.sql +11 -0
  22. package/database/migrations/0010_external_catalog_assets.sql +28 -0
  23. package/database/providers.mjs +195 -16
  24. package/database/repository.mjs +518 -70
  25. package/database/seeds/catalog/0003_2026-08-open-assets.sql +159086 -0
  26. package/database/seeds/catalog/0004_2026-08-c7-rocks.sql +39405 -0
  27. package/mcp/public-catalog.mjs +4 -52
  28. package/mcp/server.mjs +175 -12
  29. package/mcp/vite-plugin.mjs +78 -2
  30. package/package.json +32 -12
  31. package/scripts/generate-catalog-seed.mjs +34 -7
  32. package/src/asset-policy/catalogLicenses.js +64 -6
  33. package/src/assetlib/loadImported.js +15 -1
  34. package/src/catalog/officialCatalogAssetRuntime.js +13 -2
  35. package/src/catalog/officialCatalogLod.js +34 -1
  36. package/src/catalog/officialCatalogPlacement.js +29 -14
  37. package/src/character/animationRetarget.js +2 -0
  38. package/src/character/characterRig.js +6 -1
  39. package/src/character/characterRuntime.js +175 -7
  40. package/src/environment/environmentMaterialAdapter.js +30 -0
  41. package/src/environment/environmentPresets.js +90 -0
  42. package/src/environment/environmentSunShadowPass.js +42 -0
  43. package/src/environment/toonLabSurfaceLighting.js +108 -10
  44. package/src/environment/urbanPropMaterial.js +104 -2
  45. package/src/lighting/lightingSystem.js +65 -10
  46. package/src/renderer/index.js +7 -0
  47. package/src/renderer/styleComparison.js +985 -0
  48. package/src/rock-shader/index.js +5 -0
  49. package/src/rock-shader/rockGeometryDetail.js +701 -0
  50. package/src/rock-shader/rockMaterial.js +782 -39
  51. package/src/rock-shader/rockRegionRuntime.js +185 -0
  52. package/src/rock-shader/rockSemanticMaterialRuntime.js +337 -0
  53. package/src/rock-shader/rockShaderRuntime.js +354 -67
  54. package/src/rock-shader/rockShaderSettings.js +246 -16
  55. package/src/rock-shader/rockTangentIntegrity.js +136 -0
  56. package/src/rock-shader/rockTextureIntegrity.js +115 -0
  57. package/src/rockgen/index.js +1 -0
  58. package/src/rockgen/rockDocument.js +27 -3
  59. package/src/rockgen/surface/c7GeologySurface.js +372 -0
  60. package/src/shaders-tsl/water.js +8 -0
  61. package/src/sky/cloudShadow.js +25 -1
  62. package/src/sky/skySystem.js +9 -0
  63. package/src/styles/index.js +23 -0
  64. package/src/styles/neutralStylePresets.js +712 -0
  65. package/src/styles/sceneStyleRuntime.js +51 -4
  66. package/src/styles/styleAdapters.js +13 -2
  67. package/src/styles/styleBundle.js +1 -1
  68. package/src/texgen/evaluateTexture.js +30 -3
  69. package/src/texgen/textureGenerators.js +63 -31
  70. package/src/texgen/textureSettings.js +25 -8
  71. package/src/toon/toonSettings.js +96 -2
  72. package/src/vegetation/branchTree.js +327 -42
  73. package/src/vegetation/index.js +24 -2
  74. package/src/vegetation/scatter.js +372 -1
  75. package/src/vegetation/stylizedTree.js +312 -126
  76. package/src/vegetation/stylizedTreeFoliage.js +229 -7
  77. package/src/vegetation/treeSurfaceTextures.js +328 -0
  78. package/src/version.js +1 -1
  79. package/src/water/waterSettings.js +15 -7
  80. package/types/asset-policy/catalogLicenses.d.ts +2 -0
  81. package/types/asset-policy/index.d.ts +2 -0
  82. package/types/assetlib/loadImported.d.ts +3 -1
  83. package/types/catalog/officialCatalogLod.d.ts +63 -5
  84. package/types/character/characterRig.d.ts +59 -0
  85. package/types/character/characterRuntime.d.ts +1 -0
  86. package/types/environment/environmentMaterialAdapter.d.ts +3 -1
  87. package/types/environment/toonLabSurfaceLighting.d.ts +20 -3
  88. package/types/index.d.ts +89 -7
  89. package/types/lighting/lightingSystem.d.ts +7 -0
  90. package/types/react/index.d.ts +20 -0
  91. package/types/renderer/index.d.ts +1 -0
  92. package/types/renderer/styleComparison.d.ts +409 -0
  93. package/types/rock-shader/index.d.ts +5 -0
  94. package/types/rock-shader/rockGeometryDetail.d.ts +300 -0
  95. package/types/rock-shader/rockMaterial.d.ts +3 -0
  96. package/types/rock-shader/rockRegionRuntime.d.ts +86 -0
  97. package/types/rock-shader/rockSemanticMaterialRuntime.d.ts +29 -0
  98. package/types/rock-shader/rockShaderRuntime.d.ts +2 -0
  99. package/types/rock-shader/rockShaderSettings.d.ts +19 -5
  100. package/types/rock-shader/rockTangentIntegrity.d.ts +51 -0
  101. package/types/rock-shader/rockTextureIntegrity.d.ts +61 -0
  102. package/types/rockgen/index.d.ts +1 -0
  103. package/types/rockgen/rockDocument.d.ts +29 -1
  104. package/types/rockgen/surface/c7GeologySurface.d.ts +8 -0
  105. package/types/sky/cloudShadow.d.ts +1 -0
  106. package/types/styles/index.d.ts +1 -0
  107. package/types/styles/neutralStylePresets.d.ts +944 -0
  108. package/types/styles/sceneStyleRuntime.d.ts +20 -0
  109. package/types/vegetation/branchTree.d.ts +4 -0
  110. package/types/vegetation/index.d.ts +9 -7
  111. package/types/vegetation/scatter.d.ts +1 -0
  112. package/types/vegetation/stylizedTree.d.ts +1 -2
  113. package/types/vegetation/stylizedTreeFoliage.d.ts +1 -0
  114. package/types/version.d.ts +1 -1
  115. package/agents/references/geology-playbook.md +0 -118
  116. package/agents/skills/claude/karst-cliff-construction/SKILL.md +0 -258
  117. package/agents/skills/claude/outdoor-world/SKILL.md +0 -492
  118. package/agents/skills/claude/outdoor-world/references/coastal-landform-formation.md +0 -100
  119. package/agents/skills/codex/karst-cliff-construction/SKILL.md +0 -258
  120. package/agents/skills/codex/outdoor-world/SKILL.md +0 -492
  121. package/agents/skills/codex/outdoor-world/references/coastal-landform-formation.md +0 -100
  122. package/src/vegetation/legacyTreePresets.js +0 -120
  123. package/types/vegetation/legacyTreePresets.d.ts +0 -22
@@ -1,492 +0,0 @@
1
- ---
2
- name: outdoor-world
3
- description: Experimentally construct, tune, or visually review a stylized anime outdoor world with ToonLab, using research-derived rejection gates for biomes, vegetation, cliffs, beaches, terrain, water, atmosphere, and regression checks; this skill does not promise reliable one-shot scene generation.
4
- ---
5
-
6
- # Experimental stylized outdoor-world construction
7
-
8
- Use this skill only when a developer explicitly requests an outdoor
9
- construction experiment, controlled package qualification, or failure review.
10
- The recommended ToonLab workflow starts from an already constructed scene and
11
- applies focused shaders, vegetation, water, assets, and post. The formation
12
- rules below are research-derived rejection gates, not evidence that ToonLab or
13
- an LLM can currently produce a polished world from one prompt.
14
-
15
- ## Experimental assembly boundary in the public package
16
-
17
- The complete look emerges from composition: the sky, water, vegetation,
18
- terrain materials, weather, fog, shadows, and post treatment must agree on the
19
- same art direction and runtime conditions. ToonLab intentionally does
20
- not export a one-call full-world builder. Do not invent one or copy a
21
- repository-only composition helper into consumer code.
22
-
23
- The host creates the layout, major geometry, renderer, scene, camera, lights,
24
- controls, dynamic physics, navigation, placements, and render loop. Add only the public
25
- systems listed in
26
- `agents/references/runtime-entry-points.md`, keep each returned controller,
27
- and call each controller's documented update method before the host renders.
28
- Use recommended focused water, vegetation/grass, environment, ground-shader,
29
- rock-shader, and post guidance for their exact constructors and adapters.
30
- Sky/Cloud, Weather/Climate, terrain formation, and cross-system composition
31
- remain experimental. Wire shared scene state explicitly; there is no implicit
32
- production coordinator in this release.
33
-
34
- Three cross-cutting skills apply to every outdoor build and are worth reading
35
- before you start rather than after a review:
36
-
37
- - **`style-presets`** — explicitly name and record the intended selector on
38
- every style-aware factory. Some domains resolve a neutral/default treatment;
39
- Rock, Ground, and Cloud already default to Call Me Sensei. The skill lists
40
- the exact contract instead of applying one warning to every factory.
41
- - **`karst-cliff-construction`** — assembling cliffs, gorges, towers and
42
- coastlines out of catalog rocks: selecting by silhouette rather than by tag,
43
- unifying mixed catalog geologies into one parent rock, the transform grammar,
44
- and the gates that catch a rubble pile.
45
- - **`visual-verification`** — settling a scene before screenshotting, isolating
46
- a subsystem to attribute a defect, measuring colour against sampled targets,
47
- scanning the scene graph for outliers, and running an adversarial critic loop.
48
-
49
- Inspect the installed preset registry/source before authoring overrides. When
50
- working in a ToonLab repository checkout, also open the lab for each domain you
51
- touch (`labs/…`) and compare the values it boots. Labs are repository-only
52
- reference implementations: they are absent from npm and must never be imported
53
- or treated as runtime dependencies.
54
-
55
- For a controlled package qualification or subsystem test, assemble only the
56
- systems named by the test. Reusing a fixed ground base, sky, cloud, or lighting
57
- fixture is valid when the test contract allows it. Record any project-owned
58
- composition or manual override as a package, skill, asset-policy, or harness
59
- deficiency instead of presenting it as package behavior.
60
-
61
- ### Package-only grass qualification
62
-
63
- For a release-candidate grass test, install the packed tarball into a clean
64
- consumer and import only from `@call-me-sensei/toonlab/grass`. Do not import
65
- repository `src/` files or repository-only comparison assets; those are not
66
- proof that the installed package is complete.
67
-
68
- `createCallMeSenseiGrassField()` is the default first-party Call Me Sensei
69
- path. It generates either clump plus all three LODs and its material directly
70
- from installed package code; it does not load GLBs or textures. The default
71
- returned type is `StylizedGrassClumpField`. `RetainedGrassClumpField` is only
72
- an instancing/LOD container for caller-supplied geometry and materials; it is
73
- not a separate ToonLab grass asset. In a clean consumer, assert the generated
74
- LOD triangle counts, blade attributes, material, and deterministic seed, and
75
- assert that the tarball contains no grass media files. Never substitute the
76
- comparison scene's retained geometry/material or a repository sample and label
77
- that result as package grass.
78
-
79
- The default factory must resolve `preset: 'call_me_sensei_clump'`. Treat its
80
- meadow character as a contract: upright overlapping strokes, continuous
81
- coverage at the grazing camera, a bright watercolor wash, and color derived
82
- from the ground field. Sparse procedural blades, isolated tuft islands, dark
83
- or muddy roots, tangled crossed blades, bare-ground pinholes between ordinary
84
- placements, or an unexplained coverage edge are release failures. Do not repair
85
- them with example-local material overrides; correct the package preset, shader,
86
- geometry, scatter contract, or ground-field integration and add a regression.
87
-
88
- The controlled host still owns scatter and scene state. Place one clump record
89
- per package-generated or test-authored placement, include terrain normals for
90
- slope alignment, then wire all runtime inputs before visual approval:
91
-
92
- ```js
93
- import { createCallMeSenseiGrassField } from '@call-me-sensei/toonlab/grass';
94
-
95
- const grass = await createCallMeSenseiGrassField({
96
- placements,
97
- variant: 'primary', // or 'secondary'
98
- });
99
- // per frame, after updating the ground/shadow field passes:
100
- grass.update(delta, camera);
101
- ```
102
-
103
- When ground adoption is enabled, prefer `createSceneStyleRuntime()` and label
104
- terrain `terrain.ground` plus the meadow `vegetation.grass`; the selected bundle
105
- then marks ground writers and owns the environment ground-field pass. A manual
106
- subsystem integration must mark every terrain mesh, update its pass before
107
- grass, and verify at least one writer. Match the target's clump density, scale range, surface
108
- alignment, and camera before judging silhouette or color. A class/export check
109
- is not visual parity; compare the packaged result in composition and close views
110
- against the frozen controlled source mode and report the installed asset paths,
111
- clump/LOD counts, and any remaining visible mismatch. Never approve by color
112
- values alone. In every inspection
113
- view, reconcile the sum of active LOD instance counts against the placements
114
- that are meant to remain visible. A deficit means the final LOD distance or an
115
- explicit fade/cull contract is clipping the field; never approve an unexplained
116
- hard grass boundary.
117
-
118
- Treat ground blending as an LOD invariant. For the default Call Me Sensei
119
- profile, ground hue is authoritative: green terrain yields lighter/darker green
120
- blades, not yellow tips. LOD0/1/2 may simplify topology but must preserve
121
- integrated screen coverage so zooming does not make the underlying terrain
122
- appear to change color. If it does, fix retention, retained-blade width/alpha,
123
- or transition policy in the package; do not tune each camera separately.
124
-
125
- ### Outdoor-world formation standard
126
-
127
- For any rocky coast or cliff, read
128
- [references/coastal-landform-formation.md](references/coastal-landform-formation.md)
129
- before selecting or placing assets. It converts production research and
130
- coastal geomorphology into the required ToonLab pipeline and rejection gates.
131
-
132
- ToonLab does not currently expose a stable automatic cliff-formation planner.
133
- Keep landform generation and local rock assembly project-owned, record the gap,
134
- and visually approve every authored coast. Do not claim that instance-count,
135
- spacing, transform, or role metrics prove a cliff is production quality.
136
-
137
- Build outdoor worlds from large landform logic down to small dressing. Do not
138
- start by scattering props. Complete and approve each scale before moving to the
139
- next:
140
-
141
- 1. **Macro landform (20–500 m)** — author the connected terrain silhouette:
142
- headlands, bays, terraces, ridges, drainage, beaches, and sea floor. A cliff
143
- is first a continuous eroded mass, not a row of rock meshes. From Flyover
144
- and Top-down, the coast must read as a coherent landform with irregular but
145
- intentional rhythm before any catalog rock is added.
146
- 2. **Primary structure (5–20 m)** — use large face, wall, arch, shelf, and
147
- termination assets to reinforce selected turns in the terrain. Keep them
148
- subordinate to the macro mass and bury 30–60% of their depth into it. Never
149
- expose a module back, base, bounding edge, or free-standing panel silhouette.
150
- 3. **Secondary structure (1–6 m)** — bridge primary assets with ledges,
151
- buttresses, crevice wedges, and fractured slabs. Use overlaps, shared planes,
152
- and shadowed recesses so seams cannot be traced from an approved camera.
153
- 4. **Tertiary dressing (0.1–2 m)** — add talus, beach stones, debris, plants,
154
- wet accents, and story detail only after the silhouette and seams pass.
155
-
156
- One visually connected formation uses one parent geology. Surface state may
157
- vary with exposure—bare, mineral-stained, mossy, or wet—but limestone,
158
- sandstone, and granite do not alternate between adjacent modules unless the
159
- level explicitly authors a readable fault or geological contact. Sand belongs
160
- to beach, dune, or sediment deposits; never apply a sand-colored cap to random
161
- cliff rocks merely to add color variation.
162
-
163
- Every formation must show vertical weathering logic:
164
-
165
- - the **lip** has soil/grass overhangs, exposed shelves, roots, and broken edges;
166
- - the **mid-face** carries the dominant parent-rock color, large planes,
167
- fractures, and readable striation;
168
- - the **base** is darker/wetter, more fractured, and joined to talus or surf;
169
- - the **underwater continuation** uses the same parent geology plus submerged
170
- boulders, plants, bed color, and depth-driven water transition.
171
-
172
- Asset variation is an acceptance gate, not an aesthetic preference. Reusing a
173
- good modular rock is normal environment modeling: rotate it to present another
174
- face, tilt it for the structural role, change non-uniform scale within a
175
- believable range, bury/crop a different portion, and overlap it with different
176
- neighbors. Use authored transform grammar rather than small random jitter:
177
-
178
- - **face/wall** — align the load-bearing axis, then vary yaw broadly and keep
179
- pitch/roll restrained unless the formation explains a tilted stratum;
180
- - **shelf/lip** — rotate a useful plane upward, crop its rear into terrain,
181
- and support the underside with a face or buttress;
182
- - **buttress/termination** — turn the broad mass toward the coastline change
183
- and bury enough of the repeated source silhouette to make a new outline;
184
- - **talus/boulder** — allow broad three-axis rotation and 0.7–1.4 non-uniform
185
- scale, but preserve believable gravity and contact with the receiving bed.
186
-
187
- The rejection gate is **recognizable repetition**, not a repeated asset ID.
188
- Copies visible together must not expose the same camera-facing silhouette,
189
- orientation, scale, crop, or neighbor/seam pattern; never place twins beside
190
- each other or at a regular interval. Landmark faces need the strictest screen-
191
- space separation, while well-transformed tertiary rocks can be reused many
192
- times. Search the full catalog for enough role and silhouette families. On
193
- OSS use `search_assets({ source: 'official' })`; on Pro use
194
- `search_public_gallery({ source: 'toonlab', catalog: 'rock' })`; exhaust
195
- `nextOffset` on both surfaces. Shortlist by `dimensionsMeters`, family/profile, scale class,
196
- category/subcategory, parent geology, and surface before downloading or
197
- rendering. Use width/height/depth to match structural roles and estimate burial,
198
- overlap, and transformed scene size; never stretch a prop-scale boulder into a
199
- landmark because its dimensions were unknown. Then extract multiple credible placements from each. Record candidates inspected,
200
- selected IDs, instance count per ID, transform ranges, geology, surface state,
201
- and any recognizable-repeat failures in the test evidence.
202
-
203
- Reject the formation when it reads as a fence, repeated panels, mushrooms,
204
- teeth, stepping stones, or a kit row. Rotation and scale jitter cannot repair
205
- an insufficient role set. Return to MCP, search the wider catalog, and select
206
- more structurally appropriate assets.
207
-
208
- Model the cliff as a connected modular shape: establish a continuous terrain
209
- core, overlap large rock masses to define each headland and face turn, rotate
210
- useful faces toward the intended planes, scale them non-uniformly to vary
211
- thickness and reach, bury their backs and bases, then bridge every readable
212
- gap with shelves, wedges, buttresses, and talus. The resulting silhouette must
213
- read as one load-bearing landform even when individual source rocks are reused.
214
- This is an artist/modeling workflow that an agent may execute; it is not a
215
- claim that ToonLab currently has an automatic cliff-forming API.
216
-
217
- Material coverage is also a gate. Every camera-visible terrain or module
218
- surface must have authored maps or visibly readable triplanar/procedural rock
219
- detail at the intended viewing distance. A flat fallback color, stretched
220
- planar UV, missing texture request, or untextured terrain gap fails even when
221
- rocks hide part of it. Verify the lit side, shadow side, grazing angle, and
222
- close camera separately.
223
-
224
- Approve outdoor work in this order: untextured macro silhouette, geology and
225
- material continuity, primary/secondary rock structure, vegetation/ecology,
226
- beach and underwater dressing, then lighting/atmosphere. Small props and post
227
- processing cannot be used to conceal a failed earlier gate.
228
-
229
- ### Composition and biome continuity gate
230
-
231
- Treat scatter as an ecological field, not a rectangle of objects. Build grass
232
- coverage from `createDensityWeightMask()` composed with slope, water, surface,
233
- path, and POI masks. Let coverage taper over several meters at cliff lips,
234
- rock fields, paths, and backshore instead of stopping on a grid row or bounding
235
- box. Full coverage may end only behind an occluder or outside every approved
236
- camera. Reject any straight or unexplained grass boundary in Explore, Flyover,
237
- Top-down, and shore views.
238
-
239
- Partition a coast into six connected zones and dress every visible one:
240
-
241
- 1. **Meadow/topsoil** — grass masses with authored clearings and ground color
242
- adoption; expose dirt or stone where traffic, slope, or geology explains it.
243
- 2. **Cliff lip** — broken rock outcrops, short grass, and irregular erosion;
244
- never transition from full grass directly to a smooth vertical wall.
245
- 3. **Cliff face** — readable strata or overlapping rock masses at several
246
- scales. Sink rock instances 20–45% into the terrain, vary rotation and
247
- non-uniform scale, and use face, buttress, and crevice groups rather than a
248
- row of identical boulders. Search the ToonLab catalog by geological role
249
- and assemble at least one landmark wall/face family, one slab family, and
250
- one talus/detail family; do not stretch one prop boulder into every role.
251
- A large bare untextured wall or camera-visible primitive proxy is a release
252
- failure. If an authored map is absent, the package ground shader's
253
- triplanar geological detail must remain visibly readable between assets.
254
- 4. **Talus/headland** — clustered rocks bridge the wall to surf and hide the
255
- procedural terrain/water seam; keep some partially submerged silhouettes.
256
- 5. **Beach/backshore** — verify the sand albedo, normal, and packed ARM maps are
257
- actually sampled at a readable repeat. Add small rock groups, sparse grass
258
- at the dry back edge, and one or two story accents allowed by the asset
259
- policy. Do not leave an empty uniformly colored sand patch.
260
- 6. **Underwater continuation** — extend the seabed beyond the water tile and
261
- every camera footprint, then add submerged rock groupings and packaged
262
- moving water vegetation. Never expose the underside/edge of the terrain or
263
- leave the coast biologically empty below the surface.
264
-
265
- The water surface must extend past the intersection of every approved camera
266
- frustum with the water plane, with an additional safety margin for orbit,
267
- camera shake, and wave displacement. A visible rectangular surface boundary
268
- is always a failure; increase both width and depth rather than hiding the edge
269
- with composition.
270
-
271
- Build vegetation as a biome relationship. A lone tree is valid only when the
272
- composition identifies it as a deliberate landmark and gives it an ecological
273
- reason to survive. Otherwise use a small canopy cluster with age/scale
274
- variation, understory or saplings, ground cover, and nearby rock/moisture
275
- signals. Keep sightline clearings intentional and avoid both evenly spaced
276
- confetti and a random isolated specimen.
277
-
278
- Before approval, record zone coverage and asset provenance, then inspect the
279
- same coast from gameplay height, below the cliff, along the beach, Flyover,
280
- and Top-down. If any manual placement or shader override was required, classify
281
- it as a package-default, composition-skill, asset-policy, or test-harness
282
- deficiency; do not silently call the tuned fixture a package pass.
283
-
284
- Rock placement evidence must include each selected catalog ID, its original
285
- `dimensionsMeters`, authored scale/rotation, transformed scene dimensions,
286
- burial depth, geology, structural role, and reuse count. Missing spatial
287
- metadata is a catalog deficiency, not permission to render every candidate
288
- just to estimate size.
289
-
290
-
291
- ## Terrain in one call (or bring your own)
292
-
293
- Select the treatment before tuning individual values. The environment adapter
294
- accepts the named baseline directly:
295
-
296
- ```js
297
- await applyEnvironmentShader(environmentRoot, {
298
- preset: 'call_me_sensei',
299
- scenario: 'exteriorDay',
300
- });
301
- ```
302
-
303
- The numeric values below are validation benchmarks already carried by the
304
- shipped treatment, not a list to retype over it. Override one only when the
305
- scene has a measured reason that the shared preset cannot know.
306
-
307
- The first public package does not expose a world or terrain generator. Bring
308
- an existing terrain from the host project, or author ordinary Three.js mesh
309
- geometry in the host application; do not invent a ToonLab generation API.
310
- The terrain integration needs a pure `heightAt(x, z)` in meters and a
311
- displaced mesh under `terrain.root` with `frustumCulled = false`;
312
- everything downstream (masks, scatter, collision, minimap) derives from
313
- `heightAt` + `water.level`.
314
-
315
- ## Non-negotiable quality rules
316
-
317
- 1. **1 world unit = 1 meter, everywhere.** Camera `near 0.3 / far 600 / fov
318
- 45` for third-person gameplay. Trees `size 2.5–4` (≈ 8–12 m). Grass
319
- blades for ordinary short turf are often 0.22–0.48 m; qualified authored
320
- clumps such as the 0.82 m Call Me Sensei primary must not be rescaled merely
321
- to satisfy that generic range. Judge human scale instead: dense grass stays
322
- below the character's knees/hips and does not swallow the silhouette.
323
- 2. **Sun alignment**: the sky's visible sun disc and the host light rig MUST
324
- point the same way. Read the active sky sun direction and apply it to the
325
- directional light instead of assuming that ToonLab coordinates them. Match
326
- the fiction's time of day: 2 PM
327
- summer = `sunDirection y ≈ 0.8`, warm-white `sunColor [1.0, 0.97,
328
- 0.88]`, crisp short shadows; golden hour = `y ≈ 0.4`. Fully vertical
329
- (`y ≈ 1`) reads flat and hides every cast shadow.
330
- 3. **Three-layer atmosphere** — the single biggest "looks like the reference"
331
- factor:
332
- - host-owned `scene.fog` so ALL materials — terrain,
333
- tree far proxies, rocks — fade together into haze silhouettes;
334
- - the named environment treatment carries `heightFogDensity ≈ 0.00055,
335
- heightFogFalloff ≈ 400,
336
- heightFogColor [0.63, 0.8, 0.98]` (sky-blue; WHITE fog is the #1
337
- "looks wrong" mistake, and falloff < 100 silently kills fog above
338
- low ground);
339
- - restrained post `depthCue` (strength ≈ 0.1–0.2, blue) for the far wash.
340
- 4. **Cast shadows on**: terrain mesh `castShadow = true` (cliffs shadow
341
- their own valleys), rocks both flags, forests `lod: { castShadow: true }`.
342
- Without them the world has no depth anchoring.
343
- 5. **Never crush shade**: the named environment treatment should resolve near
344
- `ambientStrength >= 0.3`, `shadowLift >= 0.35`,
345
- `sunShadowStrength <= 0.8`, and blue `shadowTintColor [0.68, 0.74, 0.94]`.
346
- Ground and rock own separate lighting groups; do not apply these numeric
347
- floors to their unrelated controls. Validate each preset under the shared
348
- sun and require away-facing surfaces to remain readable.
349
- 6. **Grade it**: the treatment resolves near environment `saturation ≈ 1.2`,
350
- `exposure ≈ 1.06`; use post
351
- preset `call_me_sensei`, restrained bloom. Vividness comes from material
352
- palettes and value separation, not exposure or a white veil.
353
- 7. **Vegetation has three height layers**: canopy, understory, ground cover.
354
- Keep the forest spacing <= 7 m, explicitly author a bounded shrub/rosette
355
- layer, and keep dense follow-window grass.
356
- Cluster forests with `createNoisePatchMask({ scale: 0.004–0.006,
357
- threshold: 0.38–0.45 })`, but reject a seed/mask that leaves the hero view
358
- as one giant empty lawn. Canopies stay green-dominant with at most one
359
- gold accent.
360
- 8. **Default morphology is lush karst**: rolling green hills with localized
361
- rock outcrops in the playable area, ~20 m terracing mostly gated to the
362
- mountain field, and dramatic bare karst on the rim. Wall-to-wall rock is
363
- a failed landform balance. Paint only steep analytic slopes
364
- (`rise/run > 0.72`) and the upper mountain band warm ochre limestone;
365
- keep tops meadow
366
- `0x6ea24b` / golden `0xbfa845` patches, sand `0xdccf96` at the
367
- waterline. Bake atmospheric blue `0x9fbcd8` into far-rim vertex colors.
368
- Keep broad horizontal sediment strata and dark crevices in a dedicated
369
- triplanar cliff map at world scale (the treatment resolves near
370
- `triplanarDetailScale ≈ 28`). Do not
371
- project a highly tiled ground map underneath the cliff map.
372
- 9. **Terrain never hovers at the waterline**: continuously ramp ground within
373
- a transition band around the water level into a clear bank and then the
374
- submerged bed. Never snap or clamp `heightAt()` across a forbidden y-band;
375
- that creates a terrace or vertical skirt. The mesh must not render broken
376
- water slivers along any contour.
377
- 10. **Tune terrain numerically, not visually**: target ~14–20 % below water,
378
- peaks to ~175 m, before ever looking at a render. Iterate `heightAt` in
379
- node with a coverage-stats loop.
380
- 11. **Probe the spawn**: pick it programmatically — walkable height, water
381
- 30–110 m away, no wall > 27 m within 150 m, open sightline toward the
382
- map interior (never toward a world-edge rim).
383
- 12. **End the world in a mountain rim** (heights rise beyond the playable
384
- area) so no camera ever sees a void edge; haze it with rule 8's baked
385
- blue.
386
- 13. **Keep living light active**: use Call Me Sensei Weather, keep broad
387
- moving cloud-shadow coverage/strength around 0.5, and call every installed
388
- system's documented update method before rendering so terrain, trees,
389
- grass, and water remain synchronized.
390
- 14. **Keep gameplay VFX host-owned**: the public package has no stable checkpoint-ring or
391
- motion-trail export. If the project needs them, implement and test them in
392
- the host and record the missing package surface. Use bounded translucent
393
- geometry, near-camera fade, short speed-gated trails, and no screen-filling
394
- discs or rigid white boxes.
395
- 15. **Keep water deep and alive**: Call Me Sensei water uses a saturated deep
396
- blue body, reflection strength <= 0.5, visible detail normals, and low
397
- lake wave motion. Do not restore the old milky anime tone.
398
- 16. **Ground without crushing**: generated terrain must ship its
399
- `envVertexAo` attribute; rockgen ships SDF AO. The host may add a restrained
400
- contact-shadow solution for tree/rock bases with cool color and opacity
401
- <= 0.18. Never use opaque black blobs as AO.
402
- 17. **Give the horizon a human scale anchor**: the default lush terrain ships
403
- one deterministic castle silhouette. Bespoke worlds need an equivalent
404
- tower, city, ruin, or landmark structure on the rim; noise-only peaks are not
405
- a landmark.
406
- 18. **Far LODs keep real volume**: use the default instanced low-poly crown +
407
- crown proxy (<= 160 triangles/tree); keep trunks in near LOD only so they
408
- cannot minify into aerial dirt. Never replace it with a painted
409
- billboard, ellipse texture, or horizontal aerial cap: those become dirty
410
- speckles from above and giant color blobs from gameplay cameras.
411
- 19. **Moss hero rocks**: keep Call Me Sensei rock moss coverage around
412
- 0.25–0.4 on upward ledges. The terrain remains mostly meadow; moss helps
413
- the localized outcrops belong to it.
414
- 20. **Near-camera particles disappear**: keep the default 0.45–1.35 m cutout
415
- particle fade. A petal or leaf crossing the camera must collapse before
416
- it becomes a screen-sized pink/orange blob.
417
-
418
- ## Budgets (60 fps desktop, < 10 s startup)
419
-
420
- | System | Budget | Mechanism |
421
- |---|---|---|
422
- | Trees | 1,500–3,000 placements | `StylizedForest` LOD: 10 instanced volumetric proxy variants (<= 160 tris/tree), near = 140 live clones within 165 m |
423
- | Understory | ≤ 2,400 shrubs + 6,200 rosettes | two instanced draws derived from forest placements |
424
- | Grass | Measure with `field.bladeBudget()` | Budget clump placements over coverage-positive ground in approved camera footprints. The qualifying lab used about 1.78 patches/m² as a scene-specific reference; derive the actual drawn LOD0/1/2 blades instead of calling that a universal package density. Grade placement density against the hero camera and report how much of the field is behind every approved shot. |
425
- | Rocks | ≤ 180 clones | 3–4 rockgen variants at `gameplayHigh`, shared geometry |
426
- | Terrain | ≤ 265k vertices | one displaced plane, vertex colors + shipped `envVertexAo`; no boot-time ray bake |
427
-
428
- ## Symptom table — check here FIRST when it looks wrong
429
-
430
- | Symptom | Cause | Fix |
431
- |---|---|---|
432
- | Terrain smooth, gray-green, unlit-looking | environment/ground shader never applied | classify the terrain explicitly and apply the stable environment or ground-shader API before rendering |
433
- | Distant trees dark/near-black | shadow palette or far proxy colors too dark | use Call Me Sensei tree + vegetation shader and the default lifted volumetric LOD |
434
- | Distant trees look dirty/noisy | near-leaf detail was baked into a billboard | restore the instanced volumetric crown proxy; never use card-by-card far bakes |
435
- | Giant green/orange crown blobs | ellipse billboard or horizontal top cap leaked into gameplay | remove the billboard path; use the camera-independent volumetric proxy |
436
- | Distant trees sharp saturated blobs, no fade | `scene.fog` missing | configure host scene fog and pass matching distance-fog settings to systems that expose an adapter |
437
- | Trees look like confetti from the air | uniform/sparse scatter or no middle layer | preset spacing <= 7 m + patch mask + default instanced understory |
438
- | Aerial frame is one empty lawn | patch threshold/seed removed the whole hero region | lower the threshold toward 0.38 or choose a valid patch seed; preserve forest clearings, not map-sized voids |
439
- | Grass stops on a straight line | scatter was authored as a rectangle, hard surface threshold, or short final LOD | use `createDensityWeightMask()` with slope/water/surface masks, cover every camera footprint, and verify active LOD counts |
440
- | Cliff reads as repeated panels, mushrooms, teeth, or a fence | repeated assets expose the same face/crop or a small prop set became the primary silhouette | restore a continuous macro mass; rotate, tilt, scale, bury, crop, and overlap role-appropriate rocks until no screen-space repetition remains |
441
- | Gaps expose terrain between rock modules | discrete assets were asked to form the landmass or secondary seam coverage was skipped | make terrain the continuous parent mass; bridge faces with recessed shelves, buttresses, and crevice slabs before dressing |
442
- | Tan/sand-colored rocks alternate through a gray cliff | incompatible geology or sediment surface states were mixed for variety | choose one parent geology; reserve sand for the beach unless an explicit geological contact is authored |
443
- | Cliff is a smooth bare wall above the sea | terrain base was treated as final art instead of a support surface | compose cliff lip, overlapping face/buttress rocks, crevices, and talus; retain triplanar rock treatment between instances |
444
- | Beach is a flat empty color patch | texture maps are missing/not sampled or no backshore/swash dressing pass was done | verify albedo/normal/ARM bindings and readable repeat; add clustered rocks plus sparse dry-edge vegetation/story accents |
445
- | One random tree sticks out of a meadow | object-by-object placement replaced biome composition | form a canopy/sapling/understory cluster or explicitly justify and frame it as a landmark tree |
446
- | White/gray blotches pooling in valleys | white height fog | `heightFogColor` sky-blue (rule 3) |
447
- | Fog invisible no matter the density | `heightFogFalloff` too small (fog dies above low ground) | falloff ≈ 400 for distance-led haze |
448
- | Teal shards along cliff contours | water surface spanning steep banks (fixed in the water shader) | update ToonLab; keep terrain off the waterline (rule 9) |
449
- | Flat lighting, no sun side | rig sun near-vertical or misaligned with sky | rule 2 |
450
- | No shadows anywhere | nothing casts | rule 4 |
451
- | Everything washes pale | fog density too high or translucent overlay covers the view | density ≈ 0.00055; inspect large alpha quads/discs before touching atmosphere |
452
- | World edge visible | terrain ends at playable bounds | mountain rim (rule 11) |
453
- | Camera staring into a hillside at spawn | unprobed spawn | rule 10 |
454
- | Startup takes a minute | one unique StylizedTree per placement | use `StylizedForest` with a bounded reusable variant set |
455
- | Mountains/terrain vanish when looked at directly | frustum culling misjudging displaced geometry | `mesh.frustumCulled = false` on terrain and scaled rock clones |
456
- | Distant water bright/sharp band "cutting into" fogged mountains | surface missing the environment height-fog layer | update ToonLab (auto-wired via `setDistanceFog`); custom surfaces must join the layer |
457
- | Giant white "iceberg" wedges at far shorelines | swash film climbing steep banks (fixed: clamped +0.5 m) | update ToonLab |
458
- | Full-detail trees popping out of the haze in aerial views | LOD picked by horizontal distance | update ToonLab (true 3D distance) |
459
- | Gold/orange trees with green shadows or pink crowns | canopy palette derivation broke on warm hues (fixed) | update ToonLab |
460
- | Billboard trees upside down | render-target bakes are written top-down (fixed) | update ToonLab |
461
- | Cliff walls read as flat untextured paint up close | planar terrain UVs stretch to nothing on walls | use warm banded `envTriplanarMap` + `triplanarDetail: 1`, scale ≈ 28, and lip highlights |
462
- | Zigzag triangle pattern on cliff walls | per-vertex paint bands finer than the mesh grid; meadow/gold hue bleeding into stone | keep vertex-paint frequencies above the grid spacing; gate gold/meadow hard by slope |
463
- | Herringbone/moire on close cliffs | ground and cliff maps projected together, scale too small, or contrast too high | let one dedicated cliff map own steep faces; use broad mipmapped bands at ~28 m scale |
464
- | Trees look like broccoli with black bases | sparse crowns plus dark canopy/bark floor | keep signature `leafDensity >= 1`, warm bark, vegetation shadow floors, and the lifted proxy palette |
465
- | Grass hides the character or becomes neon line noise | clump scale/density was increased blindly or the wrong preset was selected | restore the selected package preset and dimensions, inspect `field.bladeBudget()`, then tune coverage-positive clumps against the hero/gameplay cameras rather than applying a universal blades/m² number |
466
- | Ring becomes a giant teal veil | filled plane/circle or no near-camera screen fade | fix the host-owned VFX with bounded geometry and a near-camera fade; do not invent a ToonLab import |
467
- | Pink/orange particle fills the screen | petal/leaf crossed the near plane at full size | restore the ambient cutout near fade; do not disable it for screenshots |
468
- | Flight trails look like rigid white poles | constant-width, long, always-on bespoke geometry | fix the host-owned trail with a speed gate, short lifetime, translucent taper, and near-camera safety |
469
- | Water looks milky light blue | deep band too pale and soft reflection too strong | restore Call Me Sensei water tone; reflection <= 0.5 and detail normals/wave life enabled |
470
- | Valley is uniformly lit | cloud-shadow field missing, weak, or not ticking | keep Call Me Sensei Weather and update the weather/cloud-shadow controllers before rendering |
471
- | Aerial views gray and lifeless | one height-fog density for every camera | lower `heightFogDensity` for flyover/top-down and sync `water.setDistanceFog` + `forest.setDistanceFog` |
472
- | ~20 fps in a big world | full-res meshes redrawn by water grab/depth/reflection passes | instanced volumetric forest proxies (pass `renderer`), hi/lo rock LOD by 3D distance, `userData.waterExclude`/`waterGrabExclude`, `water.settings.passes = { reflectionScale: 0.4, sceneColorScale: 0.6 }`, `?dpr=1` on retina |
473
- | Character floats above / sinks into water when swimming | hand-rolled float height | chest at waterline via `water.getHeightAt`; calm swim default, fast stroke on Shift, `timeScale = clamp(speed/1.7, 0.75, 1.35)` |
474
- | Character walks through rocks/trees | a solid root is unlabeled, explicitly non-solid, or collision readiness was skipped | label every solid root, let `createSceneStyleRuntime()` register it, call `styleRuntime.collision.assertReady()`, and use explicit metadata/custom or Rapier adapters when bounds are inappropriate |
475
-
476
- ## Verify like the labs do
477
-
478
- Run the consumer app's tests/build, then render-test in a WebGPU-capable
479
- browser after a cold reload. Wait for the app's ready flag and inspect fresh
480
- screenshots from **all three** required views: Explore, Flyover, and Top-down.
481
- Do not approve a vegetation/LOD change from only one view. Explicitly reject
482
- screen-sized color shapes, flat crown walls, dirty speckles, black bases,
483
- character-height grass, and visible LOD discontinuities; fix and repeat all
484
- three views. Also inspect close cliff/tree/water, high-speed views, and every
485
- new browser-console error. A passing build is not visual approval. Set
486
- `document.body.dataset.worldReady = 'true'` when the first frame is live.
487
- The complete reference implementation is `examples/outdoor-world/` in the
488
- ToonLab repo — copy it, then swap in your own terrain and character.
489
-
490
- For ToonLab itself, run `npm run verify:world-quality`,
491
- `npm run verify:vegetation-shader`, `npm run verify:water`,
492
- `npm run verify:vfxgen`, and `npm run build` before using the result.
@@ -1,100 +0,0 @@
1
- # Coastal landform and cliff formation
2
-
3
- Use this reference before authoring or reviewing a rocky coast, cliff, pocket
4
- beach, headland, sea stack, or submerged cliff continuation.
5
-
6
- ## Research translated into production rules
7
-
8
- The sources converge on a hybrid, multi-scale pipeline:
9
-
10
- - Ubisoft's [Procedural World Generation of Far Cry 5](https://www.gdcvault.com/play/1025215/Procedural-World-Generation-of-Far)
11
- separates large-scale automatic world filling from local artist tuning and
12
- includes dedicated tools for terrain, biomes, texturing, water networks, and
13
- cliff rocks. Translate this into ToonLab as deterministic macro generation
14
- plus explicit local assemblies; never treat one scatter pass as the finished
15
- coast.
16
- - Epic's [PCG Biome Core](https://dev.epicgames.com/documentation/unreal-engine/procedural-content-generation-pcg-biome-core-and-sample-plugins-overview-guide-in-unreal-engine)
17
- uses a fixed data-driven pipeline, layered priorities, local blending,
18
- root/child filtering, recursive hierarchical transforms, accurate bounds,
19
- and per-asset shadow overrides. Translate this into ordered coast zones,
20
- nested rock assemblies, exclusion masks, overlap checks, and cast/receive
21
- shadow defaults.
22
- - Epic's [Electric Dreams environment](https://dev.epicgames.com/documentation/unreal-engine/electric-dreams-environment-in-unreal-engine)
23
- exposes the large cliff as an assembly and combines procedural and
24
- hand-crafted areas. Treat a cliff as an assembly-level landform, not an
25
- array of unrelated meshes.
26
- - Adobe Research's [Terrain Amplification using Multi-scale Erosion](https://research.adobe.com/publication/terrain-amplification-using-multi-scale-erosion/)
27
- applies thermal, stream-power, and hillslope processes at several scales.
28
- Translate this into macro planform, primary masses, secondary fractures,
29
- and tertiary debris with coherent direction and parent geology.
30
- - The U.S. National Park Service's [Rocky Coast Landforms](https://home.nps.gov/articles/rocky-coast-landforms.htm)
31
- relates coast profile to lithology and structure, identifies headlands and
32
- protected pocket beaches, and distinguishes massive-rock versus layered-rock
33
- erosion. A beach belongs inside a protected embayment; a massive granite
34
- coast should not randomly switch to sandstone steps.
35
- - The U.S. Geological Survey's [Northern Monterey Bay field guide](https://pubs.usgs.gov/of/2000/0438/)
36
- describes seacliffs, shore platforms, pocket beaches, and headland/embayment
37
- morphology as one connected coastal system governed by geology, orientation,
38
- and wave exposure. Author all of those zones together.
39
- - SideFX's [terrain workflow](https://www.sidefx.com/products/houdini/world-building/terrain/)
40
- uses layered noise, masks, erosion, and hierarchical scattering. Drive
41
- vegetation, rock, wetness, sediment, and underwater dressing from the same
42
- coast/height/slope/exposure fields.
43
-
44
- ## Required ToonLab workflow
45
-
46
- 1. Define one parent geology and its structural behavior: massive, layered,
47
- jointed, volcanic, or karst. Set slope profile, strata direction, fracture
48
- family, erosion resistance, and material palette before choosing assets.
49
- 2. Author the continuous terrain planform with at least two scales of
50
- variation. Use broad headlands and embayments first, then smaller notches.
51
- A noisy line with constant amplitude is still uniform.
52
- 3. Make the terrain volume own the land silhouette, cliff top, and underwater
53
- continuation. Extend topsoil and grass to selected rims and shoulders.
54
- 4. Reserve sheltered embayments between headlands for pocket beaches. Blend
55
- backshore, dry sand, wet sand, swash, shallow bed, and deep bed; do not paste
56
- sand between exposed cliff modules.
57
- 5. Place primary rocks only at structural events: headland noses, cove turns,
58
- terrace breaks, fault zones, face recesses, and terminations. Build each
59
- event as a nested 3D assembly with crown, mid-face, toe, and submerged depth.
60
- 6. Bury 30–65 percent of large module depth into terrain. Crop repeated
61
- silhouettes differently. Terrain or overlapping neighbors must hide backs,
62
- bases, and bounding edges.
63
- 7. Add secondary ledges, buttresses, crevice wedges, and slabs that bridge
64
- seams. Add talus below plausible fracture/failure zones, not at a uniform
65
- density everywhere.
66
- 8. Apply ground adoption or compatible grass/soil caps to upward crown
67
- surfaces. Taper grass using slope, exposure, substrate, and distance to the
68
- rim. The terrain grass field and the asset cap must read as one surface.
69
- 9. Continue parent geology underwater with a visible bed, submerged boulders,
70
- plants, and depth/shore water response. Never leave a hollow underside.
71
- 10. Enable cast and receive shadows on terrain, rock, tree, character, beach,
72
- and relevant water passes. Inspect contact, long cast shadows, and shaded
73
- cliff value separation before grading.
74
-
75
- ToonLab does not ship an approved automatic cliff-formation API in this
76
- release. Keep the connected landform and local assemblies project-owned, and
77
- record that custom work as a custom integration note. Numeric checks can reject obvious
78
- uniformity, but no instance-count, transform-range, spacing, or role-count
79
- metric can approve a cliff without visual review.
80
-
81
- ## Rejection gates
82
-
83
- Reject immediately when any of these are visible in gameplay, shore, flyover,
84
- or top-down views:
85
-
86
- - one constant-width row of rocks following the coast;
87
- - primary assets at regular intervals, even with random jitter;
88
- - thin walls, blades, teeth, mushrooms, stepping stones, or repeated twins;
89
- - rocks defining the land silhouette while terrain stops behind them;
90
- - grass ending before the rim when the geology supports a grass cap;
91
- - isolated cap colors that do not join the terrain material;
92
- - empty terrain triangles, visible module backs/bases, or unshadowed seams;
93
- - beach outside a protected embayment or sediment inserted between cliff rocks;
94
- - no toe/talus, shore platform, or submerged continuation;
95
- - passing based on instance count alone. Hundreds of badly organized rocks
96
- still fail.
97
-
98
- Record the landform profile, geology, coast range, assembly sites, role counts,
99
- asset IDs, per-ID instance counts, burial range, transform range, exclusion
100
- masks, shadow state, material state, and screenshots for all inspection views.