@woosh/meep-engine 3.52.0 → 3.53.0

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 (370) hide show
  1. package/package.json +1 -1
  2. package/src/engine/ecs/animation/Animation.d.ts +4 -25
  3. package/src/engine/ecs/animation/Animation.d.ts.map +1 -1
  4. package/src/engine/ecs/animation/Animation.js +9 -41
  5. package/src/engine/ecs/ik/IKGoalSystem.d.ts +4 -5
  6. package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
  7. package/src/engine/ecs/ik/IKGoalSystem.js +4 -6
  8. package/src/engine/graphics/ecs/mesh/assetTypeByPath.js +1 -1
  9. package/src/engine/graphics3/AnimationGraphSystem.d.ts +9 -22
  10. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  11. package/src/engine/graphics3/AnimationGraphSystem.js +58 -203
  12. package/src/engine/graphics3/AnimationSystem.d.ts +7 -18
  13. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  14. package/src/engine/graphics3/AnimationSystem.js +62 -243
  15. package/src/engine/graphics3/FoliageWindSystem.d.ts +67 -0
  16. package/src/engine/graphics3/FoliageWindSystem.d.ts.map +1 -0
  17. package/src/engine/graphics3/FoliageWindSystem.js +257 -0
  18. package/src/engine/graphics3/GPUFluidSystem.d.ts +7 -0
  19. package/src/engine/graphics3/GPUFluidSystem.d.ts.map +1 -1
  20. package/src/engine/graphics3/GPUFluidSystem.js +39 -1
  21. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +0 -1
  22. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  23. package/src/engine/graphics3/GPUParticleEmitterSystem.js +19 -5
  24. package/src/engine/graphics3/animation/AnimationClips.d.ts +107 -13
  25. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -1
  26. package/src/engine/graphics3/animation/AnimationClips.js +207 -10
  27. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts +89 -0
  28. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts.map +1 -0
  29. package/src/engine/graphics3/animation/AnimationClipsSink.js +205 -0
  30. package/src/engine/graphics3/animation/FoliageWindRigs.d.ts +43 -0
  31. package/src/engine/graphics3/animation/FoliageWindRigs.d.ts.map +1 -0
  32. package/src/engine/graphics3/animation/FoliageWindRigs.js +69 -0
  33. package/src/engine/graphics3/animation/write_clip_playback.d.ts +17 -11
  34. package/src/engine/graphics3/animation/write_clip_playback.d.ts.map +1 -1
  35. package/src/engine/graphics3/animation/write_clip_playback.js +36 -27
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +8 -6
  38. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  39. package/src/engine/graphics3/decal/shader_decal_composite.js +11 -5
  40. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +7 -7
  41. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -1
  42. package/src/engine/graphics3/pose/collect_entity_playbacks.js +14 -15
  43. package/src/engine/graphics3/prefab/Prefab.d.ts +6 -0
  44. package/src/engine/graphics3/prefab/Prefab.d.ts.map +1 -1
  45. package/src/engine/graphics3/prefab/Prefab.js +169 -162
  46. package/src/engine/graphics3/prefab/prefab_compile.d.ts.map +1 -1
  47. package/src/engine/graphics3/prefab/prefab_compile.js +369 -334
  48. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  49. package/src/engine/graphics3/prefab/prefab_instantiate.js +43 -2
  50. package/src/engine/graphics3/terrain/chunk_terrain_material_surface.js +2 -2
  51. package/src/engine/physics/ecs/ContactProbeSystem.d.ts +2 -3
  52. package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
  53. package/src/engine/physics/ecs/ContactProbeSystem.js +2 -4
  54. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  55. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +4 -4
  56. package/src/engine/sound/simulation/README.md +1 -1
  57. package/src/engine/sound/simulation/probe/bakeProbeField.d.ts +22 -8
  58. package/src/engine/sound/simulation/probe/bakeProbeField.d.ts.map +1 -1
  59. package/src/engine/sound/simulation/probe/bakeProbeField.js +60 -15
  60. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
  61. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +19 -23
  62. package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts +63 -17
  63. package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts.map +1 -1
  64. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +67 -17
  65. package/src/generation/foliage/FOLIAGE_DESIGN.md +318 -0
  66. package/src/generation/foliage/FOLIAGE_PLAN.md +198 -0
  67. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts +20 -0
  68. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts.map +1 -0
  69. package/src/generation/foliage/animation/build_tree_wind_rig.js +108 -0
  70. package/src/generation/foliage/asset/TreeAsset.d.ts +86 -0
  71. package/src/generation/foliage/asset/TreeAsset.d.ts.map +1 -0
  72. package/src/generation/foliage/asset/TreeAsset.js +111 -0
  73. package/src/generation/foliage/asset/TreeLODAsset.d.ts +115 -0
  74. package/src/generation/foliage/asset/TreeLODAsset.d.ts.map +1 -0
  75. package/src/generation/foliage/asset/TreeLODAsset.js +346 -0
  76. package/src/generation/foliage/asset/generate_tree.d.ts +15 -0
  77. package/src/generation/foliage/asset/generate_tree.d.ts.map +1 -0
  78. package/src/generation/foliage/asset/generate_tree.js +93 -0
  79. package/src/generation/foliage/asset/place_tree.d.ts +82 -0
  80. package/src/generation/foliage/asset/place_tree.d.ts.map +1 -0
  81. package/src/generation/foliage/asset/place_tree.js +194 -0
  82. package/src/generation/foliage/config/BarkMaterialConfig.d.ts +120 -0
  83. package/src/generation/foliage/config/BarkMaterialConfig.d.ts.map +1 -0
  84. package/src/generation/foliage/config/BarkMaterialConfig.js +250 -0
  85. package/src/generation/foliage/config/BranchLevelConfig.d.ts +288 -0
  86. package/src/generation/foliage/config/BranchLevelConfig.d.ts.map +1 -0
  87. package/src/generation/foliage/config/BranchLevelConfig.js +536 -0
  88. package/src/generation/foliage/config/CrownConfig.d.ts +100 -0
  89. package/src/generation/foliage/config/CrownConfig.d.ts.map +1 -0
  90. package/src/generation/foliage/config/CrownConfig.js +186 -0
  91. package/src/generation/foliage/config/CrownEnvelopeType.d.ts +16 -0
  92. package/src/generation/foliage/config/CrownEnvelopeType.d.ts.map +1 -0
  93. package/src/generation/foliage/config/CrownEnvelopeType.js +17 -0
  94. package/src/generation/foliage/config/FoliageCardType.d.ts +12 -0
  95. package/src/generation/foliage/config/FoliageCardType.d.ts.map +1 -0
  96. package/src/generation/foliage/config/FoliageCardType.js +18 -0
  97. package/src/generation/foliage/config/FoliageConfig.d.ts +151 -0
  98. package/src/generation/foliage/config/FoliageConfig.d.ts.map +1 -0
  99. package/src/generation/foliage/config/FoliageConfig.js +283 -0
  100. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts +90 -0
  101. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts.map +1 -0
  102. package/src/generation/foliage/config/FoliageMaterialConfig.js +181 -0
  103. package/src/generation/foliage/config/PhyllotaxisMode.d.ts +13 -0
  104. package/src/generation/foliage/config/PhyllotaxisMode.d.ts.map +1 -0
  105. package/src/generation/foliage/config/PhyllotaxisMode.js +20 -0
  106. package/src/generation/foliage/config/TreeLODConfig.d.ts +87 -0
  107. package/src/generation/foliage/config/TreeLODConfig.d.ts.map +1 -0
  108. package/src/generation/foliage/config/TreeLODConfig.js +211 -0
  109. package/src/generation/foliage/config/TreePreset.d.ts +16 -0
  110. package/src/generation/foliage/config/TreePreset.d.ts.map +1 -0
  111. package/src/generation/foliage/config/TreePreset.js +17 -0
  112. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts +109 -0
  113. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts.map +1 -0
  114. package/src/generation/foliage/config/TreeSpeciesConfig.js +400 -0
  115. package/src/generation/foliage/config/TreeWindConfig.d.ts +84 -0
  116. package/src/generation/foliage/config/TreeWindConfig.d.ts.map +1 -0
  117. package/src/generation/foliage/config/TreeWindConfig.js +157 -0
  118. package/src/generation/foliage/index.d.ts +38 -0
  119. package/src/generation/foliage/index.d.ts.map +1 -0
  120. package/src/generation/foliage/index.js +43 -0
  121. package/src/generation/foliage/material/make_bark_material.d.ts +37 -0
  122. package/src/generation/foliage/material/make_bark_material.d.ts.map +1 -0
  123. package/src/generation/foliage/material/make_bark_material.js +802 -0
  124. package/src/generation/foliage/material/make_foliage_material.d.ts +14 -0
  125. package/src/generation/foliage/material/make_foliage_material.d.ts.map +1 -0
  126. package/src/generation/foliage/material/make_foliage_material.js +359 -0
  127. package/src/generation/foliage/mesh/branch_collar_project.d.ts +42 -0
  128. package/src/generation/foliage/mesh/branch_collar_project.d.ts.map +1 -0
  129. package/src/generation/foliage/mesh/branch_collar_project.js +203 -0
  130. package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts +35 -0
  131. package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts.map +1 -0
  132. package/src/generation/foliage/mesh/branch_ring_triangulate.js +72 -0
  133. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts +80 -0
  134. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts.map +1 -0
  135. package/src/generation/foliage/mesh/foliage_collect_attachments.js +502 -0
  136. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts +19 -0
  137. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts.map +1 -0
  138. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.js +150 -0
  139. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts +55 -0
  140. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -0
  141. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +1047 -0
  142. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts +21 -0
  143. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts.map +1 -0
  144. package/src/generation/foliage/mesh/tree_mesh_build_foliage.js +415 -0
  145. package/src/generation/foliage/presets/make_tree_species_preset.d.ts +13 -0
  146. package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -0
  147. package/src/generation/foliage/presets/make_tree_species_preset.js +837 -0
  148. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts +443 -0
  149. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts.map +1 -0
  150. package/src/generation/foliage/skeleton/TreeSkeleton.js +1100 -0
  151. package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts +27 -0
  152. package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts.map +1 -0
  153. package/src/generation/foliage/skeleton/crown_envelope_evaluate.js +121 -0
  154. package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts +32 -0
  155. package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts.map +1 -0
  156. package/src/generation/foliage/skeleton/spine_frame_double_reflection.js +87 -0
  157. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts +33 -0
  158. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts.map +1 -0
  159. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.js +205 -0
  160. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts +14 -0
  161. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts.map +1 -0
  162. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.js +179 -0
  163. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts +18 -0
  164. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -0
  165. package/src/generation/foliage/skeleton/tree_skeleton_grow.js +1104 -0
  166. package/src/shade/playground/additive_blending/index.html +197 -0
  167. package/src/shade/playground/additive_blending/main.d.ts +2 -0
  168. package/src/shade/playground/additive_blending/main.d.ts.map +1 -0
  169. package/src/shade/playground/additive_blending/main.js +529 -0
  170. package/src/shade/playground/foliage_wind/README.md +18 -0
  171. package/src/shade/playground/foliage_wind/foliage_world.d.ts +127 -0
  172. package/src/shade/playground/foliage_wind/foliage_world.d.ts.map +1 -0
  173. package/src/shade/playground/foliage_wind/foliage_world.js +593 -0
  174. package/src/shade/playground/foliage_wind/index.html +254 -0
  175. package/src/shade/playground/foliage_wind/main.d.ts +2 -0
  176. package/src/shade/playground/foliage_wind/main.d.ts.map +1 -0
  177. package/src/shade/playground/foliage_wind/main.js +263 -0
  178. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  179. package/src/shade/renderer/Renderer.js +45 -16
  180. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +145 -0
  181. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts +9 -1
  182. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts.map +1 -1
  183. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.js +53 -1
  184. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts +8 -0
  185. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts.map +1 -0
  186. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.js +71 -0
  187. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts +11 -0
  188. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts.map +1 -0
  189. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.js +32 -0
  190. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +30 -3
  191. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  192. package/src/shade/renderer/animation/GPUAnimationManager.js +532 -79
  193. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +19 -12
  194. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
  195. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +20 -13
  196. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts +35 -8
  197. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts.map +1 -1
  198. package/src/shade/renderer/animation/ShadeAnimationClip.js +433 -2
  199. package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
  200. package/src/shade/renderer/animation/chunk_pose_accumulator.js +40 -32
  201. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts +97 -0
  202. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts.map +1 -0
  203. package/src/shade/renderer/animation/foliage/FoliageWindJoint.js +161 -0
  204. package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts +65 -0
  205. package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts.map +1 -0
  206. package/src/shade/renderer/animation/foliage/FoliageWindRig.js +89 -0
  207. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts +19 -0
  208. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts.map +1 -0
  209. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.js +143 -0
  210. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts +14 -0
  211. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts.map +1 -0
  212. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.js +116 -0
  213. package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
  214. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +39 -29
  215. package/src/shade/renderer/animation/shader_animation_pose_resolve.js +37 -37
  216. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +2 -2
  217. package/src/shade/renderer/extension/RenderExtension.d.ts +7 -0
  218. package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
  219. package/src/shade/renderer/extension/RenderExtension.js +9 -0
  220. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts +6 -0
  221. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts.map +1 -1
  222. package/src/shade/renderer/extension/RenderExtensionRegistry.js +15 -0
  223. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +7 -0
  224. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts.map +1 -1
  225. package/src/shade/renderer/fluid/GPUFluidCascade.js +15 -0
  226. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +7 -0
  227. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  228. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +11 -0
  229. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.d.ts.map +1 -1
  230. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.js +51 -48
  231. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts +6 -0
  232. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts.map +1 -1
  233. package/src/shade/renderer/fluid/mac/FluidMacPasses.js +16 -0
  234. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.d.ts.map +1 -1
  235. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.js +15 -3
  236. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.d.ts.map +1 -1
  237. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.js +102 -96
  238. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +12 -12
  239. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.js +12 -12
  240. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +7 -0
  241. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts.map +1 -1
  242. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.js +16 -0
  243. package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts +7 -0
  244. package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts.map +1 -1
  245. package/src/shade/renderer/fluid/publish/FluidWindPublish.js +10 -0
  246. package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.js +2 -2
  247. package/src/shade/renderer/loader/SceneBundle.d.ts +7 -0
  248. package/src/shade/renderer/loader/SceneBundle.d.ts.map +1 -1
  249. package/src/shade/renderer/loader/SceneBundle.js +119 -111
  250. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +4 -0
  251. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  252. package/src/shade/renderer/material/standard/fragment_gbuffer.js +6 -5
  253. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +8 -7
  254. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
  255. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +9 -8
  256. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  257. package/src/shade/renderer/particles/GPUParticleSystem.js +3 -1
  258. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  259. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +9 -4
  260. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
  261. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +9 -7
  262. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.d.ts.map +1 -1
  263. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.js +15 -7
  264. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts.map +1 -1
  265. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +6 -4
  266. package/src/shade/renderer/rasterize/native/oit/oit_resolve_fragment_body.js +3 -3
  267. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.d.ts.map +1 -1
  268. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +8 -5
  269. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  270. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +4 -3
  271. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1 -1
  272. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts +9 -0
  273. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts.map +1 -0
  274. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.js +17 -0
  275. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts +8 -0
  276. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts.map +1 -1
  277. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.js +28 -20
  278. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts +8 -0
  279. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts.map +1 -0
  280. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.js +15 -0
  281. package/src/shade/renderer/view/chunk_view_mip_bias.d.ts +21 -0
  282. package/src/shade/renderer/view/chunk_view_mip_bias.d.ts.map +1 -0
  283. package/src/shade/renderer/view/chunk_view_mip_bias.js +44 -0
  284. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  285. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  286. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +105 -26
  287. package/src/engine/graphics/composit/CompositingStages.d.ts +0 -6
  288. package/src/engine/graphics/composit/CompositingStages.d.ts.map +0 -1
  289. package/src/engine/graphics/composit/CompositingStages.js +0 -8
  290. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts +0 -7
  291. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts.map +0 -1
  292. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.js +0 -24
  293. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts +0 -8
  294. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts.map +0 -1
  295. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.js +0 -17
  296. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts +0 -8
  297. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts.map +0 -1
  298. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.js +0 -60
  299. package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts +0 -7
  300. package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts.map +0 -1
  301. package/src/engine/graphics/geometry/buffered/computeGeometryHash.js +0 -26
  302. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts +0 -7
  303. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts.map +0 -1
  304. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.js +0 -23
  305. package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts +0 -7
  306. package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts.map +0 -1
  307. package/src/engine/graphics/geometry/instancing/geometry_copy.js +0 -15
  308. package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts +0 -2
  309. package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts.map +0 -1
  310. package/src/engine/graphics/geometry/instancing/rewriteMaterial.js +0 -57
  311. package/src/engine/graphics/geometry/ribbon/Quad.d.ts +0 -96
  312. package/src/engine/graphics/geometry/ribbon/Quad.d.ts.map +0 -1
  313. package/src/engine/graphics/geometry/ribbon/Quad.js +0 -213
  314. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts +0 -9
  315. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts.map +0 -1
  316. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.js +0 -12
  317. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts +0 -10
  318. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts.map +0 -1
  319. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.js +0 -17
  320. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts +0 -10
  321. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts.map +0 -1
  322. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.js +0 -13
  323. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts +0 -11
  324. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts.map +0 -1
  325. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.js +0 -24
  326. package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts +0 -6
  327. package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts.map +0 -1
  328. package/src/engine/graphics/geometry/ribbon/rotateRibbon.js +0 -37
  329. package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts +0 -9
  330. package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts.map +0 -1
  331. package/src/engine/graphics/geometry/ribbon/updateTipPosition.js +0 -52
  332. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts +0 -8
  333. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts.map +0 -1
  334. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.js +0 -54
  335. package/src/engine/graphics/render/RenderPassType.d.ts +0 -6
  336. package/src/engine/graphics/render/RenderPassType.d.ts.map +0 -1
  337. package/src/engine/graphics/render/RenderPassType.js +0 -8
  338. package/src/engine/graphics/render/layers/RenderLayer.d.ts +0 -78
  339. package/src/engine/graphics/render/layers/RenderLayer.d.ts.map +0 -1
  340. package/src/engine/graphics/render/layers/RenderLayer.js +0 -95
  341. package/src/engine/graphics/render/layers/RenderLayerManager.d.ts +0 -72
  342. package/src/engine/graphics/render/layers/RenderLayerManager.d.ts.map +0 -1
  343. package/src/engine/graphics/render/layers/RenderLayerManager.js +0 -160
  344. package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts +0 -18
  345. package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts.map +0 -1
  346. package/src/engine/graphics/render/layers/RenderLayerManagerState.js +0 -48
  347. package/src/engine/graphics/render/layers/RenderLayerState.d.ts +0 -18
  348. package/src/engine/graphics/render/layers/RenderLayerState.d.ts.map +0 -1
  349. package/src/engine/graphics/render/layers/RenderLayerState.js +0 -27
  350. package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts +0 -8
  351. package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts.map +0 -1
  352. package/src/engine/graphics/render/layers/RenderLayerUtils.js +0 -103
  353. package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts +0 -10
  354. package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts.map +0 -1
  355. package/src/engine/graphics/render/make_bvh_visibility_builder.js +0 -64
  356. package/src/engine/graphics/render/view/CameraViewFlags.d.ts +0 -7
  357. package/src/engine/graphics/render/view/CameraViewFlags.d.ts.map +0 -1
  358. package/src/engine/graphics/render/view/CameraViewFlags.js +0 -9
  359. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +0 -143
  360. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts.map +0 -1
  361. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.js +0 -328
  362. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts +0 -39
  363. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts.map +0 -1
  364. package/src/engine/graphics/render/visibility/VisibilityComputer.js +0 -80
  365. package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts +0 -29
  366. package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts.map +0 -1
  367. package/src/engine/graphics/render/visibility/VisibilityFilter.js +0 -37
  368. package/src/engine/graphics3/animation/write_graph_playback.d.ts +0 -24
  369. package/src/engine/graphics3/animation/write_graph_playback.d.ts.map +0 -1
  370. package/src/engine/graphics3/animation/write_graph_playback.js +0 -48
@@ -0,0 +1,802 @@
1
+ import { PI2 } from "../../../core/math/PI2.js";
2
+ import { clamp } from "../../../core/math/clamp.js";
3
+ import { lerp } from "../../../core/math/lerp.js";
4
+ import { seededRandom } from "../../../core/math/random/seededRandom.js";
5
+ import { smoothStep } from "../../../core/math/smoothStep.js";
6
+ import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
7
+ import { ShadeDrawSide } from "../../../shade/renderer/material/ShadeDrawSide.js";
8
+ import { StandardShadeMaterial } from "../../../shade/renderer/material/StandardShadeMaterial.js";
9
+ import { TransparencyMode } from "../../../shade/renderer/material/TransparencyMode.js";
10
+ import { ColorSpace } from "../../../shade/renderer/texture/ColorSpace.js";
11
+ import { ShadeTexture } from "../../../shade/renderer/texture/ShadeTexture.js";
12
+ import { TextureFilterType } from "../../../shade/renderer/texture/TextureFilterType.js";
13
+ import { TextureWrapType } from "../../../shade/renderer/texture/TextureWrapType.js";
14
+ import { AlphaMode } from "../../../shade/renderer/texture/source/AlphaMode.js";
15
+ import { ShadeImage } from "../../../shade/renderer/texture/source/ShadeImage.js";
16
+ import { BarkMaterialConfig } from "../config/BarkMaterialConfig.js";
17
+
18
+ const SCRATCH_WORLEY = new Float32Array(3);
19
+ const SCRATCH_WORLEY2 = new Float32Array(3);
20
+
21
+ /**
22
+ * Fast deterministic integer hash in [0, 1).
23
+ * @param {number} ix
24
+ * @param {number} iy
25
+ * @param {number} seed
26
+ * @returns {number}
27
+ */
28
+ function cell_hash_01(ix, iy, seed) {
29
+ let h = (ix * 374761393 + iy * 668265263 + seed * 1442695041) | 0;
30
+ h = Math.imul(h ^ (h >>> 13), 1274126177);
31
+ h = (h ^ (h >>> 16)) >>> 0;
32
+ return h / 4294967296.0;
33
+ }
34
+
35
+ /**
36
+ * Evaluates a seamlessly tileable 2D cellular Worley (Voronoi) noise on `[0, 1)^2`
37
+ * with periodic lattice dimensions `(cells_u, cells_v)`.
38
+ * Writes `[F1, F2 - F1, cell_id]` into `out`.
39
+ *
40
+ * @param {Float32Array|number[]} out
41
+ * @param {number} u
42
+ * @param {number} v
43
+ * @param {number} cells_u
44
+ * @param {number} cells_v
45
+ * @param {number} seed
46
+ */
47
+ function sample_tileable_worley(out, u, v, cells_u, cells_v, seed) {
48
+ const cu = Math.max(1, cells_u | 0);
49
+ const cv = Math.max(1, cells_v | 0);
50
+ const u_wrap = ((u % 1.0) + 1.0) % 1.0;
51
+ const v_wrap = ((v % 1.0) + 1.0) % 1.0;
52
+
53
+ const gx = u_wrap * cu;
54
+ const gy = v_wrap * cv;
55
+ const ix0 = Math.floor(gx);
56
+ const iy0 = Math.floor(gy);
57
+
58
+ let d1 = 1e9;
59
+ let d2 = 1e9;
60
+ let best_id = 0.0;
61
+
62
+ for (let dy = -1; dy <= 1; dy++) {
63
+ const ny = iy0 + dy;
64
+ const wy = ((ny % cv) + cv) % cv;
65
+ for (let dx = -1; dx <= 1; dx++) {
66
+ const nx = ix0 + dx;
67
+ const wx = ((nx % cu) + cu) % cu;
68
+
69
+ const jx = cell_hash_01(wx, wy, seed);
70
+ const jy = cell_hash_01(wx, wy, seed ^ 0x6C8E9CF5);
71
+ const cid = cell_hash_01(wx, wy, seed ^ 0xB5297A4D);
72
+
73
+ const px = nx + 0.15 + 0.70 * jx - gx;
74
+ const py = ny + 0.15 + 0.70 * jy - gy;
75
+ const dist2 = px * px + py * py;
76
+
77
+ if (dist2 < d1) {
78
+ d2 = d1;
79
+ d1 = dist2;
80
+ best_id = cid;
81
+ } else if (dist2 < d2) {
82
+ d2 = dist2;
83
+ }
84
+ }
85
+ }
86
+
87
+ const f1 = Math.sqrt(d1);
88
+ const f2 = Math.sqrt(d2);
89
+ out[0] = f1;
90
+ out[1] = clamp(f2 - f1, 0.0, 1.0);
91
+ out[2] = best_id;
92
+ }
93
+
94
+ /**
95
+ * Evaluates a seamlessly tileable 2D periodic gradient noise value on `[0, 1)^2`
96
+ * with integer periods `(freq_u, freq_v)` and zero allocation overhead.
97
+ *
98
+ * @param {number} u
99
+ * @param {number} v
100
+ * @param {number} freq_u integer circumferential frequency
101
+ * @param {number} freq_v integer vertical frequency
102
+ * @param {number} ox seed offset X
103
+ * @param {number} oy seed offset Y
104
+ * @param {number} oz seed offset Z
105
+ * @returns {number} value in [-1, 1]
106
+ */
107
+ function sample_tileable_bark_noise(u, v, freq_u, freq_v, ox, oy, oz) {
108
+ const pu = Math.max(1, freq_u | 0);
109
+ const pv = Math.max(1, freq_v | 0);
110
+ const seed_mix = ((ox * 73856093) ^ (oy * 19349663) ^ (oz * 83492791)) | 0;
111
+
112
+ const u_wrap = ((u % 1.0) + 1.0) % 1.0;
113
+ const v_wrap = ((v % 1.0) + 1.0) % 1.0;
114
+ const gx = u_wrap * pu;
115
+ const gy = v_wrap * pv;
116
+
117
+ const ix0 = Math.floor(gx);
118
+ const iy0 = Math.floor(gy);
119
+ const fx = gx - ix0;
120
+ const fy = gy - iy0;
121
+
122
+ const x0 = ((ix0 % pu) + pu) % pu;
123
+ const x1 = (x0 + 1) % pu;
124
+ const y0 = ((iy0 % pv) + pv) % pv;
125
+ const y1 = (y0 + 1) % pv;
126
+
127
+ const ux = fx * fx * fx * (fx * (fx * 6.0 - 15.0) + 10.0);
128
+ const uy = fy * fy * fy * (fy * (fy * 6.0 - 15.0) + 10.0);
129
+
130
+ const grad_dot = (ix, iy, dx, dy) => {
131
+ let h = (ix * 374761393 + iy * 668265263 + seed_mix) | 0;
132
+ h = Math.imul(h ^ (h >>> 13), 1274126177);
133
+ const g = (h ^ (h >>> 16)) & 7;
134
+ switch (g) {
135
+ case 0: return dx + dy;
136
+ case 1: return -dx + dy;
137
+ case 2: return dx - dy;
138
+ case 3: return -dx - dy;
139
+ case 4: return dx * 1.41421356;
140
+ case 5: return -dx * 1.41421356;
141
+ case 6: return dy * 1.41421356;
142
+ default: return -dy * 1.41421356;
143
+ }
144
+ };
145
+
146
+ const n00 = grad_dot(x0, y0, fx, fy);
147
+ const n10 = grad_dot(x1, y0, fx - 1.0, fy);
148
+ const n01 = grad_dot(x0, y1, fx, fy - 1.0);
149
+ const n11 = grad_dot(x1, y1, fx - 1.0, fy - 1.0);
150
+
151
+ const nx0 = n00 + ux * (n10 - n00);
152
+ const nx1 = n01 + ux * (n11 - n01);
153
+ return clamp((nx0 + uy * (nx1 - nx0)) * 0.95, -1.0, 1.0);
154
+ }
155
+
156
+ /**
157
+ * Generates deterministic knot/scar centers in the mature trunk zone `v in [0.16, 0.62]`.
158
+ * Since `V in [0, 1]` spans ~8x more world distance than `U in [0, 1)`, `ry` is ~8x smaller than `rx`
159
+ * so knots and birch-eye scars appear naturally round/horizontally-ovoid in 3D world space!
160
+ *
161
+ * @param {number} seed
162
+ * @param {number} count
163
+ * @param {string} bark_type
164
+ * @returns {Array<{u: number, v: number, rx: number, ry: number, phase: number}>}
165
+ */
166
+ function build_bark_knot_sites(seed, count, bark_type) {
167
+ const rng = seededRandom((seed ^ 0x7F4A7C15) | 0);
168
+ const sites = [];
169
+ for (let k = 0; k < count; k++) {
170
+ sites.push({
171
+ u: ((k + 0.22 + 0.55 * rng()) / Math.max(1, count)) % 1.0,
172
+ v: 0.18 + (k + 0.18 + 0.60 * rng()) / Math.max(1, count) * 0.44,
173
+ rx: bark_type === "birch" ? (0.075 + 0.030 * rng()) : (0.055 + 0.025 * rng()),
174
+ ry: bark_type === "birch" ? (0.008 + 0.004 * rng()) : (0.011 + 0.005 * rng()),
175
+ phase: rng() * PI2
176
+ });
177
+ }
178
+ return sites;
179
+ }
180
+
181
+ /**
182
+ * Evaluates the low-frequency 3D macro-relief heightfield and smooth UV grain flow at `(u, v)`.
183
+ * Used by `tree_mesh_build_bark` for 3D cross-sectional undulation (strictly band-limited to
184
+ * low circumferential frequencies `<= 3` so polygon rings never suffer Nyquist aliasing creases!).
185
+ *
186
+ * Writes `[height, dh_du, u_flow_warp, knot_mask]` to `out`.
187
+ *
188
+ * @param {Float32Array|number[]} out
189
+ * @param {number} u
190
+ * @param {number} v
191
+ * @param {BarkMaterialConfig} cfg
192
+ * @param {number} [seed=1]
193
+ */
194
+ export function evaluate_bark_relief(out, u, v, cfg, seed = 1) {
195
+ const u0 = ((u % 1.0) + 1.0) % 1.0;
196
+ const v0 = clamp(v, 0.0, 1.0);
197
+
198
+ const ox = ((seed * 1664525 + 1013904223) & 0xFFFF) * 0.003 - 98.0;
199
+ const oy = (((seed ^ 0x5A3C9E17) * 1664525) & 0xFFFF) * 0.003 - 98.0;
200
+ const oz = (((seed ^ 0x2DDFA232) * 1664525) & 0xFFFF) * 0.003 - 98.0;
201
+
202
+ const knot_amt = clamp(cfg.knot_amount ?? 0.55, 0.0, 1.0);
203
+ const bark_type = (cfg.bark_type || "fissured").toLowerCase();
204
+
205
+ // Ontogenetic attenuation: old basal/mid bark has macro-relief, young upper twigs are smooth
206
+ const young_fade = 1.0 - 0.82 * smoothStep(0.60, 0.84, v0);
207
+
208
+ let u_flow = 0.0;
209
+ let knot_height = 0.0;
210
+ let knot_mask = 0.0;
211
+
212
+ if (knot_amt > 0.0 && young_fade > 0.2) {
213
+ for (let k = 0; k < 3; k++) {
214
+ const ku = ((k * 0.37 + 0.19 + ((seed * (k + 3)) & 255) / 255.0 * 0.15) % 1.0);
215
+ const kv = 0.18 + ((k * 0.31 + 0.11 + ((seed * (k + 7)) & 255) / 255.0 * 0.12) % 0.44);
216
+ let du = u0 - ku;
217
+ if (du > 0.5) du -= 1.0;
218
+ else if (du < -0.5) du += 1.0;
219
+ const dv = v0 - kv;
220
+
221
+ const rx = 0.08;
222
+ const ry = 0.045;
223
+ const xk = du / rx;
224
+ const yk = dv / ry;
225
+ const rho2 = xk * xk + yk * yk;
226
+
227
+ if (rho2 < 5.0) {
228
+ const exp_w = Math.exp(-0.55 * rho2);
229
+ u_flow += -du * 0.16 * exp_w * knot_amt * young_fade;
230
+ }
231
+ if (rho2 < 3.0) {
232
+ const rho = Math.sqrt(rho2);
233
+ const rim = 0.22 * Math.exp(-Math.pow((rho - 0.72) / 0.35, 2.0));
234
+ const w_k = smoothStep(1.65, 0.25, rho) * knot_amt * young_fade;
235
+ if (w_k > knot_mask) knot_mask = w_k;
236
+ knot_height += rim * knot_amt * young_fade;
237
+ }
238
+ }
239
+ }
240
+
241
+ // Band-limited (freq_u = 2..3) 3D macro-relief so 12..18-gon rings vary organically along V without Nyquist striping
242
+ const v_tile = ((v0 * 3.0) % 1.0 + 1.0) % 1.0;
243
+ const warp_u = clamp(
244
+ (sample_tileable_bark_noise(u0, v_tile, 2, 5, ox + 11.3, oy + 7.1, oz + 3.7) * 0.009 + u_flow) * young_fade,
245
+ -0.014,
246
+ 0.014
247
+ );
248
+
249
+ const n_macro1 = sample_tileable_bark_noise(u0, v_tile, 2, 7, ox, oy, oz);
250
+ const n_macro2 = sample_tileable_bark_noise(u0, v_tile, 3, 12, ox + 37.0, oy + 19.0, oz + 53.0);
251
+ const amp = bark_type === "birch" ? 0.34 : 0.46;
252
+ const h = clamp(0.5 + (0.58 * n_macro1 + 0.42 * n_macro2) * amp * young_fade + knot_height, 0.0, 1.0);
253
+
254
+ const eps = 0.02;
255
+ const n_plus = sample_tileable_bark_noise(u0 + eps, v_tile, 2, 6, ox, oy, oz);
256
+ const dh_du = clamp(((n_plus - n_macro1) / eps) * amp * young_fade, -1.0, 1.0);
257
+
258
+ out[0] = h;
259
+ out[1] = dh_du;
260
+ out[2] = warp_u;
261
+ out[3] = knot_mask;
262
+ }
263
+
264
+ /**
265
+ * Synthesizes a turn-key procedural PBR `StandardShadeMaterial` for tree bark, including
266
+ * Albedo (`ColorSpace.SRGB`), 2-channel Tangent-Space Normal (`ColorSpace.LinearSRGB`,
267
+ * `TextureFilterType.LinearNormal`), and ORM (`R=Occlusion, G=Roughness, B=Metalness=0`) textures.
268
+ *
269
+ * The horizontal axis `U in [0, 1)` tiles seamlessly around branch circumferences (`wrapS = Repeat`),
270
+ * while the vertical axis `V in [0, 1]` (`wrapT = ClampToEdge`) encodes continuous ontogenetic bark
271
+ * evolution from old ruptured basal trunk bark (`V ~ 0`) through mature trunk/bough bark (`V ~ 0.35`)
272
+ * to smooth young upper shoot/twig bark (`V ~ 0.9`).
273
+ *
274
+ * Because `V in [0, 1]` spans the full ontogenetic height of the tree (~8x longer in world space than
275
+ * a single circumference wrap `U in [0, 1)`), vertical texture resolution (`height = width * 4`) and
276
+ * vertical cellular/noise frequencies are scaled by the world-space aspect ratio so bark plates,
277
+ * fissures, and lenticels have crisp, isotropic world-space proportions without vertical stretching.
278
+ *
279
+ * @param {BarkMaterialConfig|Object} [config]
280
+ * @param {number} [seed=1]
281
+ * @returns {StandardShadeMaterial}
282
+ */
283
+ export function make_bark_material(config = new BarkMaterialConfig(), seed = 1) {
284
+ const cfg = config && config.isBarkMaterialConfig ? config : BarkMaterialConfig.from(config);
285
+ const width = Math.max(16, cfg.resolution | 0);
286
+ const v_aspect = width >= 128 ? 4 : 1;
287
+ const height = width * v_aspect;
288
+ const rng = seededRandom((seed ^ 0x2DDFA232) | 0);
289
+
290
+ const ox = (rng() - 0.5) * 200.0;
291
+ const oy = (rng() - 0.5) * 200.0;
292
+ const oz = (rng() - 0.5) * 200.0;
293
+
294
+ const albedo_sampler = Sampler2D.uint8(4, width, height);
295
+ const normal_sampler = Sampler2D.uint8(2, width, height);
296
+ const orm_sampler = Sampler2D.uint8(4, width, height);
297
+
298
+ const albedo_data = albedo_sampler.data;
299
+ const normal_data = normal_sampler.data;
300
+ const orm_data = orm_sampler.data;
301
+
302
+ const height_field = new Float32Array(width * height);
303
+ const rough_field = new Float32Array(width * height);
304
+
305
+ const freq_u = Math.max(1, cfg.fissure_frequency | 0);
306
+ const depth = clamp(cfg.fissure_depth, 0.0, 1.0);
307
+ const lenticel = clamp(cfg.lenticel_amount, 0.0, 1.0);
308
+ const peel_amt = clamp(cfg.peel_amount ?? 0.35, 0.0, 1.0);
309
+ const terrace = clamp(cfg.plate_terrace ?? 0.42, 0.0, 1.0);
310
+ const knot_amt = clamp(cfg.knot_amount ?? 0.55, 0.0, 1.0);
311
+ const moss_amt = clamp(cfg.moss_amount, 0.0, 1.0);
312
+ const base_rough = clamp(Math.max(0.86, cfg.roughness), 0.86, 0.98);
313
+
314
+ // Determine effective archetype
315
+ let bark_type = (cfg.bark_type || "fissured").toLowerCase();
316
+ if (bark_type === "fissured" && lenticel > 0.55 && cfg.primary_color.r > 0.72) {
317
+ bark_type = "birch";
318
+ }
319
+
320
+ const r1 = cfg.primary_color.r, g1 = cfg.primary_color.g, b1 = cfg.primary_color.b;
321
+ const r2 = cfg.secondary_color.r, g2 = cfg.secondary_color.g, b2 = cfg.secondary_color.b;
322
+ const ri = cfg.inner_bark_color?.r ?? 0.34;
323
+ const gi = cfg.inner_bark_color?.g ?? 0.27;
324
+ const bi = cfg.inner_bark_color?.b ?? 0.22;
325
+ const rm = cfg.moss_color.r, gm = cfg.moss_color.g, bm = cfg.moss_color.b;
326
+
327
+ const knot_sites = build_bark_knot_sites(seed, bark_type === "birch" ? 6 : 5, bark_type);
328
+
329
+ // Pass 1: Synthesize species-specific ontogenetic bark heightfield and albedo
330
+ for (let y = 0; y < height; y++) {
331
+ const v = (y + 0.5) / height;
332
+ // Ontogenetic zone weights along V in [0, 1]:
333
+ // - basal_w: [0.0, 0.20] (coarse buttress base & ruptured dark birch skirt)
334
+ // - mature_w: [0.18, 0.65] (characteristic trunk & primary bough bark)
335
+ // - young_w: [0.72, 1.0] (smooth finely striated young branch & shoot bark)
336
+ const basal_w = smoothStep(0.22, 0.03, v);
337
+ const young_w = smoothStep(0.62, 0.80, v);
338
+ const mature_w = 1.0 - young_w;
339
+
340
+ for (let x = 0; x < width; x++) {
341
+ const u = x / width;
342
+ const p_idx = y * width + x;
343
+
344
+ // 1. World-aspect-corrected knot / branch-collar scar geometry in mature/basal zone
345
+ let u_flow = 0.0;
346
+ let knot_h = 0.0;
347
+ let knot_scar_mask = 0.0;
348
+ let knot_rim_mask = 0.0;
349
+
350
+ if (knot_amt > 0.0 && mature_w > 0.15) {
351
+ for (let k = 0; k < knot_sites.length; k++) {
352
+ const ks = knot_sites[k];
353
+ let du = u - ks.u;
354
+ if (du > 0.5) du -= 1.0;
355
+ else if (du < -0.5) du += 1.0;
356
+ const dv = v - ks.v;
357
+
358
+ const xk = du / ks.rx;
359
+ const yk = dv / ks.ry;
360
+ const rho2 = xk * xk + yk * yk;
361
+ if (rho2 >= 5.5) {
362
+ continue;
363
+ }
364
+
365
+ u_flow += -du * 0.20 * Math.exp(-0.55 * rho2) * knot_amt * mature_w;
366
+
367
+ if (bark_type === "birch") {
368
+ // Characteristic dark craggy chevron "Birch Eye" branch-collar scar
369
+ const y_chev = yk + 0.45 * Math.pow(Math.abs(xk), 1.15);
370
+ const chev_ridge = Math.exp(-3.4 * y_chev * y_chev) * Math.exp(-1.10 * xk * xk);
371
+ const eye_pit = Math.exp(-2.6 * (xk * xk * 0.9 + (yk + 0.35) * (yk + 0.35) * 1.5));
372
+ const crag = sample_tileable_bark_noise(u, v, 10, 80, ox + 91.0, oy + 43.0, oz + 17.0);
373
+ const scar_val = clamp((chev_ridge * 0.80 + eye_pit * 0.90) * (0.85 + 0.25 * crag) * knot_amt * mature_w, 0.0, 1.0);
374
+ if (scar_val > knot_scar_mask) knot_scar_mask = scar_val;
375
+ knot_h += (0.04 * chev_ridge - 0.12 * eye_pit) * knot_amt * mature_w;
376
+ } else if (rho2 < 3.2) {
377
+ const rho = Math.sqrt(rho2);
378
+ const pit = rho < 0.55 ? -0.26 * Math.pow(Math.cos((rho / 0.55) * Math.PI * 0.5), 1.8) : 0.0;
379
+ const rim = 0.22 * Math.exp(-Math.pow((rho - 0.76) / 0.30, 2.0));
380
+ knot_h += (pit + rim) * knot_amt * mature_w;
381
+ if (rho < 0.60) {
382
+ knot_scar_mask = Math.max(knot_scar_mask, smoothStep(0.60, 0.18, rho) * knot_amt * mature_w);
383
+ }
384
+ knot_rim_mask = Math.max(knot_rim_mask, rim * knot_amt * mature_w);
385
+ }
386
+ }
387
+ }
388
+
389
+ let h = 0.5;
390
+ let cr = r1, cg = g1, cb = b1;
391
+ let rough = base_rough;
392
+
393
+ if (bark_type === "birch") {
394
+ // --- ARCHETYPE 2: SILVER / PAPER BIRCH (WORLD-ASPECT CALIBRATED) ---
395
+ const n_low = sample_tileable_bark_noise(u, v, 2, 16, ox, oy, oz);
396
+ const n_med = sample_tileable_bark_noise(u, v, 4, 64, ox + 37.0, oy + 19.0, oz + 53.0);
397
+ const n_high = sample_tileable_bark_noise(u, v, 8, 160, ox + 73.0, oy + 41.0, oz + 89.0);
398
+ const n_sheet = sample_tileable_bark_noise(u, v, 1, 96, ox + 15.0, oy + 67.0, oz + 31.0);
399
+
400
+ // 1) Jagged basal rupture zone (v in [0, 0.17]): dark charcoal deeply fissured basal skirt
401
+ const basal_warp = sample_tileable_bark_noise(u, v, 4, 24, ox + 51.0, oy + 13.0, oz + 77.0) * 0.04;
402
+ const fissure_wave = Math.pow(Math.abs(Math.sin((u + basal_warp) * Math.PI * (freq_u * 2))), 0.65);
403
+ const basal_crag_v = sample_tileable_bark_noise(u, v, freq_u * 2, 48, ox + 88.0, oy + 31.0, oz + 19.0);
404
+ const basal_cutoff = 0.15 + 0.04 * n_low + 0.045 * (1.0 - fissure_wave);
405
+ const birch_basal_mask = smoothStep(basal_cutoff + 0.035, basal_cutoff - 0.025, v);
406
+
407
+ // 2) Young shoot zone (v in [0.68, 1.0]): smooth warm bronze/copper-brown young birch bark
408
+ const young_cutoff = 0.70 + 0.025 * n_low;
409
+ const birch_young_mask = smoothStep(young_cutoff - 0.05, young_cutoff + 0.05, v);
410
+
411
+ // 3) Mature chalk-white periderm with crisp horizontal paper striations & lenticel dashes
412
+ const horiz_band = 0.5 + 0.5 * Math.sin(v * PI2 * 140.0 + n_low * 1.1 + n_sheet * 0.8);
413
+ const fine_horiz = 0.5 + 0.5 * Math.sin(v * PI2 * 280.0 + n_med * 0.7);
414
+
415
+ // Crisp thin horizontal lenticel dashes (3x220 and 6x360 cells so dashes are thin in world Y!)
416
+ sample_tileable_worley(SCRATCH_WORLEY, u + n_low * 0.012, v, 3, 220, seed ^ 0x13579BDF);
417
+ sample_tileable_worley(SCRATCH_WORLEY2, u + n_med * 0.008, v, 6, 360, seed ^ 0x2468ACE0);
418
+ const lent_dash1 = smoothStep(0.28, 0.07, SCRATCH_WORLEY[0]) * (SCRATCH_WORLEY[2] < lenticel * 0.55 ? 1.0 : 0.0);
419
+ const lent_dash2 = smoothStep(0.25, 0.06, SCRATCH_WORLEY2[0]) * (SCRATCH_WORLEY2[2] < lenticel * 0.65 ? 1.0 : 0.0);
420
+ const lent_line = Math.pow(Math.max(0.0, Math.sin(v * PI2 * 180.0 + n_low * 1.4)), 7.0)
421
+ * smoothStep(0.30, 0.75, n_med * 0.5 + 0.5);
422
+ const lent_mask = clamp(
423
+ Math.max(lent_dash1 * 0.85, Math.max(lent_dash2 * 0.70, lent_line * 0.60)) * lenticel,
424
+ 0.0,
425
+ 1.0
426
+ );
427
+
428
+ // Sparse horizontal warm-cinnamon exfoliating paper strips
429
+ const peel_wave = sample_tileable_bark_noise(u, v, 1, 56, ox + 129.0, oy + 59.0, oz + 103.0) * 0.70
430
+ + sample_tileable_bark_noise(u, v, 3, 112, ox + 17.0, oy + 83.0, oz + 47.0) * 0.30;
431
+ const peel_thresh = 0.45 - peel_amt * 0.26;
432
+ const peel_inner_mask = (peel_amt > 0.02 && peel_wave > peel_thresh && knot_scar_mask < 0.3)
433
+ ? clamp((peel_wave - peel_thresh) * 5.5, 0.0, 0.72) * (1.0 - birch_basal_mask) * (1.0 - birch_young_mask)
434
+ : 0.0;
435
+
436
+ const h_mature = 0.72
437
+ + 0.042 * horiz_band
438
+ + 0.024 * fine_horiz
439
+ + 0.020 * n_med
440
+ - 0.080 * lent_mask
441
+ - 0.060 * peel_inner_mask
442
+ + knot_h;
443
+
444
+ const h_basal = 0.14 + 0.46 * fissure_wave + 0.14 * basal_crag_v;
445
+ const h_young = 0.68 + 0.015 * horiz_band + 0.010 * n_high - 0.022 * lent_dash2;
446
+
447
+ h = lerp(h_mature, h_basal, birch_basal_mask);
448
+ h = clamp(lerp(h, h_young, birch_young_mask), 0.0, 1.0);
449
+
450
+ // Mature chalk-white periderm color
451
+ const paper_shade = 0.90 + 0.07 * horiz_band + 0.05 * fine_horiz - 0.04 * (n_low * 0.5 + 0.5);
452
+ cr = clamp(r1 * paper_shade, 0.0, 1.0);
453
+ cg = clamp(g1 * paper_shade, 0.0, 1.0);
454
+ cb = clamp(b1 * paper_shade, 0.0, 1.0);
455
+
456
+ if (peel_inner_mask > 0.0) {
457
+ const inner_var = 0.92 + 0.14 * horiz_band;
458
+ cr = lerp(cr, ri * inner_var, peel_inner_mask);
459
+ cg = lerp(cg, gi * inner_var, peel_inner_mask);
460
+ cb = lerp(cb, bi * inner_var, peel_inner_mask);
461
+ }
462
+
463
+ if (lent_mask > 0.0) {
464
+ const lm = lent_mask * 0.80 * (1.0 - birch_young_mask * 0.6);
465
+ cr = lerp(cr, r2 * 1.20, lm);
466
+ cg = lerp(cg, g2 * 1.15, lm);
467
+ cb = lerp(cb, b2 * 1.10, lm);
468
+ }
469
+
470
+ if (knot_scar_mask > 0.0) {
471
+ cr = lerp(cr, r2 * 0.68, knot_scar_mask);
472
+ cg = lerp(cg, g2 * 0.68, knot_scar_mask);
473
+ cb = lerp(cb, b2 * 0.68, knot_scar_mask);
474
+ }
475
+
476
+ if (birch_basal_mask > 0.0) {
477
+ const b_shade = 0.52 + 0.72 * fissure_wave + 0.18 * basal_crag_v;
478
+ const br = clamp(r2 * 1.35 * b_shade, 0.06, 0.40);
479
+ const bg = clamp(g2 * 1.32 * b_shade, 0.06, 0.38);
480
+ const bb = clamp(b2 * 1.28 * b_shade, 0.06, 0.36);
481
+ cr = lerp(cr, br, birch_basal_mask);
482
+ cg = lerp(cg, bg, birch_basal_mask);
483
+ cb = lerp(cb, bb, birch_basal_mask);
484
+ }
485
+
486
+ if (birch_young_mask > 0.0) {
487
+ const y_shade = 0.90 + 0.14 * horiz_band + 0.06 * n_med;
488
+ let yr = clamp(ri * 0.92 * y_shade, 0.18, 0.62);
489
+ let yg = clamp(gi * 0.88 * y_shade, 0.12, 0.46);
490
+ let yb = clamp(bi * 0.82 * y_shade, 0.08, 0.34);
491
+ const speck = lent_dash2 * 0.45;
492
+ yr = lerp(yr, 0.68, speck);
493
+ yg = lerp(yg, 0.60, speck);
494
+ yb = lerp(yb, 0.50, speck);
495
+
496
+ cr = lerp(cr, yr, birch_young_mask);
497
+ cg = lerp(cg, yg, birch_young_mask);
498
+ cb = lerp(cb, yb, birch_young_mask);
499
+ }
500
+
501
+ rough = clamp(base_rough + 0.05 * birch_basal_mask - 0.02 * birch_young_mask, 0.85, 0.97);
502
+ } else if (bark_type === "plated") {
503
+ // --- ARCHETYPE 3: RAGGED FLAKY CONIFER SCALE BARK (PINE / SPRUCE, WORLD-ASPECT CALIBRATED) ---
504
+ const warp_u = (
505
+ sample_tileable_bark_noise(u, v, 3, 20, ox + 11.3, oy + 7.1, oz + 3.7) * 0.042
506
+ + sample_tileable_bark_noise(u, v, freq_u * 2, 56, ox + 61.0, oy + 23.0, oz + 89.0) * 0.028
507
+ + u_flow
508
+ );
509
+ const warp_v = (
510
+ sample_tileable_bark_noise(u, v, 3, 18, ox + 29.1, oy + 13.7, oz + 61.9) * 0.008
511
+ + sample_tileable_bark_noise(u, v, freq_u * 2, 48, ox + 43.0, oy + 79.0, oz + 17.0) * 0.005
512
+ );
513
+ const uw = ((u + warp_u) % 1.0 + 1.0) % 1.0;
514
+ const vw = ((v + warp_v) % 1.0 + 1.0) % 1.0;
515
+
516
+ // World-aspect-calibrated scale lattice: 6x28 primary scales + 12x56 secondary scales
517
+ const cells_v = Math.max(12, Math.round(freq_u * 4.5));
518
+ sample_tileable_worley(SCRATCH_WORLEY, uw, vw, freq_u, cells_v, seed);
519
+ sample_tileable_worley(SCRATCH_WORLEY2, uw, vw, freq_u * 2, cells_v * 2, seed ^ 0x9E3779B9);
520
+
521
+ const df1 = SCRATCH_WORLEY[1];
522
+ const cid1 = SCRATCH_WORLEY[2];
523
+ const df2 = SCRATCH_WORLEY2[1];
524
+ const cid2 = SCRATCH_WORLEY2[2];
525
+
526
+ const fiber_n = sample_tileable_bark_noise(u, v, freq_u * 3, 64, ox + 53.0, oy + 97.0, oz + 23.0);
527
+ const fine_striation = sample_tileable_bark_noise(u, v, freq_u * 4, 48, ox + 19.0, oy + 71.0, oz + 41.0);
528
+
529
+ // Ragged scale edges + exfoliating stepped terraces
530
+ const jag_df1 = df1 + fiber_n * 0.065;
531
+ const plate_edge = smoothStep(0.02, 0.22, jag_df1) * smoothStep(0.01, 0.11, df2 + fiber_n * 0.04 + 0.03);
532
+ const contour_raw = clamp(jag_df1 * 1.55 + fiber_n * 0.08, 0.0, 0.999);
533
+ const contour_step = Math.floor(contour_raw * 4.0) / 4.0;
534
+ const contour_fract = (contour_raw * 4.0) - Math.floor(contour_raw * 4.0);
535
+ const step_lip = smoothStep(0.18, 0.02, contour_fract) * plate_edge;
536
+
537
+ const h_mature = clamp(
538
+ plate_edge * (0.46 + 0.24 * cid1 + 0.20 * lerp(contour_raw, contour_step, terrace) + 0.06 * cid2)
539
+ + fiber_n * 0.06
540
+ - basal_w * (1.0 - plate_edge) * 0.16
541
+ + knot_h,
542
+ 0.0,
543
+ 1.0
544
+ );
545
+
546
+ // Young conifer shoot bark (v > 0.72): finely striated, low-relief reddish-grey shoot bark
547
+ const h_young = 0.56 + 0.038 * fine_striation + 0.025 * fiber_n;
548
+ h = clamp(lerp(h_mature, h_young, young_w), 0.0, 1.0);
549
+
550
+ const crevice_mix = smoothStep(0.04, 0.36, plate_edge) * (1.0 - 0.70 * knot_scar_mask);
551
+ const plate_tint = 0.88 + 0.20 * cid1 + 0.07 * step_lip + 0.05 * fiber_n;
552
+ const pr_col = lerp(r1, ri, 0.28) * plate_tint;
553
+ const pg_col = lerp(g1, gi, 0.28) * plate_tint;
554
+ const pb_col = lerp(b1, bi, 0.28) * plate_tint;
555
+
556
+ const mr = lerp(r2 * 0.75, pr_col, crevice_mix);
557
+ const mg = lerp(g2 * 0.75, pg_col, crevice_mix);
558
+ const mb = lerp(b2 * 0.75, pb_col, crevice_mix);
559
+
560
+ const y_tint = 0.94 + 0.07 * fine_striation + 0.04 * fiber_n;
561
+ const yr = lerp(r1, r2, 0.25) * y_tint;
562
+ const yg = lerp(g1, g2, 0.25) * y_tint;
563
+ const yb = lerp(b1, b2, 0.25) * y_tint;
564
+
565
+ cr = lerp(mr, yr, young_w);
566
+ cg = lerp(mg, yg, young_w);
567
+ cb = lerp(mb, yb, young_w);
568
+ rough = clamp(lerp(0.95, base_rough, crevice_mix) * (1.0 - 0.03 * young_w), 0.86, 0.98);
569
+ } else if (bark_type === "ringed") {
570
+ // --- ARCHETYPE 4: RINGED / FIBROUS TRUNK BARK (PALM / SHRUB / FERN) ---
571
+ const n1 = sample_tileable_bark_noise(u, v, 2, 24, ox, oy, oz);
572
+ const n2 = sample_tileable_bark_noise(u, v, 12, 48, ox + 41.0, oy + 29.0, oz + 73.0);
573
+ const ring_wave = Math.pow(Math.abs(Math.sin(v * Math.PI * 56.0 + 0.25 * Math.sin(u * PI2 * 5.0) + n1 * 0.50)), 0.60);
574
+ const fiber_weave = 0.5 + 0.25 * Math.sin((u * 18.0 + v * 24.0) * PI2 + n2) + 0.25 * Math.sin((u * 18.0 - v * 24.0) * PI2 - n2);
575
+
576
+ const h_mature = clamp(0.65 * ring_wave + 0.25 * fiber_weave + 0.10 * n2 + knot_h, 0.0, 1.0);
577
+ const h_young = 0.58 + 0.08 * ring_wave + 0.06 * fiber_weave;
578
+ h = clamp(lerp(h_mature, h_young, young_w), 0.0, 1.0);
579
+
580
+ const mix_col = clamp(lerp(1.0 - depth * (1.0 - 0.65 * young_w), 1.0, h), 0.0, 1.0);
581
+ cr = lerp(r2, r1, mix_col);
582
+ cg = lerp(g2, g1, mix_col);
583
+ cb = lerp(b2, b1, mix_col);
584
+ rough = clamp(base_rough + (1.0 - h) * 0.08, 0.86, 0.98);
585
+ } else {
586
+ // --- ARCHETYPE 1: FISSURED / BRAIDED RIDGE BARK (OAK / WILLOW / MAPLE, WORLD-ASPECT CALIBRATED) ---
587
+ // Vertical frequencies are scaled to match the 1:8 world-space U:V aspect ratio so ridges anastomose
588
+ // naturally every 30-50cm along the trunk instead of stretching into 6-meter stripes!
589
+ const warp_u = (
590
+ sample_tileable_bark_noise(u, v, 3, 20, ox + 11.3, oy + 7.1, oz + 3.7) * 0.065
591
+ + sample_tileable_bark_noise(u, v, freq_u, 42, ox + 47.0, oy + 29.0, oz + 13.0) * 0.032
592
+ + u_flow
593
+ );
594
+ const warp_v = sample_tileable_bark_noise(u, v, 3, 16, ox + 23.1, oy + 17.9, oz + 41.2) * 0.008;
595
+ const uw = ((u + warp_u) % 1.0 + 1.0) % 1.0;
596
+ const vw = ((v + warp_v) % 1.0 + 1.0) % 1.0;
597
+
598
+ // Braided cellular Voronoi ridges + multi-harmonic vertical canyons + craggy transverse breaks
599
+ const cells_v = Math.max(10, Math.round(freq_u * 3.6));
600
+ sample_tileable_worley(SCRATCH_WORLEY, uw, vw, freq_u, cells_v, seed);
601
+ sample_tileable_worley(SCRATCH_WORLEY2, uw, vw, freq_u * 2, cells_v * 2, seed ^ 0x5A3C9E17);
602
+
603
+ const detail_n1 = sample_tileable_bark_noise(uw, vw, freq_u, 24, ox, oy, oz);
604
+ const detail_n2 = sample_tileable_bark_noise(uw, vw, freq_u * 2, 48, ox + 37.0, oy + 19.0, oz + 53.0);
605
+ const fiber_n3 = sample_tileable_bark_noise(u, v, freq_u * 4, 36, ox + 83.0, oy + 59.0, oz + 19.0);
606
+
607
+ // Anastomosing vertical ridges that split and merge around elongated cellular plates
608
+ const ridge_primary = Math.pow(Math.abs(Math.sin(uw * Math.PI * freq_u + detail_n1 * 1.35)), 0.62);
609
+ const ridge_secondary = Math.pow(Math.abs(Math.sin(uw * Math.PI * (freq_u * 2) + detail_n2 * 0.95)), 0.72);
610
+ const cell_ridge = smoothStep(0.03, 0.42, SCRATCH_WORLEY[1]) * (0.75 + 0.25 * smoothStep(0.02, 0.30, SCRATCH_WORLEY2[1]));
611
+ const braid = 0.44 * ridge_primary + 0.24 * ridge_secondary + 0.32 * cell_ridge;
612
+
613
+ let h_macro = smoothStep(0.14, 0.84, braid);
614
+ const h_terrace = Math.round(h_macro * 4.0) / 4.0;
615
+ h_macro = lerp(h_macro, h_terrace, terrace * 0.35);
616
+
617
+ // Basal zone has deeper, wider crevices; young zone transitions to smooth finely striated shoot bark
618
+ const h_mature = clamp(
619
+ h_macro * (1.0 - 0.14 * basal_w) + detail_n2 * 0.12 + fiber_n3 * 0.08 + knot_h,
620
+ 0.0,
621
+ 1.0
622
+ );
623
+ const h_young = 0.56 + 0.048 * ridge_secondary + 0.040 * fiber_n3 + 0.022 * detail_n2;
624
+ h = clamp(lerp(h_mature, h_young, young_w), 0.0, 1.0);
625
+
626
+ // Muted weathered ash-grey/taupe color ramp on mature trunk
627
+ const plate_mix = clamp(
628
+ lerp(1.0 - depth * 0.92, 1.0, Math.pow(h_mature, 1.12)) * (1.0 - 0.60 * knot_scar_mask),
629
+ 0.0,
630
+ 1.0
631
+ );
632
+ const cell_var = 0.92 + 0.14 * SCRATCH_WORLEY[2] + 0.06 * fiber_n3;
633
+ let mr = lerp(r2, r1 * cell_var, plate_mix);
634
+ let mg = lerp(g2, g1 * cell_var, plate_mix);
635
+ let mb = lerp(b2, b1 * cell_var, plate_mix);
636
+
637
+ // Subtle warm inner-bark tint deep inside active basal/mature fissures
638
+ const phloem_seam = smoothStep(0.05, 0.14, h_mature) * smoothStep(0.24, 0.14, h_mature) * depth;
639
+ mr = lerp(mr, ri, phloem_seam * 0.26);
640
+ mg = lerp(mg, gi, phloem_seam * 0.26);
641
+ mb = lerp(mb, bi, phloem_seam * 0.26);
642
+
643
+ // Subtle weathered silver-ash highlight on ridge crests
644
+ const ridge_crest = smoothStep(0.70, 0.92, h_mature) * 0.045 + knot_rim_mask * 0.05;
645
+ mr = clamp(mr + ridge_crest, 0.0, 1.0);
646
+ mg = clamp(mg + ridge_crest * 0.98, 0.0, 1.0);
647
+ mb = clamp(mb + ridge_crest * 0.94, 0.0, 1.0);
648
+
649
+ // Smooth finely striated young shoot bark (v in [0.74, 1.0]): cohesive olive-taupe/grey-brown
650
+ const young_var = 0.95 + 0.07 * fiber_n3 + 0.04 * ridge_secondary;
651
+ const yr = lerp(r2, r1, 0.68) * young_var;
652
+ const yg = lerp(g2, g1, 0.70) * young_var;
653
+ const yb = lerp(b2, b1, 0.66) * young_var;
654
+
655
+ cr = lerp(mr, yr, young_w);
656
+ cg = lerp(mg, yg, young_w);
657
+ cb = lerp(mb, yb, young_w);
658
+
659
+ rough = clamp(base_rough + (1.0 - h) * 0.08 - young_w * 0.03, 0.86, 0.98);
660
+ }
661
+
662
+ // Lichen / moss flecking (concentrated toward basal skirt and deep crevices on lower trunk)
663
+ const eff_moss = moss_amt * (0.45 + 0.55 * basal_w) * (1.0 - young_w);
664
+ if (eff_moss > 0.0) {
665
+ const m_noise = sample_tileable_bark_noise(u, v, 4, 28, ox + 113.0, oy + 61.0, oz + 97.0);
666
+ const m_score = (m_noise * 0.5 + 0.5) * 0.72 + (1.0 - h) * 0.28;
667
+ const moss_mask = smoothStep(1.0 - eff_moss * 1.45, 1.0, m_score) * eff_moss;
668
+ cr = lerp(cr, rm, moss_mask);
669
+ cg = lerp(cg, gm, moss_mask);
670
+ cb = lerp(cb, bm, moss_mask);
671
+ rough = clamp(rough + moss_mask * 0.06, 0.86, 0.99);
672
+ }
673
+
674
+ height_field[p_idx] = h;
675
+ rough_field[p_idx] = rough;
676
+
677
+ const i4 = p_idx * 4;
678
+ albedo_data[i4] = clamp(Math.round(cr * 255), 0, 255);
679
+ albedo_data[i4 + 1] = clamp(Math.round(cg * 255), 0, 255);
680
+ albedo_data[i4 + 2] = clamp(Math.round(cb * 255), 0, 255);
681
+ albedo_data[i4 + 3] = 255;
682
+ }
683
+ }
684
+
685
+ // Pass 2: 3x3 rotationally invariant Scharr normal map + multi-radius Laplacian cavity AO
686
+ const res_scale = Math.max(1.0, width / 64.0);
687
+ const base_slope = (bark_type === "birch"
688
+ ? (2.10 * depth + 0.45)
689
+ : (2.35 * depth + 0.52)) * res_scale;
690
+ const r_ao = Math.max(1, Math.round(width / 64));
691
+
692
+ for (let y = 0; y < height; y++) {
693
+ // Clamp Y at ontogenetic boundaries so basal trunk (y=0) never bleeds into young shoots (y=height-1)
694
+ const ym1 = Math.max(0, y - 1);
695
+ const yp1 = Math.min(height - 1, y + 1);
696
+ const ym_ao = Math.max(0, y - r_ao);
697
+ const yp_ao = Math.min(height - 1, y + r_ao);
698
+
699
+ for (let x = 0; x < width; x++) {
700
+ const xm1 = (x - 1 + width) % width;
701
+ const xp1 = (x + 1) % width;
702
+ const xm_ao = (x - r_ao + width) % width;
703
+ const xp_ao = (x + r_ao) % width;
704
+
705
+ const p_idx = y * width + x;
706
+ const h_c = height_field[p_idx];
707
+
708
+ const h_mm = height_field[ym1 * width + xm1];
709
+ const h_0m = height_field[ym1 * width + x];
710
+ const h_pm = height_field[ym1 * width + xp1];
711
+ const h_m0 = height_field[y * width + xm1];
712
+ const h_p0 = height_field[y * width + xp1];
713
+ const h_mp = height_field[yp1 * width + xm1];
714
+ const h_0p = height_field[yp1 * width + x];
715
+ const h_pp = height_field[yp1 * width + xp1];
716
+
717
+ // 3x3 Scharr derivative
718
+ const gu = (3.0 * (h_pm - h_mm) + 10.0 * (h_p0 - h_m0) + 3.0 * (h_pp - h_mp)) / 32.0;
719
+ const gv = (3.0 * (h_mp - h_mm) + 10.0 * (h_0p - h_0m) + 3.0 * (h_pp - h_pm)) / 32.0;
720
+
721
+ let nx = -gu * base_slope;
722
+ let ny = -gv * base_slope;
723
+ let nz = 1.0;
724
+ const nl = Math.sqrt(nx * nx + ny * ny + nz * nz);
725
+ nx /= nl;
726
+ ny /= nl;
727
+
728
+ const i2 = p_idx * 2;
729
+ normal_data[i2] = clamp(Math.round((nx * 0.5 + 0.5) * 255), 0, 255);
730
+ normal_data[i2 + 1] = clamp(Math.round((ny * 0.5 + 0.5) * 255), 0, 255);
731
+
732
+ // Multi-scale neighborhood average for local concavity / crevice shadow
733
+ const h_avg = 0.125 * (
734
+ height_field[y * width + xm_ao] +
735
+ height_field[y * width + xp_ao] +
736
+ height_field[ym_ao * width + x] +
737
+ height_field[yp_ao * width + x] +
738
+ h_m0 + h_p0 + h_0m + h_0p
739
+ );
740
+ const cavity = Math.max(0.0, h_avg - h_c);
741
+ const ao = clamp(
742
+ lerp(1.0 - depth * 0.78, 1.0, Math.pow(h_c, 0.82)) - cavity * 2.2,
743
+ 0.08,
744
+ 1.0
745
+ );
746
+
747
+ const i4 = p_idx * 4;
748
+ orm_data[i4] = clamp(Math.round(ao * 255), 0, 255);
749
+ orm_data[i4 + 1] = clamp(Math.round(rough_field[p_idx] * 255), 0, 255);
750
+ orm_data[i4 + 2] = 0;
751
+ orm_data[i4 + 3] = 255;
752
+ }
753
+ }
754
+
755
+ const albedo_image = ShadeImage.fromSampler2D(albedo_sampler);
756
+ albedo_image.color_space = ColorSpace.SRGB;
757
+ albedo_image.alpha_mode = AlphaMode.Opaque;
758
+ const texture_albedo = ShadeTexture.from(albedo_image);
759
+ texture_albedo.label = "foliage_bark_albedo";
760
+ texture_albedo.color_space = ColorSpace.SRGB;
761
+ texture_albedo.mipmapGenerationFilter = TextureFilterType.Linear;
762
+ texture_albedo.wrapS = TextureWrapType.Repeat;
763
+ texture_albedo.wrapT = TextureWrapType.ClampToEdge;
764
+
765
+ const normal_image = ShadeImage.fromSampler2D(normal_sampler);
766
+ normal_image.color_space = ColorSpace.None;
767
+ normal_image.alpha_mode = AlphaMode.Opaque;
768
+ const texture_normal = ShadeTexture.from(normal_image);
769
+ texture_normal.label = "foliage_bark_normal";
770
+ texture_normal.color_space = ColorSpace.LinearSRGB;
771
+ texture_normal.mipmapGenerationFilter = TextureFilterType.LinearNormal;
772
+ texture_normal.wrapS = TextureWrapType.Repeat;
773
+ texture_normal.wrapT = TextureWrapType.ClampToEdge;
774
+
775
+ const orm_image = ShadeImage.fromSampler2D(orm_sampler);
776
+ orm_image.color_space = ColorSpace.None;
777
+ orm_image.alpha_mode = AlphaMode.Opaque;
778
+ const texture_orm = ShadeTexture.from(orm_image);
779
+ texture_orm.label = "foliage_bark_orm";
780
+ texture_orm.color_space = ColorSpace.LinearSRGB;
781
+ texture_orm.wrapS = TextureWrapType.Repeat;
782
+ texture_orm.wrapT = TextureWrapType.ClampToEdge;
783
+
784
+ const material = new StandardShadeMaterial();
785
+ material.name = "foliage_bark_material";
786
+ material.texture_albedo = texture_albedo;
787
+ material.texture_normal = texture_normal;
788
+ material.texture_orm = texture_orm;
789
+ material.roughness_factor = 1.0;
790
+ material.metallic_factor = 0.0;
791
+ material.ior_factor = 1.25;
792
+ material.transmission_factor = 0.0;
793
+ // CRITICAL: StandardShadeMaterial defaults ambient_factors to LinearModifier(1, 1);
794
+ // set offset to 0 so ORM.r and vertex color AO actually darken crevices!
795
+ material.ambient_factors.a = 1.0;
796
+ material.ambient_factors.b = 0.0;
797
+ material.transparency_mode = TransparencyMode.Opaque;
798
+ material.transparency = TransparencyMode.Opaque;
799
+ material.draw_side = ShadeDrawSide.Front;
800
+
801
+ return material;
802
+ }