@call-me-sensei/toonlab 0.3.0 → 0.4.19

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 (736) hide show
  1. package/README.md +549 -184
  2. package/agents/README.md +59 -0
  3. package/agents/references/anime-art-direction.md +24 -0
  4. package/agents/references/asset-sourcing-policy.md +23 -0
  5. package/agents/references/custom-gap-report.md +16 -0
  6. package/agents/references/geology-playbook.md +118 -0
  7. package/agents/references/mcp-asset-discovery.md +104 -0
  8. package/agents/references/runtime-entry-points.md +174 -0
  9. package/agents/references/style-bundles.md +71 -0
  10. package/agents/skills/claude/asset-sourcing/SKILL.md +275 -0
  11. package/agents/skills/claude/environment/SKILL.md +59 -0
  12. package/agents/skills/claude/game-dev/SKILL.md +100 -0
  13. package/agents/skills/claude/karst-cliff-construction/SKILL.md +258 -0
  14. package/agents/skills/claude/outdoor-world/SKILL.md +492 -0
  15. package/agents/skills/claude/outdoor-world/references/coastal-landform-formation.md +100 -0
  16. package/agents/skills/claude/post-processing/SKILL.md +44 -0
  17. package/agents/skills/claude/rock-ground-shaders/SKILL.md +118 -0
  18. package/agents/skills/claude/rockgen/SKILL.md +30 -0
  19. package/agents/skills/claude/scene-style-application/SKILL.md +74 -0
  20. package/agents/skills/claude/style-presets/SKILL.md +101 -0
  21. package/agents/skills/claude/toon-shading/SKILL.md +44 -0
  22. package/agents/skills/claude/vegetation-sky/SKILL.md +167 -0
  23. package/agents/skills/claude/visual-verification/SKILL.md +136 -0
  24. package/agents/skills/claude/water/SKILL.md +105 -0
  25. package/agents/skills/codex/asset-sourcing/SKILL.md +275 -0
  26. package/agents/skills/codex/environment/SKILL.md +59 -0
  27. package/agents/skills/codex/game-dev/SKILL.md +100 -0
  28. package/agents/skills/codex/karst-cliff-construction/SKILL.md +258 -0
  29. package/agents/skills/codex/outdoor-world/SKILL.md +492 -0
  30. package/agents/skills/codex/outdoor-world/references/coastal-landform-formation.md +100 -0
  31. package/agents/skills/codex/post-processing/SKILL.md +44 -0
  32. package/agents/skills/codex/rock-ground-shaders/SKILL.md +118 -0
  33. package/agents/skills/codex/rockgen/SKILL.md +30 -0
  34. package/agents/skills/codex/scene-style-application/SKILL.md +74 -0
  35. package/agents/skills/codex/style-presets/SKILL.md +101 -0
  36. package/agents/skills/codex/toon-shading/SKILL.md +44 -0
  37. package/agents/skills/codex/vegetation-sky/SKILL.md +167 -0
  38. package/agents/skills/codex/visual-verification/SKILL.md +136 -0
  39. package/agents/skills/codex/water/SKILL.md +105 -0
  40. package/cli/toonlab.mjs +52 -0
  41. package/compose.yaml +20 -0
  42. package/database/apply-sql.mjs +141 -0
  43. package/database/client.mjs +39 -0
  44. package/database/creation-tags.mjs +23 -0
  45. package/database/env.mjs +16 -0
  46. package/database/generation-service.mjs +314 -0
  47. package/database/migrations/0001_local_workspace.sql +120 -0
  48. package/database/migrations/0002_file_ownership.sql +11 -0
  49. package/database/migrations/0003_remove_autosaves_from_library.sql +7 -0
  50. package/database/migrations/0004_catalog_asset_packs.sql +39 -0
  51. package/database/migrations/0005_creation_tag_discovery.sql +1 -0
  52. package/database/migrations/0006_normalize_creation_tags.sql +28 -0
  53. package/database/providers.mjs +465 -0
  54. package/database/repository.mjs +625 -0
  55. package/database/seeds/catalog/0001_empty_official_catalog.sql +4 -0
  56. package/database/seeds/catalog/0002_2026-08.sql +19454 -0
  57. package/mcp/lab-management.mjs +629 -0
  58. package/mcp/public-catalog.mjs +168 -0
  59. package/mcp/server.mjs +1026 -63
  60. package/mcp/vite-plugin.mjs +443 -26
  61. package/mcp/workspace.mjs +26 -1
  62. package/package.json +312 -45
  63. package/scripts/generate-catalog-seed.mjs +297 -0
  64. package/scripts/setup-local.mjs +128 -0
  65. package/src/agents/index.js +7 -0
  66. package/src/agents/sceneStyleOperations.js +169 -0
  67. package/src/asset-policy/catalogLicenses.js +44 -0
  68. package/src/asset-policy/index.js +315 -0
  69. package/src/assetlib/assetRef.js +1 -1
  70. package/src/assetlib/galleryMaterialFamily.js +165 -0
  71. package/src/assetlib/index.js +6 -2
  72. package/src/assetlib/plateau.js +188 -0
  73. package/src/assetlib/plateauLandmarks.js +144 -0
  74. package/src/assetlib/plateauViewer.js +348 -0
  75. package/src/assetlib/sources.js +16 -2
  76. package/src/catalog/manifest.js +11 -1
  77. package/src/catalog/officialCatalog.js +4 -0
  78. package/src/catalog/officialCatalogAssetRuntime.js +313 -0
  79. package/src/catalog/officialCatalogLod.js +150 -0
  80. package/src/catalog/officialCatalogPlacement.js +228 -0
  81. package/src/catalog/officialCatalogProvider.js +334 -0
  82. package/src/character/animationRetarget.js +1082 -0
  83. package/src/character/characterRuntime.js +376 -0
  84. package/src/character/groundStabilizer.js +137 -0
  85. package/src/character/index.js +8 -0
  86. package/src/character/locomotionActions.js +74 -0
  87. package/src/character/locomotionStateMachine.js +241 -0
  88. package/src/character/mannequinAsset.js +15 -0
  89. package/src/character/mannequinAssetUrl.browser.js +4 -0
  90. package/src/character/mannequinAssetUrl.node.js +3 -0
  91. package/src/character/modelLoader.js +92 -12
  92. package/src/character/walkableCharacterRuntime.js +284 -0
  93. package/src/character/waterInteractionController.js +217 -0
  94. package/src/cloud/ambientSkyBaker.js +248 -0
  95. package/src/cloud/cloudLighting.js +1114 -0
  96. package/src/cloud/cloudParams.js +819 -0
  97. package/src/cloud/cloudReprojection.js +563 -0
  98. package/src/cloud/cloudStyle.js +780 -0
  99. package/src/cloud/cloudStyleSnapshots.js +387 -0
  100. package/src/cloud/cloudVolume.js +1903 -0
  101. package/src/cloud/heroCloudRecipe.js +404 -0
  102. package/src/cloud/index.js +42 -0
  103. package/src/cloud/noise/baseShapeVolume.js +331 -0
  104. package/src/cloud/noise/cirrusMap.js +131 -0
  105. package/src/cloud/noise/curlNoise.js +289 -0
  106. package/src/cloud/noise/erosionVolume.js +188 -0
  107. package/src/cloud/noise/noiseVolume.js +202 -0
  108. package/src/cloud/noise/periodicNoise3.js +295 -0
  109. package/src/cloud/noise/weatherMap.js +470 -0
  110. package/src/cloud/paramSchema.js +458 -0
  111. package/src/collisionMetadata.js +320 -0
  112. package/src/core/systemStylePolicy.js +32 -0
  113. package/src/environment/dayCurves.js +146 -0
  114. package/src/environment/environmentGroundFieldPass.js +354 -0
  115. package/src/environment/environmentMaterialAdapter.js +114 -6
  116. package/src/environment/environmentPresets.js +396 -90
  117. package/src/environment/environmentRigs.js +17 -2
  118. package/src/environment/environmentSettings.js +37 -1
  119. package/src/environment/environmentShaderMaterials.js +37 -6
  120. package/src/environment/environmentState.js +133 -0
  121. package/src/environment/environmentSunShadowPass.js +357 -6
  122. package/src/environment/environmentTextureResolver.js +7 -0
  123. package/src/environment/index.js +51 -0
  124. package/src/environment/manufacturedMaterialContract.js +837 -0
  125. package/src/environment/manufacturedReflectionProvider.js +114 -0
  126. package/src/environment/scanAssetStylize.js +4 -4
  127. package/src/environment/surfaceMaterialModes.js +71 -0
  128. package/src/environment/toonLabEnvironmentMaterials.js +353 -0
  129. package/src/environment/toonLabMaterialPassCoupling.js +347 -0
  130. package/src/environment/toonLabNormalIntegration.js +171 -0
  131. package/src/environment/toonLabRockMaterialResolver.js +592 -0
  132. package/src/environment/toonLabSourceDefaultLit.js +444 -0
  133. package/src/environment/toonLabSourceLibrary.js +762 -0
  134. package/src/environment/toonLabSourceMaterials.js +3718 -0
  135. package/src/environment/toonLabSourceSubsurfaceLighting.js +415 -0
  136. package/src/environment/toonLabSourceTemporal.js +717 -0
  137. package/src/environment/toonLabSurfaceLighting.js +364 -0
  138. package/src/environment/toonLabTextureReadiness.js +105 -0
  139. package/src/environment/toonLabTreeMaterials.js +450 -0
  140. package/src/environment/transparentMaterialProfile.js +87 -0
  141. package/src/environment/urbanPropMaterial.js +2874 -0
  142. package/src/ground-shader/groundPrintLayer.js +375 -0
  143. package/src/ground-shader/groundShaderMaterial.js +851 -0
  144. package/src/ground-shader/groundShaderSettings.js +468 -0
  145. package/src/ground-shader/index.js +3 -0
  146. package/src/index.js +52 -22
  147. package/src/lighting/callMeSenseiLightingContract.js +163 -0
  148. package/src/lighting/index.js +14 -7
  149. package/src/lighting/lightingCapabilities.js +2 -2
  150. package/src/lighting/lightingPresets.js +6 -3
  151. package/src/lighting/lightingStyle.js +41 -6
  152. package/src/lighting/lightingSystem.js +140 -1
  153. package/src/lighting/{unrealExport.js → toonLabExport.js} +40 -41
  154. package/src/post/postProcessing.js +71 -12
  155. package/src/react/index.js +66 -0
  156. package/src/renderer/index.js +9 -0
  157. package/src/renderer/rendererConfiguration.js +250 -0
  158. package/src/rock-shader/index.js +3 -0
  159. package/src/rock-shader/rockMaterial.js +1843 -0
  160. package/src/rock-shader/rockShaderRuntime.js +494 -0
  161. package/src/rock-shader/rockShaderSettings.js +869 -0
  162. package/src/rockgen/export/glbExport.js +104 -14
  163. package/src/rockgen/index.js +4 -3
  164. package/src/rockgen/lod/index.js +6 -0
  165. package/src/rockgen/lod/rockLodMetrics.js +168 -0
  166. package/src/rockgen/lod/rockLodPlanner.js +372 -0
  167. package/src/rockgen/lod/rockLodPolicy.js +235 -0
  168. package/src/rockgen/lod/rockLodRuntime.js +124 -0
  169. package/src/rockgen/lod/rockLodSimplifier.js +173 -0
  170. package/src/rockgen/lod/rockLodValidation.js +113 -0
  171. package/src/rockgen/mesh/meshAttributes.js +17 -0
  172. package/src/rockgen/mesh/meshDocument.js +6 -0
  173. package/src/rockgen/rockDocument.js +352 -9
  174. package/src/rockgen/rockgenPresets.js +114 -13
  175. package/src/rockgen/rockgenSettings.js +62 -11
  176. package/src/runtime/index.js +14 -0
  177. package/src/runtime/sceneCollisionRuntime.js +317 -0
  178. package/src/runtime/sceneSurfaceRuntime.js +451 -0
  179. package/src/runtime/sceneUpdateScheduler.js +203 -0
  180. package/src/shaders-tsl/anime.js +9 -2
  181. package/src/shaders-tsl/chunks/environment-ground-field.js +174 -0
  182. package/src/shaders-tsl/chunks/environment-state.js +79 -0
  183. package/src/shaders-tsl/chunks/environment-sun-shadow.js +99 -32
  184. package/src/shaders-tsl/chunks/normalized-hue.js +41 -0
  185. package/src/shaders-tsl/chunks/pass-depth-color.js +4 -2
  186. package/src/shaders-tsl/chunks/scene-depth-color-pass.js +273 -0
  187. package/src/shaders-tsl/chunks/vegetation-style.js +116 -8
  188. package/src/shaders-tsl/chunks/water-color.js +19 -5
  189. package/src/shaders-tsl/chunks/water-shore-state.js +8 -1
  190. package/src/shaders-tsl/chunks/world-noise.js +30 -0
  191. package/src/shaders-tsl/environment.js +123 -17
  192. package/src/shaders-tsl/flower.js +51 -8
  193. package/src/shaders-tsl/grass.js +194 -29
  194. package/src/shaders-tsl/post-composite.js +83 -2
  195. package/src/shaders-tsl/tree-leaf.js +107 -16
  196. package/src/shaders-tsl/water-breaker.js +18 -4
  197. package/src/shaders-tsl/water.js +43 -3
  198. package/src/shaders-tsl/woody-surface.js +59 -7
  199. package/src/sky/atmosphereDome.js +193 -0
  200. package/src/sky/atmosphereParams.js +396 -0
  201. package/src/sky/atmosphereScattering.js +593 -0
  202. package/src/sky/atmosphereSky.js +371 -0
  203. package/src/sky/cloudShadow.js +355 -0
  204. package/src/sky/godRays.js +257 -0
  205. package/src/sky/index.js +55 -1
  206. package/src/sky/nightSky.js +1190 -0
  207. package/src/sky/renderLayers.js +120 -0
  208. package/src/sky/skyColor.js +582 -0
  209. package/src/sky/skyDayCycle.js +244 -0
  210. package/src/sky/skyParams.js +661 -0
  211. package/src/sky/skyPresets.js +772 -0
  212. package/src/sky/skyQualityTiers.js +383 -0
  213. package/src/sky/skyShaderSettings.js +699 -0
  214. package/src/sky/skyStyleSnapshots.js +211 -0
  215. package/src/sky/skySystem.js +1438 -0
  216. package/src/sky/skyTimeKeyframes.js +361 -0
  217. package/src/sky/stylizedSky.js +405 -116
  218. package/src/sky/sunDriver.js +499 -0
  219. package/src/sky/timeOfDay.js +335 -0
  220. package/src/styles/animeGameProfile.js +44 -0
  221. package/src/styles/index.js +134 -0
  222. package/src/styles/manufacturedStyleLabeling.js +204 -0
  223. package/src/styles/sceneLayerDocuments.js +185 -0
  224. package/src/styles/sceneLookComposition.js +156 -0
  225. package/src/styles/sceneQualityApplication.js +152 -0
  226. package/src/styles/sceneQualityProfiles.js +268 -0
  227. package/src/styles/sceneStyleAudit.js +512 -0
  228. package/src/styles/sceneStyleRuntime.js +876 -0
  229. package/src/styles/styleAdapters.js +166 -0
  230. package/src/styles/styleApplication.js +369 -0
  231. package/src/styles/styleBundle.js +444 -91
  232. package/src/styles/styleBundleProvider.js +83 -0
  233. package/src/styles/styleDomains.js +21 -0
  234. package/src/styles/styleInspector.js +262 -0
  235. package/src/styles/styleMaterialContract.js +375 -0
  236. package/src/styles/styleMetadata.js +73 -0
  237. package/src/styles/styleTargetDiscovery.js +162 -0
  238. package/src/styles/styleTargetLabels.js +206 -0
  239. package/src/styles/styleTargetMaterialCoverage.js +137 -0
  240. package/src/styles/styleTransaction.js +272 -0
  241. package/src/texgen/textureGenerators.js +21 -5
  242. package/src/toon/toonSettings.js +4 -0
  243. package/src/vegetation/branchTree.js +302 -0
  244. package/src/vegetation/callMeSenseiGrass.js +183 -0
  245. package/src/vegetation/compiledTree.js +506 -0
  246. package/src/vegetation/contactShadowField.js +107 -0
  247. package/src/vegetation/flowerSpecies.js +10 -2
  248. package/src/vegetation/grass.js +13 -0
  249. package/src/vegetation/grassClump.js +1179 -0
  250. package/src/vegetation/importedVegetationMaterial.js +183 -0
  251. package/src/vegetation/index.js +15 -1
  252. package/src/vegetation/legacyTreePresets.js +120 -0
  253. package/src/vegetation/scatter.js +322 -3
  254. package/src/vegetation/stylizedBush.js +14 -0
  255. package/src/vegetation/stylizedFlower.js +31 -0
  256. package/src/vegetation/stylizedFlowers.js +59 -7
  257. package/src/vegetation/stylizedForest.js +455 -147
  258. package/src/vegetation/stylizedGrass.js +188 -24
  259. package/src/vegetation/stylizedTree.js +378 -46
  260. package/src/vegetation/stylizedTreeFoliage.js +889 -38
  261. package/src/vegetation/stylizedUnderstory.js +230 -0
  262. package/src/vegetation/treeExport.js +262 -47
  263. package/src/vegetation/treeSurfaceTextures.js +337 -0
  264. package/src/vegetation/vegetationShaders.js +617 -28
  265. package/src/version.js +3 -0
  266. package/src/water/water.js +2 -0
  267. package/src/water/waterBreakerSystem.js +2 -0
  268. package/src/water/waterCurrentField.js +1 -0
  269. package/src/water/waterMaterial.js +3 -0
  270. package/src/water/waterRain.js +2 -0
  271. package/src/water/waterScenePasses.js +170 -7
  272. package/src/water/waterSettings.js +235 -43
  273. package/src/water/waterShoreMaterial.js +16 -2
  274. package/src/water/waterShoreStateField.js +1 -1
  275. package/src/water/waterSplashSystem.js +2 -0
  276. package/src/water/waterStageSettings.js +60 -0
  277. package/src/water/waterSurface.js +144 -4
  278. package/src/water/waterUnderwaterAtmosphere.js +288 -0
  279. package/src/water/waterVegetation.js +20 -4
  280. package/src/worldCollision.js +64 -9
  281. package/types/agents/index.d.ts +1 -0
  282. package/types/agents/sceneStyleOperations.d.ts +484 -0
  283. package/types/asset-policy/catalogLicenses.d.ts +5 -0
  284. package/types/asset-policy/index.d.ts +18 -0
  285. package/types/assetlib/ambientcg.d.ts +81 -0
  286. package/types/assetlib/assetRef.d.ts +26 -0
  287. package/types/assetlib/galleryMaterialFamily.d.ts +13 -0
  288. package/types/assetlib/importedEntry.d.ts +18 -0
  289. package/types/assetlib/index.d.ts +16 -0
  290. package/types/assetlib/kaykit.d.ts +112 -0
  291. package/types/assetlib/kaykitStaticIndex.d.ts +38 -0
  292. package/types/assetlib/loadImported.d.ts +54 -0
  293. package/types/assetlib/opensource3d.d.ts +55 -0
  294. package/types/assetlib/plateau.d.ts +67 -0
  295. package/types/assetlib/plateauLandmarks.d.ts +238 -0
  296. package/types/assetlib/plateauViewer.d.ts +3 -0
  297. package/types/assetlib/polyhaven.d.ts +90 -0
  298. package/types/assetlib/polypizza.d.ts +10 -0
  299. package/types/assetlib/smithsonian.d.ts +9 -0
  300. package/types/assetlib/sources.d.ts +22 -0
  301. package/types/assetlib/zip.d.ts +8 -0
  302. package/types/catalog/manifest.d.ts +26 -0
  303. package/types/catalog/officialCatalog.d.ts +4 -0
  304. package/types/catalog/officialCatalogAssetRuntime.d.ts +2 -0
  305. package/types/catalog/officialCatalogLod.d.ts +5 -0
  306. package/types/catalog/officialCatalogPlacement.d.ts +49 -0
  307. package/types/catalog/officialCatalogProvider.d.ts +7 -0
  308. package/types/character/animationRetarget.d.ts +20 -0
  309. package/types/character/characterRig.d.ts +28 -0
  310. package/types/character/characterRuntime.d.ts +4 -0
  311. package/types/character/freestyleSwimClip.d.ts +5 -0
  312. package/types/character/groundStabilizer.d.ts +55 -0
  313. package/types/character/index.d.ts +10 -0
  314. package/types/character/locomotionActions.d.ts +4 -0
  315. package/types/character/locomotionStateMachine.d.ts +62 -0
  316. package/types/character/mannequinAsset.d.ts +12 -0
  317. package/types/character/mannequinAssetUrl.node.d.ts +1 -0
  318. package/types/character/modelLoader.d.ts +7 -0
  319. package/types/character/walkableCharacterRuntime.d.ts +343 -0
  320. package/types/character/waterInteractionController.d.ts +114 -0
  321. package/types/cloud/ambientSkyBaker.d.ts +18 -0
  322. package/types/cloud/cloudLighting.d.ts +38 -0
  323. package/types/cloud/cloudParams.d.ts +18 -0
  324. package/types/cloud/cloudReprojection.d.ts +15 -0
  325. package/types/cloud/cloudStyle.d.ts +1380 -0
  326. package/types/cloud/cloudStyleSnapshots.d.ts +10 -0
  327. package/types/cloud/cloudVolume.d.ts +43 -0
  328. package/types/cloud/heroCloudRecipe.d.ts +167 -0
  329. package/types/cloud/index.d.ts +12 -0
  330. package/types/cloud/noise/baseShapeVolume.d.ts +86 -0
  331. package/types/cloud/noise/cirrusMap.d.ts +24 -0
  332. package/types/cloud/noise/curlNoise.d.ts +106 -0
  333. package/types/cloud/noise/erosionVolume.d.ts +58 -0
  334. package/types/cloud/noise/noiseVolume.d.ts +63 -0
  335. package/types/cloud/noise/periodicNoise3.d.ts +75 -0
  336. package/types/cloud/noise/weatherMap.d.ts +227 -0
  337. package/types/cloud/paramSchema.d.ts +142 -0
  338. package/types/collisionMetadata.d.ts +11 -0
  339. package/types/core/generation.d.ts +95 -0
  340. package/types/core/materialRoles.d.ts +102 -0
  341. package/types/core/presetDocuments.d.ts +25 -0
  342. package/types/core/systemStylePolicy.d.ts +4 -0
  343. package/types/environment/dayCurves.d.ts +47 -0
  344. package/types/environment/environmentAmbientProbe.d.ts +2 -0
  345. package/types/environment/environmentGroundFieldPass.d.ts +2 -0
  346. package/types/environment/environmentMaterialAdapter.d.ts +42 -0
  347. package/types/environment/environmentMaterialClassifier.d.ts +26 -0
  348. package/types/environment/environmentPlanarReflection.d.ts +3 -0
  349. package/types/environment/environmentPresets.d.ts +171 -0
  350. package/types/environment/environmentRigs.d.ts +13 -0
  351. package/types/environment/environmentSettings.d.ts +161 -0
  352. package/types/environment/environmentShaderMaterials.d.ts +14 -0
  353. package/types/environment/environmentState.d.ts +6 -0
  354. package/types/environment/environmentSunShadowPass.d.ts +2 -0
  355. package/types/environment/environmentTextureResolver.d.ts +30 -0
  356. package/types/environment/environmentTimeOfDay.d.ts +25 -0
  357. package/types/environment/environmentVertexAo.d.ts +18 -0
  358. package/types/environment/index.d.ts +27 -0
  359. package/types/environment/manufacturedMaterialContract.d.ts +129 -0
  360. package/types/environment/manufacturedReflectionProvider.d.ts +3 -0
  361. package/types/environment/scanAssetStylize.d.ts +43 -0
  362. package/types/environment/surfaceMaterialModes.d.ts +14 -0
  363. package/types/environment/toonLabEnvironmentMaterials.d.ts +139 -0
  364. package/types/environment/toonLabMaterialPassCoupling.d.ts +7 -0
  365. package/types/environment/toonLabNormalIntegration.d.ts +29 -0
  366. package/types/environment/toonLabRockMaterialResolver.d.ts +270 -0
  367. package/types/environment/toonLabSourceDefaultLit.d.ts +136 -0
  368. package/types/environment/toonLabSourceLibrary.d.ts +19 -0
  369. package/types/environment/toonLabSourceMaterials.d.ts +14 -0
  370. package/types/environment/toonLabSourceSubsurfaceLighting.d.ts +85 -0
  371. package/types/environment/toonLabSourceTemporal.d.ts +20 -0
  372. package/types/environment/toonLabSurfaceLighting.d.ts +136 -0
  373. package/types/environment/toonLabTextureReadiness.d.ts +8 -0
  374. package/types/environment/toonLabTreeMaterials.d.ts +7 -0
  375. package/types/environment/transparentMaterialProfile.d.ts +76 -0
  376. package/types/environment/urbanPropMaterial.d.ts +25 -0
  377. package/types/ground-shader/groundPrintLayer.d.ts +4 -0
  378. package/types/ground-shader/groundShaderMaterial.d.ts +11 -0
  379. package/types/ground-shader/groundShaderSettings.d.ts +90 -0
  380. package/types/ground-shader/index.d.ts +3 -0
  381. package/types/index.d.ts +1502 -0
  382. package/types/lighting/callMeSenseiLightingContract.d.ts +14 -0
  383. package/types/lighting/colorIntensity.d.ts +44 -0
  384. package/types/lighting/index.d.ts +12 -0
  385. package/types/lighting/lightDescriptors.d.ts +803 -0
  386. package/types/lighting/lightingCapabilities.d.ts +85 -0
  387. package/types/lighting/lightingDocuments.d.ts +140 -0
  388. package/types/lighting/lightingFixtures.d.ts +171 -0
  389. package/types/lighting/lightingGenerator.d.ts +403 -0
  390. package/types/lighting/lightingPresets.d.ts +264 -0
  391. package/types/lighting/lightingRuntime.d.ts +401 -0
  392. package/types/lighting/lightingStyle.d.ts +156 -0
  393. package/types/lighting/lightingSystem.d.ts +433 -0
  394. package/types/lighting/toonLabExport.d.ts +46 -0
  395. package/types/lighting/utils.d.ts +18 -0
  396. package/types/loaders/index.d.ts +1 -0
  397. package/types/post/index.d.ts +2 -0
  398. package/types/post/postGenerator.d.ts +282 -0
  399. package/types/post/postProcessing.d.ts +16 -0
  400. package/types/react/index.d.ts +1765 -0
  401. package/types/renderer/index.d.ts +1 -0
  402. package/types/renderer/rendererConfiguration.d.ts +8 -0
  403. package/types/rock-shader/index.d.ts +3 -0
  404. package/types/rock-shader/rockMaterial.d.ts +18 -0
  405. package/types/rock-shader/rockShaderRuntime.d.ts +8 -0
  406. package/types/rock-shader/rockShaderSettings.d.ts +170 -0
  407. package/types/rockgen/export/glbExport.d.ts +58 -0
  408. package/types/rockgen/heightfield/heightfieldErosion.d.ts +10 -0
  409. package/types/rockgen/heightfield/heightfieldPatch.d.ts +15 -0
  410. package/types/rockgen/heightfield/stylizedErosionSim.d.ts +41 -0
  411. package/types/rockgen/index.d.ts +11 -0
  412. package/types/rockgen/lod/index.d.ts +6 -0
  413. package/types/rockgen/lod/rockLodMetrics.d.ts +62 -0
  414. package/types/rockgen/lod/rockLodPlanner.d.ts +86 -0
  415. package/types/rockgen/lod/rockLodPolicy.d.ts +76 -0
  416. package/types/rockgen/lod/rockLodRuntime.d.ts +95 -0
  417. package/types/rockgen/lod/rockLodSimplifier.d.ts +15 -0
  418. package/types/rockgen/lod/rockLodValidation.d.ts +16 -0
  419. package/types/rockgen/mesh/meshAttributes.d.ts +32 -0
  420. package/types/rockgen/mesh/meshDocument.d.ts +40 -0
  421. package/types/rockgen/mesh/surfaceNets.d.ts +42 -0
  422. package/types/rockgen/noise/cellularNoise3.d.ts +24 -0
  423. package/types/rockgen/noise/prng.d.ts +16 -0
  424. package/types/rockgen/noise/simplexNoise3.d.ts +2 -0
  425. package/types/rockgen/noise/valueNoise3.d.ts +12 -0
  426. package/types/rockgen/rockDocument.d.ts +215 -0
  427. package/types/rockgen/rockHelpers.d.ts +2 -0
  428. package/types/rockgen/rockgenPresets.d.ts +10 -0
  429. package/types/rockgen/rockgenSettings.d.ts +531 -0
  430. package/types/rockgen/sdf/fieldCompiler.d.ts +20 -0
  431. package/types/rockgen/sdf/sculptEdits.d.ts +30 -0
  432. package/types/rockgen/sdf/sdfModifiers.d.ts +19 -0
  433. package/types/rockgen/sdf/sdfOps.d.ts +8 -0
  434. package/types/rockgen/sdf/sdfPrimitives.d.ts +22 -0
  435. package/types/runtime/index.d.ts +3 -0
  436. package/types/runtime/sceneCollisionRuntime.d.ts +94 -0
  437. package/types/runtime/sceneSurfaceRuntime.d.ts +90 -0
  438. package/types/runtime/sceneUpdateScheduler.d.ts +28 -0
  439. package/types/shaders-tsl/anime.d.ts +9 -0
  440. package/types/shaders-tsl/chunks/character-color.d.ts +6 -0
  441. package/types/shaders-tsl/chunks/character-highlights.d.ts +12 -0
  442. package/types/shaders-tsl/chunks/character-lighting.d.ts +20 -0
  443. package/types/shaders-tsl/chunks/character-material-maps.d.ts +18 -0
  444. package/types/shaders-tsl/chunks/character-roles.d.ts +21 -0
  445. package/types/shaders-tsl/chunks/character-scene-lights.d.ts +48 -0
  446. package/types/shaders-tsl/chunks/character-shadow-color.d.ts +5 -0
  447. package/types/shaders-tsl/chunks/character-skinning.d.ts +23 -0
  448. package/types/shaders-tsl/chunks/environment-color.d.ts +9 -0
  449. package/types/shaders-tsl/chunks/environment-debug.d.ts +24 -0
  450. package/types/shaders-tsl/chunks/environment-ground-field.d.ts +40 -0
  451. package/types/shaders-tsl/chunks/environment-lighting.d.ts +22 -0
  452. package/types/shaders-tsl/chunks/environment-state.d.ts +42 -0
  453. package/types/shaders-tsl/chunks/environment-sun-shadow.d.ts +19 -0
  454. package/types/shaders-tsl/chunks/foliage-fog.d.ts +21 -0
  455. package/types/shaders-tsl/chunks/normalized-hue.d.ts +1 -0
  456. package/types/shaders-tsl/chunks/pass-depth-color.d.ts +20 -0
  457. package/types/shaders-tsl/chunks/projected-water-caustics.d.ts +24 -0
  458. package/types/shaders-tsl/chunks/scene-depth-color-pass.d.ts +39 -0
  459. package/types/shaders-tsl/chunks/stylized-cloud-shadow.d.ts +9 -0
  460. package/types/shaders-tsl/chunks/vegetation-style.d.ts +60 -0
  461. package/types/shaders-tsl/chunks/water-color.d.ts +15 -0
  462. package/types/shaders-tsl/chunks/water-common.d.ts +9 -0
  463. package/types/shaders-tsl/chunks/water-foam.d.ts +8 -0
  464. package/types/shaders-tsl/chunks/water-lighting.d.ts +9 -0
  465. package/types/shaders-tsl/chunks/water-ripple.d.ts +8 -0
  466. package/types/shaders-tsl/chunks/water-shore-state.d.ts +7 -0
  467. package/types/shaders-tsl/chunks/water-waves.d.ts +18 -0
  468. package/types/shaders-tsl/chunks/world-noise.d.ts +4 -0
  469. package/types/shaders-tsl/environment-ao-overlay.d.ts +5 -0
  470. package/types/shaders-tsl/environment.d.ts +34 -0
  471. package/types/shaders-tsl/flower.d.ts +6 -0
  472. package/types/shaders-tsl/grass.d.ts +4 -0
  473. package/types/shaders-tsl/post-composite.d.ts +25 -0
  474. package/types/shaders-tsl/sky.d.ts +4 -0
  475. package/types/shaders-tsl/tree-leaf.d.ts +2 -0
  476. package/types/shaders-tsl/water-breaker.d.ts +15 -0
  477. package/types/shaders-tsl/water-kelp.d.ts +5 -0
  478. package/types/shaders-tsl/water-rain.d.ts +10 -0
  479. package/types/shaders-tsl/water-shore-state-simulation.d.ts +12 -0
  480. package/types/shaders-tsl/water-simulation.d.ts +5 -0
  481. package/types/shaders-tsl/water-splash.d.ts +12 -0
  482. package/types/shaders-tsl/water.d.ts +22 -0
  483. package/types/shaders-tsl/woody-surface.d.ts +3 -0
  484. package/types/sky/atmosphereDome.d.ts +2 -0
  485. package/types/sky/atmosphereParams.d.ts +185 -0
  486. package/types/sky/atmosphereScattering.d.ts +11 -0
  487. package/types/sky/atmosphereSky.d.ts +2 -0
  488. package/types/sky/cloudShadow.d.ts +68 -0
  489. package/types/sky/godRays.d.ts +5 -0
  490. package/types/sky/index.d.ts +18 -0
  491. package/types/sky/nightSky.d.ts +22 -0
  492. package/types/sky/renderLayers.d.ts +59 -0
  493. package/types/sky/sceneOverrideLayers.d.ts +10 -0
  494. package/types/sky/skyColor.d.ts +704 -0
  495. package/types/sky/skyDayCycle.d.ts +86 -0
  496. package/types/sky/skyParams.d.ts +3407 -0
  497. package/types/sky/skyPresets.d.ts +160 -0
  498. package/types/sky/skyQuality.d.ts +21 -0
  499. package/types/sky/skyQualityTiers.d.ts +223 -0
  500. package/types/sky/skyShaderSettings.d.ts +152 -0
  501. package/types/sky/skyStyleSnapshots.d.ts +11 -0
  502. package/types/sky/skySystem.d.ts +3 -0
  503. package/types/sky/skyTimeKeyframes.d.ts +230 -0
  504. package/types/sky/stylizedSky.d.ts +341 -0
  505. package/types/sky/sunDriver.d.ts +15 -0
  506. package/types/sky/timeOfDay.d.ts +145 -0
  507. package/types/styles/animeGameProfile.d.ts +27 -0
  508. package/types/styles/index.d.ts +17 -0
  509. package/types/styles/manufacturedStyleLabeling.d.ts +119 -0
  510. package/types/styles/sceneLayerDocuments.d.ts +145 -0
  511. package/types/styles/sceneLookComposition.d.ts +53 -0
  512. package/types/styles/sceneQualityApplication.d.ts +34 -0
  513. package/types/styles/sceneQualityProfiles.d.ts +13 -0
  514. package/types/styles/sceneStyleAudit.d.ts +80 -0
  515. package/types/styles/sceneStyleRuntime.d.ts +1782 -0
  516. package/types/styles/styleAdapters.d.ts +14 -0
  517. package/types/styles/styleApplication.d.ts +47 -0
  518. package/types/styles/styleBundle.d.ts +19 -0
  519. package/types/styles/styleBundleProvider.d.ts +44 -0
  520. package/types/styles/styleDomains.d.ts +18 -0
  521. package/types/styles/styleInspector.d.ts +59 -0
  522. package/types/styles/styleMaterialContract.d.ts +46 -0
  523. package/types/styles/styleMetadata.d.ts +11 -0
  524. package/types/styles/styleTargetDiscovery.d.ts +48 -0
  525. package/types/styles/styleTargetLabels.d.ts +32 -0
  526. package/types/styles/styleTargetMaterialCoverage.d.ts +20 -0
  527. package/types/styles/styleTransaction.d.ts +10 -0
  528. package/types/styles/styleTypes.d.ts +66 -0
  529. package/types/texgen/evaluateTexture.d.ts +40 -0
  530. package/types/texgen/index.d.ts +7 -0
  531. package/types/texgen/noise2.d.ts +46 -0
  532. package/types/texgen/textureAi.d.ts +6 -0
  533. package/types/texgen/textureGenerators.d.ts +261 -0
  534. package/types/texgen/texturePresets.d.ts +45 -0
  535. package/types/texgen/textureSettings.d.ts +121 -0
  536. package/types/texgen/textureThree.d.ts +13 -0
  537. package/types/toon/characterRenderPasses.d.ts +3 -0
  538. package/types/toon/index.d.ts +3 -0
  539. package/types/toon/settings/alphaSettings.d.ts +125 -0
  540. package/types/toon/settings/averageShadowSettings.d.ts +39 -0
  541. package/types/toon/settings/baseTextureSettings.d.ts +39 -0
  542. package/types/toon/settings/celShadeSettings.d.ts +37 -0
  543. package/types/toon/settings/contactShadowSettings.d.ts +30 -0
  544. package/types/toon/settings/eyeHighlightSettings.d.ts +55 -0
  545. package/types/toon/settings/faceLightingSettings.d.ts +32 -0
  546. package/types/toon/settings/furSettings.d.ts +23 -0
  547. package/types/toon/settings/glitterSettings.d.ts +43 -0
  548. package/types/toon/settings/hairHighlightSettings.d.ts +89 -0
  549. package/types/toon/settings/indirectLightSettings.d.ts +43 -0
  550. package/types/toon/settings/localLightSettings.d.ts +46 -0
  551. package/types/toon/settings/materialMapSettings.d.ts +86 -0
  552. package/types/toon/settings/outlineSettings.d.ts +125 -0
  553. package/types/toon/settings/perspectiveRemovalSettings.d.ts +14 -0
  554. package/types/toon/settings/rimLightSettings.d.ts +79 -0
  555. package/types/toon/settings/sceneShadowSettings.d.ts +32 -0
  556. package/types/toon/settings/selfShadowSettings.d.ts +44 -0
  557. package/types/toon/settings/shadowColorSettings.d.ts +77 -0
  558. package/types/toon/settings/skinToneSettings.d.ts +30 -0
  559. package/types/toon/settings/specularSettings.d.ts +96 -0
  560. package/types/toon/settings/stickerSettings.d.ts +40 -0
  561. package/types/toon/toonMaterialAdapter.d.ts +883 -0
  562. package/types/toon/toonSettings.d.ts +1182 -0
  563. package/types/vegetation/branchTree.d.ts +10 -0
  564. package/types/vegetation/callMeSenseiGrass.d.ts +8 -0
  565. package/types/vegetation/compiledTree.d.ts +75 -0
  566. package/types/vegetation/contactShadowField.d.ts +26 -0
  567. package/types/vegetation/flowerSpecies.d.ts +107 -0
  568. package/types/vegetation/grass.d.ts +4 -0
  569. package/types/vegetation/grassClump.d.ts +7 -0
  570. package/types/vegetation/grassPalettes.d.ts +29 -0
  571. package/types/vegetation/importedVegetationMaterial.d.ts +13 -0
  572. package/types/vegetation/index.d.ts +216 -0
  573. package/types/vegetation/legacyTreePresets.d.ts +22 -0
  574. package/types/vegetation/scatter.d.ts +12 -0
  575. package/types/vegetation/stylizedBush.d.ts +2 -0
  576. package/types/vegetation/stylizedFlower.d.ts +2 -0
  577. package/types/vegetation/stylizedFlowers.d.ts +8 -0
  578. package/types/vegetation/stylizedForest.d.ts +3 -0
  579. package/types/vegetation/stylizedGrass.d.ts +21 -0
  580. package/types/vegetation/stylizedTree.d.ts +19 -0
  581. package/types/vegetation/stylizedTreeFoliage.d.ts +18 -0
  582. package/types/vegetation/stylizedUnderstory.d.ts +50 -0
  583. package/types/vegetation/treeExport.d.ts +6 -0
  584. package/types/vegetation/treeSurfaceTextures.d.ts +72 -0
  585. package/types/vegetation/vegetationShaders.d.ts +74 -0
  586. package/types/version.d.ts +1 -0
  587. package/types/water/index.d.ts +1 -0
  588. package/types/water/sceneOverrideLayers.d.ts +16 -0
  589. package/types/water/water.d.ts +17 -0
  590. package/types/water/waterBreakerSystem.d.ts +46 -0
  591. package/types/water/waterCurrentField.d.ts +115 -0
  592. package/types/water/waterInteraction.d.ts +21 -0
  593. package/types/water/waterMaterial.d.ts +60 -0
  594. package/types/water/waterNearshorePhase.d.ts +5 -0
  595. package/types/water/waterRain.d.ts +17 -0
  596. package/types/water/waterRippleSimulation.d.ts +52 -0
  597. package/types/water/waterScenePasses.d.ts +70 -0
  598. package/types/water/waterSettings.d.ts +648 -0
  599. package/types/water/waterShoreMaterial.d.ts +3 -0
  600. package/types/water/waterShoreStateField.d.ts +2 -0
  601. package/types/water/waterSplashSystem.d.ts +2 -0
  602. package/types/water/waterStageSettings.d.ts +9 -0
  603. package/types/water/waterSurface.d.ts +2 -0
  604. package/types/water/waterUnderwaterAtmosphere.d.ts +103 -0
  605. package/types/water/waterVegetation.d.ts +16 -0
  606. package/types/worldCollision.d.ts +22 -0
  607. package/AGENTS.md +0 -254
  608. package/ATTRIBUTION.md +0 -78
  609. package/docs/characters.md +0 -144
  610. package/docs/debug-panel.md +0 -126
  611. package/docs/docs.css +0 -589
  612. package/docs/environment.md +0 -186
  613. package/docs/getting-started.md +0 -180
  614. package/docs/index.html +0 -14
  615. package/docs/lab-architecture.md +0 -100
  616. package/docs/lighting.md +0 -825
  617. package/docs/main.jsx +0 -739
  618. package/docs/mcp.md +0 -97
  619. package/docs/post-processing.md +0 -98
  620. package/docs/settings-reference.md +0 -1878
  621. package/docs/shader-constants.md +0 -77
  622. package/docs/sky.md +0 -182
  623. package/docs/style-labs.md +0 -309
  624. package/docs/texture-lab.md +0 -135
  625. package/docs/toon-shading.md +0 -183
  626. package/docs/tsl-conventions.md +0 -167
  627. package/docs/vegetation-sky.md +0 -275
  628. package/docs/water.md +0 -430
  629. package/docs/weather.md +0 -200
  630. package/docs/world-scale.md +0 -111
  631. package/mcp/style-lab-tools.mjs +0 -371
  632. package/src/ambientfx/INTEGRATION.md +0 -164
  633. package/src/ambientfx/ambientFxPresets.js +0 -83
  634. package/src/ambientfx/ambientFxSettings.js +0 -368
  635. package/src/ambientfx/emitters.js +0 -169
  636. package/src/ambientfx/index.js +0 -5
  637. package/src/ambientfx/particleBackbone.js +0 -493
  638. package/src/ambientfx/stylizedAmbientFx.js +0 -450
  639. package/src/biome/biomeGenerator.js +0 -385
  640. package/src/biome/biomeRuntime.js +0 -299
  641. package/src/biome/index.js +0 -2
  642. package/src/buildinggen/buildingAsset.js +0 -44
  643. package/src/buildinggen/buildingGrammar.js +0 -311
  644. package/src/buildinggen/buildingMesh.js +0 -451
  645. package/src/buildinggen/buildingPresets.js +0 -46
  646. package/src/buildinggen/buildingRecipe.js +0 -100
  647. package/src/buildinggen/buildingSettings.js +0 -238
  648. package/src/buildinggen/index.js +0 -6
  649. package/src/camera/cameraDirector.js +0 -157
  650. package/src/camera/cameraGenerator.js +0 -367
  651. package/src/camera/cameraRig.js +0 -570
  652. package/src/camera/cameraSettings.js +0 -236
  653. package/src/camera/index.js +0 -7
  654. package/src/catalog/builtinEntries.js +0 -245
  655. package/src/catalog/catalog.js +0 -210
  656. package/src/catalog/index.js +0 -3
  657. package/src/core/shaderBackend.js +0 -24
  658. package/src/debrisgen/debrisFields.js +0 -544
  659. package/src/debrisgen/debrisGenerator.js +0 -1929
  660. package/src/debrisgen/debrisPalettes.js +0 -71
  661. package/src/debrisgen/debrisPhysics.js +0 -198
  662. package/src/debrisgen/debrisPresets.js +0 -162
  663. package/src/debrisgen/debrisSettings.js +0 -333
  664. package/src/debrisgen/debrisTextures.js +0 -380
  665. package/src/debrisgen/index.js +0 -5
  666. package/src/debug/fieldValues.js +0 -95
  667. package/src/debug/index.js +0 -7
  668. package/src/debug/settingsPanel.js +0 -170
  669. package/src/fauna/INTEGRATION.md +0 -174
  670. package/src/fauna/boids.js +0 -861
  671. package/src/fauna/faunaBodies.js +0 -492
  672. package/src/fauna/faunaPresets.js +0 -52
  673. package/src/fauna/faunaSettings.js +0 -525
  674. package/src/fauna/index.js +0 -5
  675. package/src/fauna/stylizedFauna.js +0 -395
  676. package/src/game-feel/gameFeelGenerator.js +0 -402
  677. package/src/game-feel/gameFeelRuntime.js +0 -549
  678. package/src/game-feel/index.js +0 -2
  679. package/src/motion/index.js +0 -5
  680. package/src/motion/motionClip.js +0 -441
  681. package/src/motion/motionController.js +0 -628
  682. package/src/motion/motionDocuments.js +0 -225
  683. package/src/motion/motionGraph.js +0 -307
  684. package/src/motion/motionSettings.js +0 -222
  685. package/src/pathgen/index.js +0 -7
  686. package/src/pathgen/pathBridge.js +0 -232
  687. package/src/pathgen/pathPresets.js +0 -35
  688. package/src/pathgen/pathRibbon.js +0 -410
  689. package/src/pathgen/pathRouter.js +0 -380
  690. package/src/pathgen/pathSettings.js +0 -335
  691. package/src/pathgen/pathTextures.js +0 -123
  692. package/src/pathgen/stylizedPaths.js +0 -453
  693. package/src/propgen/generatorsWave1.js +0 -379
  694. package/src/propgen/generatorsWave2.js +0 -462
  695. package/src/propgen/index.js +0 -5
  696. package/src/propgen/propAsset.js +0 -323
  697. package/src/propgen/propParts.js +0 -170
  698. package/src/propgen/propPlacement.js +0 -459
  699. package/src/propgen/propPresets.js +0 -82
  700. package/src/propgen/propSettings.js +0 -395
  701. package/src/soundscape/index.js +0 -4
  702. package/src/soundscape/soundscapeGenerator.js +0 -179
  703. package/src/soundscape/soundscapeRuntime.js +0 -806
  704. package/src/soundscape/soundscapeSettings.js +0 -292
  705. package/src/stylizedTerrain.js +0 -631
  706. package/src/stylizedWorld.js +0 -903
  707. package/src/vegetation/treeRecipe.js +0 -647
  708. package/src/vfxgen/INTEGRATION.md +0 -145
  709. package/src/vfxgen/core/burstBackbone.js +0 -380
  710. package/src/vfxgen/core/projectileCore.js +0 -92
  711. package/src/vfxgen/core/spriteShapes.js +0 -98
  712. package/src/vfxgen/core/trailRibbon.js +0 -272
  713. package/src/vfxgen/core/vfxRandom.js +0 -29
  714. package/src/vfxgen/effects/emitHelpers.js +0 -37
  715. package/src/vfxgen/effects/magicEffects.js +0 -162
  716. package/src/vfxgen/effects/movementEffects.js +0 -87
  717. package/src/vfxgen/effects/weaponEffects.js +0 -118
  718. package/src/vfxgen/index.js +0 -18
  719. package/src/vfxgen/moves/moveController.js +0 -146
  720. package/src/vfxgen/moves/moveLibrary.js +0 -335
  721. package/src/vfxgen/vfxPresets.js +0 -98
  722. package/src/vfxgen/vfxSettings.js +0 -384
  723. package/src/vfxgen/vfxSystem.js +0 -449
  724. package/src/vfxgen/weapons/stylizedWeapons.js +0 -137
  725. package/src/villagegen/index.js +0 -4
  726. package/src/villagegen/stylizedVillage.js +0 -490
  727. package/src/villagegen/villageArchetypes.js +0 -160
  728. package/src/villagegen/villageNames.js +0 -40
  729. package/src/villagegen/villageSites.js +0 -105
  730. package/src/weather/index.js +0 -6
  731. package/src/weather/weatherPrecipitation.js +0 -221
  732. package/src/weather/weatherPresets.js +0 -258
  733. package/src/weather/weatherSettings.js +0 -269
  734. package/src/weather/weatherSystem.js +0 -871
  735. package/src/worldMinimap.js +0 -214
  736. package/src/worldPresets.js +0 -125
@@ -0,0 +1,289 @@
1
+ // Curl noise — the divergence-free vector field that advects cloud edges into
2
+ // wisps. Displacing a sample position by an arbitrary noise vector pumps
3
+ // density in and out of the cloud (the field has sources and sinks), so edges
4
+ // bulge and pop. The curl of a vector potential is divergence-free by
5
+ // construction, so advecting along it shears and folds the cloud without
6
+ // creating or destroying any of it — the reason curl noise, not plain noise, is
7
+ // what makes a wisp look torn from the body rather than pasted onto it.
8
+ //
9
+ // Potential: three decorrelated periodic Perlin FBM fields. Curl: collocated
10
+ // central differences of those. Because the same difference stencil is used for
11
+ // every partial, the mixed second derivatives cancel exactly and the discrete
12
+ // divergence is zero to floating-point rounding — not just to O(h²).
13
+ //
14
+ // Encoding: the volume packs curl * 0.5 + 0.5 into RGB and the vector's length
15
+ // into A, so a shader can modulate wisp strength by field energy from the same
16
+ // fetch. Decode through decodeCurlNoise(), or take the ready-made advection
17
+ // offset from curlNoiseOffsetNode(), rather than unpacking by hand; the scale
18
+ // the CPU normalized by is this module's business, not the raymarcher's.
19
+ //
20
+ // Both channels share one normalization scale, so A is exactly the length of the
21
+ // vector RGB decodes to. That scale comes from the probed peak *length*, not the
22
+ // peak component: a length reaches up to sqrt(3) times its largest component, so
23
+ // normalizing by the component peak overflowed A and clipped it.
24
+
25
+ import {
26
+ Fn,
27
+ texture3D,
28
+ vec3,
29
+ } from 'three/tsl';
30
+
31
+ import { hashSeed } from '../../core/generation.js';
32
+ import { hashCombine } from '../../rockgen/noise/prng.js';
33
+ import {
34
+ createNoiseVolumeTexture,
35
+ encodeSnorm8,
36
+ encodeUnorm8,
37
+ noiseVolumeKey,
38
+ resolveNoiseDims,
39
+ warnNoiseVolumeOnce,
40
+ } from './noiseVolume.js';
41
+ import { createPeriodicPerlinFbm3 } from './periodicNoise3.js';
42
+
43
+ /** Default resolution. Curl is a low-frequency advection field; 32³ is ample. */
44
+ export const CURL_NOISE_DEFAULT_DIMS = 32;
45
+
46
+ /**
47
+ * Potential-field plan. `epsilon` is the central-difference step in tile units:
48
+ * small enough to read as a derivative, large enough that the difference of two
49
+ * nearly equal FBM samples keeps its significant digits.
50
+ */
51
+ export const CURL_NOISE_PLAN = Object.freeze({
52
+ epsilon: 1 / 256,
53
+ gain: 0.6,
54
+ lacunarity: 2,
55
+ octaves: 3,
56
+ period: 3,
57
+ });
58
+
59
+ // The normalization scale is measured on a fixed probe grid rather than on the
60
+ // output grid, so the same seed yields the same field at every resolution — a
61
+ // 16³ curl volume must not be a differently scaled field from the 64³ one.
62
+ const NORMALIZATION_PROBE_DIMS = 32;
63
+ // Headroom over the probed peak, and the reason the probe can be fixed at all: a
64
+ // finer output grid samples points the probe never visits, so it finds higher
65
+ // values. Measured against the 32³ probe's peak length, the true peak runs 8.5%
66
+ // higher on a 64³ output grid and 8.8% higher on a 128³ one, and a 400k-point
67
+ // off-lattice sweep tops out at 6.8% — so the growth flattens off well inside
68
+ // 15%, resolveNoiseDims' 256³ ceiling included.
69
+ const NORMALIZATION_HEADROOM = 1.15;
70
+
71
+ const volumeCache = new Map();
72
+
73
+ /**
74
+ * Builds the divergence-free field.
75
+ *
76
+ * `sample(x, y, z)` takes tile coordinates and writes the normalized curl into
77
+ * `out`, returning it — components land in about [-1, 1]. `curl()` returns the
78
+ * same vector unnormalized, which is what the divergence check needs.
79
+ */
80
+ export function createCurlNoiseField({ seed = 1, plan = {} } = {}) {
81
+ const rootSeed = hashSeed(seed);
82
+ const settings = { ...CURL_NOISE_PLAN, ...plan };
83
+ const epsilon = Math.max(1e-5, Number(settings.epsilon) || CURL_NOISE_PLAN.epsilon);
84
+ const fbmOptions = {
85
+ // The potential is evaluated analytically at arbitrary offsets, not on the
86
+ // output grid, so it carries no band limit of its own. The curl's own
87
+ // frequency content is set by `period` and stays well inside 32³.
88
+ dim: Infinity,
89
+ gain: settings.gain,
90
+ lacunarity: settings.lacunarity,
91
+ octaves: settings.octaves,
92
+ period: settings.period,
93
+ };
94
+ // Three potential components, seeded apart so the curl does not degenerate
95
+ // toward a single axis.
96
+ const psi = [
97
+ createPeriodicPerlinFbm3(hashCombine(rootSeed, 0x9e37), fbmOptions),
98
+ createPeriodicPerlinFbm3(hashCombine(rootSeed, 0x85eb), fbmOptions),
99
+ createPeriodicPerlinFbm3(hashCombine(rootSeed, 0xc2b2), fbmOptions),
100
+ ];
101
+ const inverseStep = 1 / (2 * epsilon);
102
+
103
+ function curl(x, y, z, out) {
104
+ const dy3 = (psi[2].sample(x, y + epsilon, z) - psi[2].sample(x, y - epsilon, z)) * inverseStep;
105
+ const dz2 = (psi[1].sample(x, y, z + epsilon) - psi[1].sample(x, y, z - epsilon)) * inverseStep;
106
+ const dz1 = (psi[0].sample(x, y, z + epsilon) - psi[0].sample(x, y, z - epsilon)) * inverseStep;
107
+ const dx3 = (psi[2].sample(x + epsilon, y, z) - psi[2].sample(x - epsilon, y, z)) * inverseStep;
108
+ const dx2 = (psi[1].sample(x + epsilon, y, z) - psi[1].sample(x - epsilon, y, z)) * inverseStep;
109
+ const dy1 = (psi[0].sample(x, y + epsilon, z) - psi[0].sample(x, y - epsilon, z)) * inverseStep;
110
+ out.x = dy3 - dz2;
111
+ out.y = dz1 - dx3;
112
+ out.z = dx2 - dy1;
113
+ return out;
114
+ }
115
+
116
+ // Probe for the peak so the 8-bit encoding uses its range without clipping the
117
+ // tails. Both peaks are measured; only the length one sets the scale.
118
+ const probe = { x: 0, y: 0, z: 0 };
119
+ let componentPeak = 0;
120
+ let lengthPeak = 0;
121
+ const inverseProbe = 1 / NORMALIZATION_PROBE_DIMS;
122
+ for (let z = 0; z < NORMALIZATION_PROBE_DIMS; z += 1) {
123
+ for (let y = 0; y < NORMALIZATION_PROBE_DIMS; y += 1) {
124
+ for (let x = 0; x < NORMALIZATION_PROBE_DIMS; x += 1) {
125
+ curl((x + 0.5) * inverseProbe, (y + 0.5) * inverseProbe, (z + 0.5) * inverseProbe, probe);
126
+ componentPeak = Math.max(
127
+ componentPeak, Math.abs(probe.x), Math.abs(probe.y), Math.abs(probe.z),
128
+ );
129
+ lengthPeak = Math.max(
130
+ lengthPeak,
131
+ Math.sqrt(probe.x * probe.x + probe.y * probe.y + probe.z * probe.z),
132
+ );
133
+ }
134
+ }
135
+ }
136
+ // Normalize by the *length* peak, because the length is what the A channel
137
+ // encodes and a length runs up to sqrt(3) times its largest component. Scaling
138
+ // by the component peak fit RGB and overflowed A, and a clipped |curl| is no
139
+ // longer the length of the RGB it ships with. One shared scale keeps
140
+ // `a === length(decode(rgb))` exact; it costs the components about a tenth of
141
+ // their range, which is cheaper than an inconsistent encoding.
142
+ const scale = 1 / (lengthPeak * NORMALIZATION_HEADROOM || 1);
143
+
144
+ return {
145
+ componentPeak,
146
+ curl,
147
+ epsilon,
148
+ lengthPeak,
149
+ sample(x, y, z, out = { x: 0, y: 0, z: 0 }) {
150
+ curl(x, y, z, out);
151
+ out.x *= scale;
152
+ out.y *= scale;
153
+ out.z *= scale;
154
+ return out;
155
+ },
156
+ scale,
157
+ seed: rootSeed,
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Bakes the RGBA8 curl volume. Returned separately from the texture so the
163
+ * divergence and tiling checks can read the numbers without a renderer.
164
+ */
165
+ export function createCurlNoiseData({
166
+ dims = CURL_NOISE_DEFAULT_DIMS,
167
+ seed = 1,
168
+ plan = {},
169
+ } = {}) {
170
+ const size = resolveNoiseDims(dims, CURL_NOISE_DEFAULT_DIMS);
171
+ const field = createCurlNoiseField({ plan, seed });
172
+ const data = new Uint8Array(size.x * size.y * size.z * 4);
173
+ const vector = { x: 0, y: 0, z: 0 };
174
+ const invX = 1 / size.x;
175
+ const invY = 1 / size.y;
176
+ const invZ = 1 / size.z;
177
+ let cursor = 0;
178
+ // Watchdog on the fixed probe grid's assumption: the output grid is free to
179
+ // land on a higher field value than the probe found, and if the headroom ever
180
+ // fails to cover that the encoders clamp silently. Report it instead.
181
+ let peakLength = 0;
182
+ let clippedTexels = 0;
183
+ for (let z = 0; z < size.z; z += 1) {
184
+ const w = (z + 0.5) * invZ;
185
+ for (let y = 0; y < size.y; y += 1) {
186
+ const v = (y + 0.5) * invY;
187
+ for (let x = 0; x < size.x; x += 1) {
188
+ const u = (x + 0.5) * invX;
189
+ field.sample(u, v, w, vector);
190
+ const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
191
+ if (length > peakLength) peakLength = length;
192
+ if (length > 1) clippedTexels += 1;
193
+ data[cursor] = encodeSnorm8(vector.x);
194
+ data[cursor + 1] = encodeSnorm8(vector.y);
195
+ data[cursor + 2] = encodeSnorm8(vector.z);
196
+ data[cursor + 3] = encodeUnorm8(length);
197
+ cursor += 4;
198
+ }
199
+ }
200
+ }
201
+ if (clippedTexels > 0) {
202
+ warnNoiseVolumeOnce(
203
+ `curl-clip:${size.x}x${size.y}x${size.z}`,
204
+ `[curlNoise] |curl| peaked at ${peakLength.toFixed(3)} on the `
205
+ + `${size.x}x${size.y}x${size.z} output grid, above the 1.0 the A channel can hold, so `
206
+ + `${clippedTexels} texel(s) clipped. The ${NORMALIZATION_PROBE_DIMS}³ probe grid `
207
+ + 'under-estimated the field peak at this resolution.',
208
+ );
209
+ }
210
+
211
+ return {
212
+ clippedTexels,
213
+ data,
214
+ dims: size,
215
+ field,
216
+ peakLength,
217
+ seed: field.seed,
218
+ };
219
+ }
220
+
221
+ /** Bakes an uncached curl volume. Callers own dispose(). */
222
+ export function createCurlNoiseVolume({
223
+ dims = CURL_NOISE_DEFAULT_DIMS,
224
+ seed = 1,
225
+ plan = {},
226
+ } = {}) {
227
+ const baked = createCurlNoiseData({ dims, plan, seed });
228
+ const texture = createNoiseVolumeTexture(
229
+ baked.data,
230
+ baked.dims,
231
+ `ToonLabCloudCurl${baked.dims.x}x${baked.dims.y}x${baked.dims.z}`,
232
+ );
233
+ texture.userData.toonlabCloudNoise = {
234
+ componentPeak: baked.field.componentPeak,
235
+ dims: baked.dims,
236
+ encoding: 'rgb = curl * 0.5 + 0.5, a = |curl|',
237
+ kind: 'curl',
238
+ lengthPeak: baked.field.lengthPeak,
239
+ peakLength: baked.peakLength,
240
+ scale: baked.field.scale,
241
+ seed: baked.seed,
242
+ };
243
+ return texture;
244
+ }
245
+
246
+ /** Cached curl volume, keyed by resolution and seed. */
247
+ export function getCurlNoiseVolume({
248
+ dims = CURL_NOISE_DEFAULT_DIMS,
249
+ seed = 1,
250
+ plan = {},
251
+ } = {}) {
252
+ const size = resolveNoiseDims(dims, CURL_NOISE_DEFAULT_DIMS);
253
+ // The plan joins the key: a custom potential is a different field, and
254
+ // returning the default one for it would be a silent wrong answer.
255
+ const key = `${noiseVolumeKey(size, hashSeed(seed))}:${hashSeed(JSON.stringify({ ...CURL_NOISE_PLAN, ...plan }))}`;
256
+ const cached = volumeCache.get(key);
257
+ if (cached) return cached;
258
+ const texture = createCurlNoiseVolume({ dims: size, plan, seed });
259
+ volumeCache.set(key, texture);
260
+ return texture;
261
+ }
262
+
263
+ /** Releases every cached curl volume. */
264
+ export function disposeCurlNoiseVolumes() {
265
+ for (const texture of volumeCache.values()) texture.dispose();
266
+ volumeCache.clear();
267
+ }
268
+
269
+ /** Decodes a packed curl texel back to a signed vector in about [-1, 1]. */
270
+ export const decodeCurlNoise = /*@__PURE__*/ Fn(([packed]) => (
271
+ packed.rgb.mul(2).sub(vec3(1))
272
+ ));
273
+
274
+ /**
275
+ * Samples a baked curl volume as an advection offset, in metres.
276
+ *
277
+ * `scale` is the world size of one tile — pass the same repeat the erosion
278
+ * detail uses so wisps shear at the scale they are carved at. `strength` is the
279
+ * offset magnitude in metres at full field energy. RepeatWrapping does the
280
+ * tiling, so the world position needs no fract() first.
281
+ */
282
+ export function curlNoiseOffsetNode(volume, {
283
+ position,
284
+ scale,
285
+ strength,
286
+ }) {
287
+ const packed = texture3D(volume).sample(position.div(scale));
288
+ return decodeCurlNoise(packed).mul(strength);
289
+ }
@@ -0,0 +1,188 @@
1
+ // Cloud erosion volume — the high-frequency Worley detail field that carves
2
+ // the cloud silhouette after the base shape has decided where cloud exists.
3
+ //
4
+ // R inverted Worley FBM, low detail (2 / 4 / 8 cells)
5
+ // G inverted Worley FBM, mid detail (4 / 8 / 16 cells)
6
+ // B inverted Worley FBM, high detail (8 / 16 cells)
7
+ // A R * 0.625 + G * 0.25 + B * 0.125, precombined
8
+ //
9
+ // Each RGB channel is already an overlapping FBM, matching Hillaire's published
10
+ // TileableVolumeNoise companion implementation. The density field combines the
11
+ // three FBMs once more, which is what gives erosion a broad support plus enough
12
+ // fine structure to break a silhouette:
13
+ //
14
+ // detail = r * 0.625 + g * 0.25 + b * 0.125 (or just the A channel)
15
+ // wispy = mix(detail, 1 - detail, saturate(heightFraction * 5))
16
+ // modifier = mix(detail, wispy, erosionShape)
17
+ // density = remap(base, modifier * erosionStrength, 1, 0, 1)
18
+ //
19
+ // The A channel exists for the cheap paths — the shadow bake and the env-map
20
+ // bake carve with one weighted band instead of three, and a fetch they already
21
+ // have to make is cheaper than three multiplies they do not.
22
+ //
23
+ // The band limit here is deliberately looser than the base-shape volume's (two
24
+ // texels per cell rather than four). A detail field's job is high-frequency
25
+ // grain, not a resolvable silhouette, and the top rung of a 32³ detail volume
26
+ // is where the reference-class implementations sit.
27
+
28
+ import { deriveSeed, hashSeed } from '../../core/generation.js';
29
+ import {
30
+ createNoiseVolumeTexture,
31
+ encodeUnorm8,
32
+ noiseVolumeKey,
33
+ resolveNoiseDims,
34
+ warnNoiseVolumeOnce,
35
+ } from './noiseVolume.js';
36
+ import { createWorleyLadder3 } from './periodicNoise3.js';
37
+
38
+ /** Default resolution. Not tier-driven: erosion is cheap at every tier. */
39
+ export const CLOUD_EROSION_DEFAULT_DIMS = 32;
40
+
41
+ /**
42
+ * Seed namespace for this volume's bands.
43
+ *
44
+ * createWorleyLadder3 seeds each band by its cell count, so a frequency is the
45
+ * same field at every volume resolution — and, without a namespace, the same
46
+ * field in every *volume* that requests that count. The base-shape volume's
47
+ * ladder overlaps this plan at 4/8/16 cells, so the two combined fields became
48
+ * strongly correlated. Carving a cloud with a copy of its own erosion basis
49
+ * flattens the silhouette instead of tearing it, and at
50
+ * `shape.erosionScaleBaseMultiplier = 1.0` — the top of the spec's authoring
51
+ * range, where both volumes are read at the same tile coordinate — the two
52
+ * fields were 0.69 correlated. Namespacing the seed drops that to ~0.
53
+ */
54
+ export const CLOUD_EROSION_SEED_NAMESPACE = 'cloud-erosion';
55
+
56
+ /** Weights the A channel packs, and the density field's own detail FBM. */
57
+ export const CLOUD_EROSION_DETAIL_WEIGHTS = Object.freeze([0.625, 0.25, 0.125]);
58
+
59
+ /**
60
+ * Frequency plan in cells across one tile. Fixed in tile units so a custom
61
+ * resolution re-resolves the same field rather than authoring a new one.
62
+ */
63
+ export const CLOUD_EROSION_PLAN = Object.freeze({
64
+ cells: Object.freeze([2, 4, 8, 16]),
65
+ jitter: 1,
66
+ texelsPerCell: 2,
67
+ });
68
+
69
+ const volumeCache = new Map();
70
+
71
+ /**
72
+ * Bakes the RGBA8 erosion field. Returned separately from the texture so
73
+ * verification scripts can read the numbers without a renderer.
74
+ */
75
+ export function createCloudErosionData({
76
+ dims = CLOUD_EROSION_DEFAULT_DIMS,
77
+ seed = 1,
78
+ } = {}) {
79
+ const size = resolveNoiseDims(dims, CLOUD_EROSION_DEFAULT_DIMS);
80
+ const rootSeed = hashSeed(seed);
81
+ // The public seed is reported unchanged so a preset can round-trip it; only
82
+ // the field seed is namespaced.
83
+ const fieldSeed = deriveSeed(rootSeed, CLOUD_EROSION_SEED_NAMESPACE);
84
+ const bands = createWorleyLadder3(fieldSeed, CLOUD_EROSION_PLAN.cells, {
85
+ dim: Math.min(size.x, size.y, size.z),
86
+ jitter: CLOUD_EROSION_PLAN.jitter,
87
+ texelsPerCell: CLOUD_EROSION_PLAN.texelsPerCell,
88
+ });
89
+ // Four bands are the contract, not a preference: RGB are the overlapping
90
+ // FBMs [2/4/8], [4/8/16] and [8/16]. At two texels per cell a short axis of
91
+ // 16 band-limits the last rung and loses the finest part of G/B.
92
+ const distinctBands = new Set(bands).size;
93
+ if (distinctBands < CLOUD_EROSION_PLAN.cells.length) {
94
+ warnNoiseVolumeOnce(
95
+ `erosion-bands:${size.x}x${size.y}x${size.z}`,
96
+ `[erosionVolume] ${size.x}x${size.y}x${size.z} band-limits cells `
97
+ + `[${CLOUD_EROSION_PLAN.cells}] to [${bands.map((band) => band.cells)}], leaving `
98
+ + `${distinctBands} distinct band(s) of ${CLOUD_EROSION_PLAN.cells.length}: the repeated `
99
+ + 'channels carry identical bytes and the detail FBM loses a band. Raise the resolution to '
100
+ + `${CLOUD_EROSION_PLAN.cells[CLOUD_EROSION_PLAN.cells.length - 1]
101
+ * CLOUD_EROSION_PLAN.texelsPerCell}³ or above for all three.`,
102
+ );
103
+ }
104
+ const [weightR, weightG, weightB] = CLOUD_EROSION_DETAIL_WEIGHTS;
105
+
106
+ const data = new Uint8Array(size.x * size.y * size.z * 4);
107
+ const invX = 1 / size.x;
108
+ const invY = 1 / size.y;
109
+ const invZ = 1 / size.z;
110
+ let cursor = 0;
111
+ for (let z = 0; z < size.z; z += 1) {
112
+ const w = (z + 0.5) * invZ;
113
+ for (let y = 0; y < size.y; y += 1) {
114
+ const v = (y + 0.5) * invY;
115
+ for (let x = 0; x < size.x; x += 1) {
116
+ const u = (x + 0.5) * invX;
117
+ const w0 = 1 - bands[0].sample(u, v, w);
118
+ const w1 = 1 - bands[1].sample(u, v, w);
119
+ const w2 = 1 - bands[2].sample(u, v, w);
120
+ const w3 = 1 - bands[3].sample(u, v, w);
121
+ // Exact packing from Hillaire's reference generator. The highest
122
+ // channel has two usable rungs at 32^3, hence 0.75 / 0.25.
123
+ const low = w0 * 0.625 + w1 * 0.25 + w2 * 0.125;
124
+ const mid = w1 * 0.625 + w2 * 0.25 + w3 * 0.125;
125
+ const high = w2 * 0.75 + w3 * 0.25;
126
+ data[cursor] = encodeUnorm8(low);
127
+ data[cursor + 1] = encodeUnorm8(mid);
128
+ data[cursor + 2] = encodeUnorm8(high);
129
+ data[cursor + 3] = encodeUnorm8(low * weightR + mid * weightG + high * weightB);
130
+ cursor += 4;
131
+ }
132
+ }
133
+ }
134
+
135
+ return {
136
+ data,
137
+ dims: size,
138
+ distinctBands,
139
+ fieldSeed,
140
+ seed: rootSeed,
141
+ worleyCells: bands.map((band) => band.cells),
142
+ };
143
+ }
144
+
145
+ /** Bakes an uncached erosion volume. Callers own dispose(). */
146
+ export function createCloudErosionVolume({
147
+ dims = CLOUD_EROSION_DEFAULT_DIMS,
148
+ seed = 1,
149
+ } = {}) {
150
+ const baked = createCloudErosionData({ dims, seed });
151
+ const texture = createNoiseVolumeTexture(
152
+ baked.data,
153
+ baked.dims,
154
+ `ToonLabCloudErosion${baked.dims.x}x${baked.dims.y}x${baked.dims.z}`,
155
+ );
156
+ texture.userData.toonlabCloudNoise = {
157
+ detailWeights: CLOUD_EROSION_DETAIL_WEIGHTS,
158
+ dims: baked.dims,
159
+ distinctBands: baked.distinctBands,
160
+ // `seed` is the public seed, so a lab can serialize it and get this volume
161
+ // back; `fieldSeed` is the namespaced seed the bands were built from.
162
+ fieldSeed: baked.fieldSeed,
163
+ kind: 'erosion',
164
+ seed: baked.seed,
165
+ worleyCells: baked.worleyCells,
166
+ };
167
+ return texture;
168
+ }
169
+
170
+ /** Cached erosion volume, keyed by resolution and seed. */
171
+ export function getCloudErosionVolume({
172
+ dims = CLOUD_EROSION_DEFAULT_DIMS,
173
+ seed = 1,
174
+ } = {}) {
175
+ const size = resolveNoiseDims(dims, CLOUD_EROSION_DEFAULT_DIMS);
176
+ const key = noiseVolumeKey(size, hashSeed(seed));
177
+ const cached = volumeCache.get(key);
178
+ if (cached) return cached;
179
+ const texture = createCloudErosionVolume({ dims: size, seed });
180
+ volumeCache.set(key, texture);
181
+ return texture;
182
+ }
183
+
184
+ /** Releases every cached erosion volume. */
185
+ export function disposeCloudErosionVolumes() {
186
+ for (const texture of volumeCache.values()) texture.dispose();
187
+ volumeCache.clear();
188
+ }
@@ -0,0 +1,202 @@
1
+ // The Data3DTexture contract shared by the three cloud noise volumes.
2
+ //
3
+ // All of them are RGBA8 tiling fields sampled trilinearly with RepeatWrapping
4
+ // on every axis. Getting one axis wrong (wrapR defaults to ClampToEdge) puts a
5
+ // seam in the sky that looks like a shader bug rather than a texture setting,
6
+ // so the settings live in one place instead of three.
7
+
8
+ import * as THREE from 'three';
9
+
10
+ /**
11
+ * Reads one authored number out of untrusted input, returning `fallback` for
12
+ * anything absent. The single definition of "absent" for the whole noise module.
13
+ *
14
+ * `Number()` is not the guard it looks like: `Number(null)`, `Number('')`,
15
+ * `Number([])` and `Number(false)` are all 0 and all pass `Number.isFinite`, so
16
+ * a clamp downstream pins them to a range's minimum instead of falling back to a
17
+ * default. A preset that round-tripped through JSON carries `null` for every
18
+ * untouched field, so that difference is the difference between reloading a sky
19
+ * and authoring a new one. Numeric strings stay legal because lab inputs and URL
20
+ * parameters arrive as strings.
21
+ */
22
+ export function resolveAuthoredNumber(value, fallback) {
23
+ if (typeof value === 'number') return Number.isFinite(value) ? value : fallback;
24
+ if (typeof value === 'string' && value.trim() !== '') {
25
+ const parsed = Number(value);
26
+ return Number.isFinite(parsed) ? parsed : fallback;
27
+ }
28
+ return fallback;
29
+ }
30
+
31
+ /**
32
+ * Hard floor for every noise volume, on every axis.
33
+ *
34
+ * Below 8 the band ladder has nothing left to resolve: every Worley rung
35
+ * band-limits onto the same cell count, so the three erosion channels come out
36
+ * byte-identical and what remains is not a cloud field. The floor lives here
37
+ * rather than in each baker because the degenerate volume still samples cleanly
38
+ * — nothing downstream can detect that it was handed junk.
39
+ */
40
+ export const NOISE_VOLUME_MIN_DIM = 8;
41
+
42
+ /** Accepts 64, [64, 32, 64] or { x, y, z } and normalizes to { x, y, z }. */
43
+ export function resolveNoiseDims(dims, fallback = 64) {
44
+ const clampAxis = (value) => {
45
+ // An absent axis is the default, not zero: a preset that serialized `null`
46
+ // — or `false`, or 0 — must not deserialize into a 2³ volume.
47
+ const size = Math.round(resolveAuthoredNumber(value, fallback));
48
+ if (!(size > 0)) return fallback;
49
+ if (size < NOISE_VOLUME_MIN_DIM) {
50
+ warnNoiseVolumeOnce(
51
+ `noise-dim-floor:${size}`,
52
+ `Noise volume axis ${size} is below the ${NOISE_VOLUME_MIN_DIM}-texel floor; `
53
+ + `clamping to ${NOISE_VOLUME_MIN_DIM}. Below it every band collapses onto one `
54
+ + 'cell count and the erosion channels come out identical.',
55
+ );
56
+ }
57
+ return Math.min(Math.max(size, NOISE_VOLUME_MIN_DIM), 256);
58
+ };
59
+ if (Array.isArray(dims)) {
60
+ return {
61
+ x: clampAxis(dims[0]),
62
+ y: clampAxis(dims[1] ?? dims[0]),
63
+ z: clampAxis(dims[2] ?? dims[0]),
64
+ };
65
+ }
66
+ if (dims && typeof dims === 'object') {
67
+ return { x: clampAxis(dims.x), y: clampAxis(dims.y), z: clampAxis(dims.z) };
68
+ }
69
+ const size = clampAxis(dims);
70
+ return { x: size, y: size, z: size };
71
+ }
72
+
73
+ /** `${x}x${y}x${z}:${seed}` — the cache key every volume generator uses. */
74
+ export function noiseVolumeKey(dims, seed) {
75
+ return `${dims.x}x${dims.y}x${dims.z}:${seed}`;
76
+ }
77
+
78
+ const warnedKeys = new Set();
79
+
80
+ /**
81
+ * Reports a degenerate volume configuration once per distinct `key`.
82
+ *
83
+ * A band ladder that collapsed, a mip level that hit the resolution floor, an
84
+ * encoding that clipped — all of them produce a field that still *looks* like a
85
+ * volume, so silence is the failure mode. Deduplicated because a lab bound to a
86
+ * seed slider re-bakes on every drag, and a warning repeated a hundred times
87
+ * buries the first one. The key is the configuration, not the seed: the same
88
+ * resolution degenerates the same way whatever it is seeded with.
89
+ */
90
+ export function warnNoiseVolumeOnce(key, message) {
91
+ if (warnedKeys.has(key)) return false;
92
+ warnedKeys.add(key);
93
+ console.warn(message);
94
+ return true;
95
+ }
96
+
97
+ /**
98
+ * Wraps baked RGBA8 data in a fully configured tiling 3D texture.
99
+ *
100
+ * `generateMipmaps` stays off: three.js cannot build a 3D mip chain on the
101
+ * WebGPU backend. Volumes that carry authored levels are configured and uploaded
102
+ * by configureNoiseVolumeMipChain/uploadNoiseVolumeMipChain below.
103
+ */
104
+ export function createNoiseVolumeTexture(data, dims, name) {
105
+ const texture = new THREE.Data3DTexture(data, dims.x, dims.y, dims.z);
106
+ texture.name = name;
107
+ texture.format = THREE.RGBAFormat;
108
+ texture.type = THREE.UnsignedByteType;
109
+ texture.colorSpace = THREE.NoColorSpace;
110
+ texture.wrapS = THREE.RepeatWrapping;
111
+ texture.wrapT = THREE.RepeatWrapping;
112
+ texture.wrapR = THREE.RepeatWrapping;
113
+ texture.minFilter = THREE.LinearFilter;
114
+ texture.magFilter = THREE.LinearFilter;
115
+ texture.generateMipmaps = false;
116
+ texture.unpackAlignment = 1;
117
+ texture.needsUpdate = true;
118
+ return texture;
119
+ }
120
+
121
+ function volumeMipDims(dims, level) {
122
+ const scale = 2 ** level;
123
+ return {
124
+ x: Math.max(1, Math.floor(dims.x / scale)),
125
+ y: Math.max(1, Math.floor(dims.y / scale)),
126
+ z: Math.max(1, Math.floor(dims.z / scale)),
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Gives a Data3DTexture a full authored mip pyramid. WebGPU cannot generate
132
+ * 3D mips through three's normal generator, so the byte levels are retained
133
+ * until a renderer can copy them into the allocated GPU levels.
134
+ */
135
+ export function configureNoiseVolumeMipChain(texture, levels, dims) {
136
+ if (!texture?.isData3DTexture || !Array.isArray(levels) || levels.length < 2) {
137
+ return texture;
138
+ }
139
+ texture.minFilter = THREE.LinearMipMapLinearFilter;
140
+ texture.magFilter = THREE.LinearFilter;
141
+ texture.generateMipmaps = false;
142
+ texture.mipmaps = levels.map((unused, level) => {
143
+ const size = volumeMipDims(dims, level);
144
+ return { width: size.x, height: size.y, depth: size.z };
145
+ });
146
+ texture.userData.toonlabVolumeMipChain = {
147
+ dims: { ...dims },
148
+ levels,
149
+ uploadedRenderers: new WeakSet(),
150
+ };
151
+ texture.needsUpdate = true;
152
+ return texture;
153
+ }
154
+
155
+ /** Uploads the retained 3D mip levels once for each renderer. */
156
+ export function uploadNoiseVolumeMipChain(renderer, texture) {
157
+ const chain = texture?.userData?.toonlabVolumeMipChain;
158
+ if (!renderer?.copyTextureToTexture || !chain || chain.uploadedRenderers.has(renderer)) {
159
+ return false;
160
+ }
161
+
162
+ const temps = [];
163
+ for (let level = 1; level < chain.levels.length; level += 1) {
164
+ const size = volumeMipDims(chain.dims, level);
165
+ const temp = new THREE.Data3DTexture(
166
+ chain.levels[level],
167
+ size.x,
168
+ size.y,
169
+ size.z,
170
+ );
171
+ temp.format = THREE.RGBAFormat;
172
+ temp.type = THREE.UnsignedByteType;
173
+ temp.unpackAlignment = 1;
174
+ temp.needsUpdate = true;
175
+ renderer.copyTextureToTexture(
176
+ temp,
177
+ texture,
178
+ new THREE.Box3(
179
+ new THREE.Vector3(0, 0, 0),
180
+ new THREE.Vector3(size.x, size.y, size.z),
181
+ ),
182
+ new THREE.Vector3(0, 0, 0),
183
+ 0,
184
+ level,
185
+ );
186
+ temps.push(temp);
187
+ }
188
+ for (const temp of temps) temp.dispose();
189
+ chain.uploadedRenderers.add(renderer);
190
+ return true;
191
+ }
192
+
193
+ /** Quantizes a [0, 1] field value to a byte with round-half-up. */
194
+ export function encodeUnorm8(value) {
195
+ const clamped = value < 0 ? 0 : value > 1 ? 1 : value;
196
+ return (clamped * 255 + 0.5) | 0;
197
+ }
198
+
199
+ /** Quantizes a [-1, 1] field value to a byte, matching a `* 2 - 1` decode. */
200
+ export function encodeSnorm8(value) {
201
+ return encodeUnorm8(value * 0.5 + 0.5);
202
+ }