@zephyr3d/scene 0.9.27 → 0.10.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 (502) hide show
  1. package/README.md +60 -27
  2. package/dist/animation/animation_bank.js +634 -0
  3. package/dist/animation/animation_bank.js.map +1 -0
  4. package/dist/animation/animation_bank_gpu.js +256 -0
  5. package/dist/animation/animation_bank_gpu.js.map +1 -0
  6. package/dist/animation/animationset.js +54 -0
  7. package/dist/animation/animationset.js.map +1 -1
  8. package/dist/animation/cloth/gpu_cloth_component.js +406 -0
  9. package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
  10. package/dist/animation/cloth/gpu_cloth_system.js +332 -202
  11. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  12. package/dist/animation/gpu_animation_driver.js +289 -0
  13. package/dist/animation/gpu_animation_driver.js.map +1 -0
  14. package/dist/animation/joint_dynamics/collision.js +112 -1
  15. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  16. package/dist/animation/joint_dynamics/controller.js +6 -0
  17. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
  19. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  20. package/dist/animation/joint_dynamics/solver.js +50 -12
  21. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/skeleton.js +279 -55
  24. package/dist/animation/skeleton.js.map +1 -1
  25. package/dist/animation/skin_palette_atlas.js +252 -0
  26. package/dist/animation/skin_palette_atlas.js.map +1 -0
  27. package/dist/animation/spring/multi_chain_spring_system.js +298 -38
  28. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  29. package/dist/animation/spring/spring_chain.js +2 -0
  30. package/dist/animation/spring/spring_chain.js.map +1 -1
  31. package/dist/animation/spring/spring_collider.js +159 -21
  32. package/dist/animation/spring/spring_collider.js.map +1 -1
  33. package/dist/animation/spring/spring_particle.js +1 -0
  34. package/dist/animation/spring/spring_particle.js.map +1 -1
  35. package/dist/animation/spring/spring_solver.js +173 -0
  36. package/dist/animation/spring/spring_solver.js.map +1 -0
  37. package/dist/animation/spring/spring_system.js +249 -24
  38. package/dist/animation/spring/spring_system.js.map +1 -1
  39. package/dist/animation/spring_modifier.js +32 -1
  40. package/dist/animation/spring_modifier.js.map +1 -1
  41. package/dist/app/app.js +26 -0
  42. package/dist/app/app.js.map +1 -1
  43. package/dist/app/engine.js +86 -15
  44. package/dist/app/engine.js.map +1 -1
  45. package/dist/app/gamepad.js +191 -0
  46. package/dist/app/gamepad.js.map +1 -0
  47. package/dist/app/inputactions.js +271 -0
  48. package/dist/app/inputactions.js.map +1 -0
  49. package/dist/app/inputmgr.js +331 -22
  50. package/dist/app/inputmgr.js.map +1 -1
  51. package/dist/app/loading.js +138 -0
  52. package/dist/app/loading.js.map +1 -0
  53. package/dist/app/pipelinecache.js +209 -0
  54. package/dist/app/pipelinecache.js.map +1 -0
  55. package/dist/app/runtimescript.js +25 -0
  56. package/dist/app/runtimescript.js.map +1 -1
  57. package/dist/app/scriptingsystem.js +54 -0
  58. package/dist/app/scriptingsystem.js.map +1 -1
  59. package/dist/app/scriptregistry.js +7 -2
  60. package/dist/app/scriptregistry.js.map +1 -1
  61. package/dist/asset/asset_manifest.js +59 -0
  62. package/dist/asset/asset_manifest.js.map +1 -0
  63. package/dist/asset/asset_preload.js +258 -0
  64. package/dist/asset/asset_preload.js.map +1 -0
  65. package/dist/asset/assetmanager.js +117 -65
  66. package/dist/asset/assetmanager.js.map +1 -1
  67. package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
  68. package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  69. package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  70. package/dist/asset/loaders/ktx2/basis_location.js +17 -0
  71. package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
  72. package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
  73. package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
  74. package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
  75. package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
  76. package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
  77. package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
  78. package/dist/asset/mesh_lod_builder.js +104 -0
  79. package/dist/asset/mesh_lod_builder.js.map +1 -0
  80. package/dist/asset/mesh_settings.js +111 -0
  81. package/dist/asset/mesh_settings.js.map +1 -0
  82. package/dist/asset/meshopt_decoder.js +18 -0
  83. package/dist/asset/meshopt_decoder.js.map +1 -0
  84. package/dist/asset/meshopt_simplifier.js +26 -0
  85. package/dist/asset/meshopt_simplifier.js.map +1 -0
  86. package/dist/asset/model.js +171 -1
  87. package/dist/asset/model.js.map +1 -1
  88. package/dist/asset/texture_settings.js +231 -0
  89. package/dist/asset/texture_settings.js.map +1 -0
  90. package/dist/asset/zmsh_binary.js +131 -0
  91. package/dist/asset/zmsh_binary.js.map +1 -0
  92. package/dist/asset/zsdf_binary.js +111 -0
  93. package/dist/asset/zsdf_binary.js.map +1 -0
  94. package/dist/blitter/bilateralblur.js +1 -2
  95. package/dist/blitter/bilateralblur.js.map +1 -1
  96. package/dist/blitter/gaussianblur.js +1 -6
  97. package/dist/blitter/gaussianblur.js.map +1 -1
  98. package/dist/camera/base.js +31 -10
  99. package/dist/camera/base.js.map +1 -1
  100. package/dist/camera/camera.js +104 -178
  101. package/dist/camera/camera.js.map +1 -1
  102. package/dist/camera/follow.js +342 -0
  103. package/dist/camera/follow.js.map +1 -0
  104. package/dist/camera/fps.js +9 -7
  105. package/dist/camera/fps.js.map +1 -1
  106. package/dist/camera/orbit.js +46 -19
  107. package/dist/camera/orbit.js.map +1 -1
  108. package/dist/index.d.ts +25436 -15990
  109. package/dist/index.js +65 -11
  110. package/dist/index.js.map +1 -1
  111. package/dist/material/blinn.js +3 -0
  112. package/dist/material/blinn.js.map +1 -1
  113. package/dist/material/eye.js +1 -1
  114. package/dist/material/eye.js.map +1 -1
  115. package/dist/material/hair.js +2 -3
  116. package/dist/material/hair.js.map +1 -1
  117. package/dist/material/lambert.js +4 -1
  118. package/dist/material/lambert.js.map +1 -1
  119. package/dist/material/material.js +66 -4
  120. package/dist/material/material.js.map +1 -1
  121. package/dist/material/meshmaterial.js +118 -45
  122. package/dist/material/meshmaterial.js.map +1 -1
  123. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  124. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  126. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  128. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  130. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  132. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  133. package/dist/material/mixins/lit.js +191 -83
  134. package/dist/material/mixins/lit.js.map +1 -1
  135. package/dist/material/mixins/pbr/common.js +31 -206
  136. package/dist/material/mixins/pbr/common.js.map +1 -1
  137. package/dist/material/mtoon.js +1 -1
  138. package/dist/material/mtoon.js.map +1 -1
  139. package/dist/material/pbrmr.js +3 -0
  140. package/dist/material/pbrmr.js.map +1 -1
  141. package/dist/material/pbrsg.js +3 -0
  142. package/dist/material/pbrsg.js.map +1 -1
  143. package/dist/material/sdf_debug.js +78 -0
  144. package/dist/material/sdf_debug.js.map +1 -0
  145. package/dist/material/shader/helper.js +333 -191
  146. package/dist/material/shader/helper.js.map +1 -1
  147. package/dist/material/shader/terrain_blend.js +204 -43
  148. package/dist/material/shader/terrain_blend.js.map +1 -1
  149. package/dist/material/skin.js +331 -297
  150. package/dist/material/skin.js.map +1 -1
  151. package/dist/material/skinprofile.js +1058 -0
  152. package/dist/material/skinprofile.js.map +1 -0
  153. package/dist/material/sss.js +353 -0
  154. package/dist/material/sss.js.map +1 -0
  155. package/dist/material/sss_kernel.js +265 -0
  156. package/dist/material/sss_kernel.js.map +1 -0
  157. package/dist/material/sssprofile.js +879 -0
  158. package/dist/material/sssprofile.js.map +1 -0
  159. package/dist/material/subsurfaceprofile.js +4 -8
  160. package/dist/material/subsurfaceprofile.js.map +1 -1
  161. package/dist/material/terrain-cm.js +464 -188
  162. package/dist/material/terrain-cm.js.map +1 -1
  163. package/dist/material/unlit.js +3 -0
  164. package/dist/material/unlit.js.map +1 -1
  165. package/dist/material/water.js +1261 -1438
  166. package/dist/material/water.js.map +1 -1
  167. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  168. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  169. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  172. package/dist/physics/character.js +226 -0
  173. package/dist/physics/character.js.map +1 -0
  174. package/dist/physics/collider.js +209 -0
  175. package/dist/physics/collider.js.map +1 -0
  176. package/dist/physics/events.js +79 -0
  177. package/dist/physics/events.js.map +1 -0
  178. package/dist/physics/joint.js +272 -0
  179. package/dist/physics/joint.js.map +1 -0
  180. package/dist/physics/node_physics.js +234 -0
  181. package/dist/physics/node_physics.js.map +1 -0
  182. package/dist/physics/part.js +91 -0
  183. package/dist/physics/part.js.map +1 -0
  184. package/dist/physics/rigid_body.js +379 -0
  185. package/dist/physics/rigid_body.js.map +1 -0
  186. package/dist/physics/vehicle.js +335 -0
  187. package/dist/physics/vehicle.js.map +1 -0
  188. package/dist/physics/world.js +25 -0
  189. package/dist/physics/world.js.map +1 -0
  190. package/dist/posteffect/bloom.js +49 -14
  191. package/dist/posteffect/bloom.js.map +1 -1
  192. package/dist/posteffect/motionblur.js +106 -106
  193. package/dist/posteffect/motionblur.js.map +1 -1
  194. package/dist/posteffect/postsss.js +572 -0
  195. package/dist/posteffect/postsss.js.map +1 -0
  196. package/dist/posteffect/sao.js +2 -6
  197. package/dist/posteffect/sao.js.map +1 -1
  198. package/dist/posteffect/skinsss.js +605 -355
  199. package/dist/posteffect/skinsss.js.map +1 -1
  200. package/dist/posteffect/ssgi.js +91 -162
  201. package/dist/posteffect/ssgi.js.map +1 -1
  202. package/dist/posteffect/ssr.js +3 -11
  203. package/dist/posteffect/ssr.js.map +1 -1
  204. package/dist/posteffect/sss.js +4 -13
  205. package/dist/posteffect/sss.js.map +1 -1
  206. package/dist/posteffect/taa.js +1 -0
  207. package/dist/posteffect/taa.js.map +1 -1
  208. package/dist/render/abuffer_oit.js +3 -2
  209. package/dist/render/abuffer_oit.js.map +1 -1
  210. package/dist/render/clipmap.js +179 -64
  211. package/dist/render/clipmap.js.map +1 -1
  212. package/dist/render/cluster_light.js +958 -224
  213. package/dist/render/cluster_light.js.map +1 -1
  214. package/dist/render/cull_visitor.js +25 -5
  215. package/dist/render/cull_visitor.js.map +1 -1
  216. package/dist/render/debug_views.js +37 -0
  217. package/dist/render/debug_views.js.map +1 -0
  218. package/dist/render/depthpass.js +5 -1
  219. package/dist/render/depthpass.js.map +1 -1
  220. package/dist/render/drawable_mixin.js +53 -6
  221. package/dist/render/drawable_mixin.js.map +1 -1
  222. package/dist/render/dualdepthpeeling_oit.js +5 -5
  223. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  224. package/dist/render/envlight.js +196 -113
  225. package/dist/render/envlight.js.map +1 -1
  226. package/dist/render/fbm_wavegenerator.js +5 -10
  227. package/dist/render/fbm_wavegenerator.js.map +1 -1
  228. package/dist/render/fft_wavegenerator.js +247 -157
  229. package/dist/render/fft_wavegenerator.js.map +1 -1
  230. package/dist/render/gerstner_wavegenerator.js +16 -38
  231. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  232. package/dist/render/gi/probe_volume.js +1334 -0
  233. package/dist/render/gi/probe_volume.js.map +1 -0
  234. package/dist/render/gi/scene_gi.js +282 -0
  235. package/dist/render/gi/scene_gi.js.map +1 -0
  236. package/dist/render/gi/voxel_atlas.js +198 -0
  237. package/dist/render/gi/voxel_atlas.js.map +1 -0
  238. package/dist/render/gi/voxel_lighting.js +652 -0
  239. package/dist/render/gi/voxel_lighting.js.map +1 -0
  240. package/dist/render/gi/voxel_scene.js +642 -0
  241. package/dist/render/gi/voxel_scene.js.map +1 -0
  242. package/dist/render/gi/voxelize_pass.js +223 -0
  243. package/dist/render/gi/voxelize_pass.js.map +1 -0
  244. package/dist/render/globalbindgroup_allocator.js +3 -2
  245. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  246. package/dist/render/gpu_picking.js +9 -36
  247. package/dist/render/gpu_picking.js.map +1 -1
  248. package/dist/render/instance_culling.js +499 -0
  249. package/dist/render/instance_culling.js.map +1 -0
  250. package/dist/render/lightpass.js +19 -8
  251. package/dist/render/lightpass.js.map +1 -1
  252. package/dist/render/lod.js +46 -0
  253. package/dist/render/lod.js.map +1 -0
  254. package/dist/render/primitive.js +301 -9
  255. package/dist/render/primitive.js.map +1 -1
  256. package/dist/render/primitive_readback.js +209 -0
  257. package/dist/render/primitive_readback.js.map +1 -0
  258. package/dist/render/render_queue.js +162 -11
  259. package/dist/render/render_queue.js.map +1 -1
  260. package/dist/render/renderer.js +10 -7
  261. package/dist/render/renderer.js.map +1 -1
  262. package/dist/render/rendergraph/blackboard.js +14 -1
  263. package/dist/render/rendergraph/blackboard.js.map +1 -1
  264. package/dist/render/rendergraph/executor.js +136 -0
  265. package/dist/render/rendergraph/executor.js.map +1 -1
  266. package/dist/render/rendergraph/forward_plus_builder.js +272 -55
  267. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  268. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  269. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  270. package/dist/render/rendergraph/scene_render_context.js +31 -2
  271. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  272. package/dist/render/rendergraph/types.js.map +1 -1
  273. package/dist/render/renderpass.js +28 -5
  274. package/dist/render/renderpass.js.map +1 -1
  275. package/dist/render/sdf/box_allocator.js +98 -0
  276. package/dist/render/sdf/box_allocator.js.map +1 -0
  277. package/dist/render/sdf/global_sdf.js +865 -0
  278. package/dist/render/sdf/global_sdf.js.map +1 -0
  279. package/dist/render/sdf/scene_sdf.js +562 -0
  280. package/dist/render/sdf/scene_sdf.js.map +1 -0
  281. package/dist/render/sdf/sdf_atlas.js +227 -0
  282. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  283. package/dist/render/sdf/sdf_programs.js +42 -0
  284. package/dist/render/sdf/sdf_programs.js.map +1 -0
  285. package/dist/render/sdf/sdf_view.js +199 -0
  286. package/dist/render/sdf/sdf_view.js.map +1 -0
  287. package/dist/render/sdf/waterline.js +610 -0
  288. package/dist/render/sdf/waterline.js.map +1 -0
  289. package/dist/render/shadow_mask_pass.js +142 -25
  290. package/dist/render/shadow_mask_pass.js.map +1 -1
  291. package/dist/render/shore_wave_generator.js +1193 -0
  292. package/dist/render/shore_wave_generator.js.map +1 -0
  293. package/dist/render/sky.js +516 -86
  294. package/dist/render/sky.js.map +1 -1
  295. package/dist/render/transmission_thickness_pass.js +477 -0
  296. package/dist/render/transmission_thickness_pass.js.map +1 -0
  297. package/dist/render/underwater.js +58 -158
  298. package/dist/render/underwater.js.map +1 -1
  299. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  300. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  301. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  302. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  303. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  304. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  305. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  306. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  307. package/dist/render/volumetric_cloud/resources.js +380 -0
  308. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  309. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  310. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  311. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  312. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  313. package/dist/render/water_caustics.js +134 -319
  314. package/dist/render/water_caustics.js.map +1 -1
  315. package/dist/render/water_foam.js +627 -0
  316. package/dist/render/water_foam.js.map +1 -0
  317. package/dist/render/water_interaction.js +1795 -0
  318. package/dist/render/water_interaction.js.map +1 -0
  319. package/dist/render/weightedblended_oit.js +3 -3
  320. package/dist/render/weightedblended_oit.js.map +1 -1
  321. package/dist/scene/basesprite.js +9 -4
  322. package/dist/scene/basesprite.js.map +1 -1
  323. package/dist/scene/batchgroup.js +108 -12
  324. package/dist/scene/batchgroup.js.map +1 -1
  325. package/dist/scene/environment.js +28 -7
  326. package/dist/scene/environment.js.map +1 -1
  327. package/dist/scene/foliage.js +1020 -0
  328. package/dist/scene/foliage.js.map +1 -0
  329. package/dist/scene/foliage_buckets.js +147 -0
  330. package/dist/scene/foliage_buckets.js.map +1 -0
  331. package/dist/scene/foliage_mask.js +358 -0
  332. package/dist/scene/foliage_mask.js.map +1 -0
  333. package/dist/scene/hair.js +15 -4
  334. package/dist/scene/hair.js.map +1 -1
  335. package/dist/scene/light.js +179 -13
  336. package/dist/scene/light.js.map +1 -1
  337. package/dist/scene/mesh.js +327 -45
  338. package/dist/scene/mesh.js.map +1 -1
  339. package/dist/scene/meshdrawable.js +6 -0
  340. package/dist/scene/meshdrawable.js.map +1 -1
  341. package/dist/scene/msdftext.js +9 -3
  342. package/dist/scene/msdftext.js.map +1 -1
  343. package/dist/scene/msdftextsprite.js +9 -3
  344. package/dist/scene/msdftextsprite.js.map +1 -1
  345. package/dist/scene/particlesys.js +8 -2
  346. package/dist/scene/particlesys.js.map +1 -1
  347. package/dist/scene/physics_settings.js +157 -0
  348. package/dist/scene/physics_settings.js.map +1 -0
  349. package/dist/scene/scene.js +190 -44
  350. package/dist/scene/scene.js.map +1 -1
  351. package/dist/scene/scene_node.js +147 -6
  352. package/dist/scene/scene_node.js.map +1 -1
  353. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  354. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  355. package/dist/scene/terrain-cm/grass.js +881 -42
  356. package/dist/scene/terrain-cm/grass.js.map +1 -1
  357. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  358. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  359. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  360. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  361. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  362. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  363. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  364. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  365. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  366. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  367. package/dist/scene/update_queue.js +54 -0
  368. package/dist/scene/update_queue.js.map +1 -0
  369. package/dist/scene/water.js +633 -268
  370. package/dist/scene/water.js.map +1 -1
  371. package/dist/scene/water_surface_sampler.js +324 -0
  372. package/dist/scene/water_surface_sampler.js.map +1 -0
  373. package/dist/scene/wind.js +317 -0
  374. package/dist/scene/wind.js.map +1 -0
  375. package/dist/shaders/atmosphere.js +388 -166
  376. package/dist/shaders/atmosphere.js.map +1 -1
  377. package/dist/shaders/fog.js +100 -32
  378. package/dist/shaders/fog.js.map +1 -1
  379. package/dist/shaders/gi.js +365 -0
  380. package/dist/shaders/gi.js.map +1 -0
  381. package/dist/shaders/ltc_rect.js +202 -0
  382. package/dist/shaders/ltc_rect.js.map +1 -0
  383. package/dist/shaders/misc.js +1 -10
  384. package/dist/shaders/misc.js.map +1 -1
  385. package/dist/shaders/noise.js +5 -1
  386. package/dist/shaders/noise.js.map +1 -1
  387. package/dist/shaders/probes.js +309 -0
  388. package/dist/shaders/probes.js.map +1 -0
  389. package/dist/shaders/sdf.js +537 -0
  390. package/dist/shaders/sdf.js.map +1 -0
  391. package/dist/shaders/shadow.js +104 -70
  392. package/dist/shaders/shadow.js.map +1 -1
  393. package/dist/shaders/skin_brdf.js +243 -0
  394. package/dist/shaders/skin_brdf.js.map +1 -0
  395. package/dist/shaders/ssgi.js +63 -0
  396. package/dist/shaders/ssgi.js.map +1 -0
  397. package/dist/shaders/ssgi_reprojection.js +118 -0
  398. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  399. package/dist/shaders/ssr.js +6 -159
  400. package/dist/shaders/ssr.js.map +1 -1
  401. package/dist/shaders/temporal.js +38 -27
  402. package/dist/shaders/temporal.js.map +1 -1
  403. package/dist/shaders/water.js +32 -82
  404. package/dist/shaders/water.js.map +1 -1
  405. package/dist/shaders/water_medium.js +7 -21
  406. package/dist/shaders/water_medium.js.map +1 -1
  407. package/dist/shadow/dom.js +110 -19
  408. package/dist/shadow/dom.js.map +1 -1
  409. package/dist/shadow/esm.js +3 -3
  410. package/dist/shadow/esm.js.map +1 -1
  411. package/dist/shadow/pcf_opt.js +15 -48
  412. package/dist/shadow/pcf_opt.js.map +1 -1
  413. package/dist/shadow/pcf_pd.js +15 -53
  414. package/dist/shadow/pcf_pd.js.map +1 -1
  415. package/dist/shadow/pcss.js +34 -9
  416. package/dist/shadow/pcss.js.map +1 -1
  417. package/dist/shadow/shadow_impl.js +3 -8
  418. package/dist/shadow/shadow_impl.js.map +1 -1
  419. package/dist/shadow/shadow_region.js +40 -2
  420. package/dist/shadow/shadow_region.js.map +1 -1
  421. package/dist/shadow/shadowmapper.js +93 -53
  422. package/dist/shadow/shadowmapper.js.map +1 -1
  423. package/dist/shadow/ssm.js +18 -72
  424. package/dist/shadow/ssm.js.map +1 -1
  425. package/dist/shadow/vsm.js +3 -3
  426. package/dist/shadow/vsm.js.map +1 -1
  427. package/dist/shapes/shape.js +44 -1
  428. package/dist/shapes/shape.js.map +1 -1
  429. package/dist/utility/buoyancy.js +287 -0
  430. package/dist/utility/buoyancy.js.map +1 -0
  431. package/dist/utility/physical.js +10 -1
  432. package/dist/utility/physical.js.map +1 -1
  433. package/dist/utility/pmrem.js +17 -43
  434. package/dist/utility/pmrem.js.map +1 -1
  435. package/dist/utility/sdf/bake.js +435 -0
  436. package/dist/utility/sdf/bake.js.map +1 -0
  437. package/dist/utility/sdf/bvh.js +576 -0
  438. package/dist/utility/sdf/bvh.js.map +1 -0
  439. package/dist/utility/serialization/manager.js +34 -6
  440. package/dist/utility/serialization/manager.js.map +1 -1
  441. package/dist/utility/serialization/scene/animation.js +46 -5
  442. package/dist/utility/serialization/scene/animation.js.map +1 -1
  443. package/dist/utility/serialization/scene/batch.js +11 -4
  444. package/dist/utility/serialization/scene/batch.js.map +1 -1
  445. package/dist/utility/serialization/scene/camera.js +87 -254
  446. package/dist/utility/serialization/scene/camera.js.map +1 -1
  447. package/dist/utility/serialization/scene/cloth.js +25 -0
  448. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  449. package/dist/utility/serialization/scene/common.js +14 -6
  450. package/dist/utility/serialization/scene/common.js.map +1 -1
  451. package/dist/utility/serialization/scene/foliage.js +821 -0
  452. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  453. package/dist/utility/serialization/scene/hair.js +11 -4
  454. package/dist/utility/serialization/scene/hair.js.map +1 -1
  455. package/dist/utility/serialization/scene/light.js +115 -7
  456. package/dist/utility/serialization/scene/light.js.map +1 -1
  457. package/dist/utility/serialization/scene/material.js +388 -220
  458. package/dist/utility/serialization/scene/material.js.map +1 -1
  459. package/dist/utility/serialization/scene/mesh.js +69 -4
  460. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  461. package/dist/utility/serialization/scene/node.js +140 -5
  462. package/dist/utility/serialization/scene/node.js.map +1 -1
  463. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  464. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  465. package/dist/utility/serialization/scene/particle.js +11 -4
  466. package/dist/utility/serialization/scene/particle.js.map +1 -1
  467. package/dist/utility/serialization/scene/physics.js +120 -0
  468. package/dist/utility/serialization/scene/physics.js.map +1 -0
  469. package/dist/utility/serialization/scene/primitive.js +124 -10
  470. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  471. package/dist/utility/serialization/scene/scene.js +1687 -51
  472. package/dist/utility/serialization/scene/scene.js.map +1 -1
  473. package/dist/utility/serialization/scene/sprite.js +11 -4
  474. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  475. package/dist/utility/serialization/scene/terrain.js +163 -33
  476. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  477. package/dist/utility/serialization/scene/text.js +11 -4
  478. package/dist/utility/serialization/scene/text.js.map +1 -1
  479. package/dist/utility/serialization/scene/water.js +1543 -264
  480. package/dist/utility/serialization/scene/water.js.map +1 -1
  481. package/dist/utility/serialization/types.js.map +1 -1
  482. package/dist/utility/shprojector.js +10 -22
  483. package/dist/utility/shprojector.js.map +1 -1
  484. package/dist/utility/textures/foam.js +170 -0
  485. package/dist/utility/textures/foam.js.map +1 -0
  486. package/dist/utility/textures/ggxlut.js +17 -43
  487. package/dist/utility/textures/ggxlut.js.map +1 -1
  488. package/dist/utility/textures/ltcdata.js +4 -4
  489. package/dist/utility/textures/ltcdata.js.map +1 -1
  490. package/dist/utility/textures/ltclut.js +16 -6
  491. package/dist/utility/textures/ltclut.js.map +1 -1
  492. package/dist/utility/unsupported.js +24 -0
  493. package/dist/utility/unsupported.js.map +1 -0
  494. package/dist/values.js +13 -1
  495. package/dist/values.js.map +1 -1
  496. package/package.json +25 -12
  497. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  498. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  499. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  500. package/src/asset/meshoptimizer/LICENSE +21 -0
  501. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  502. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -0,0 +1,265 @@
1
+ import { Vector3 } from '@zephyr3d/base';
2
+
3
+ /**
4
+ * Taps stored per profile in the kernel LUT, per side of the kernel centre.
5
+ *
6
+ * The full separable kernel is `2 * SSS_KERNEL_TAPS_PER_SIDE + 1` wide. Unreal's
7
+ * separable path uses 13 + 9 + 6 taps across its three kernels; this is the same
8
+ * order of magnitude, and the quality presets stride across it rather than
9
+ * baking a different table per preset.
10
+ */ const SSS_KERNEL_TAPS_PER_SIDE = 15;
11
+ /**
12
+ * Entries in a baked kernel row: the centre tap plus one side.
13
+ *
14
+ * Only half the kernel is stored because it is symmetric about its centre and
15
+ * the shader mirrors each tap as it walks outwards. The weights are normalized
16
+ * for the *full* mirrored kernel, so a consumer that does not mirror would come
17
+ * out half as bright.
18
+ */ const SSS_KERNEL_TAPS = SSS_KERNEL_TAPS_PER_SIDE + 1;
19
+ /**
20
+ * Entries in a baked transmission table.
21
+ *
22
+ * Unreal's own is 32 wide, which its capture shows holding a per-channel
23
+ * Beer-Lambert falloff sampled across thickness. Matching the width is not the
24
+ * point - it is simply enough resolution for a curve this smooth.
25
+ */ const SSS_TRANSMISSION_SAMPLES = 32;
26
+ /**
27
+ * Columns of the kernel LUT that precede the baked taps.
28
+ *
29
+ * One, holding `(diffusionWorldRadius, transmissionMaxThickness, 0, 0)` - the
30
+ * two scales the rest of the row is measured against. Named because the baker
31
+ * writes it and the shader reads it, and an off-by-one between them silently
32
+ * reads a weight as a radius.
33
+ */ const SSS_KERNEL_LUT_HEADER_COLUMNS = 1;
34
+ /**
35
+ * Christensen-Burley shaping parameter.
36
+ *
37
+ * The "diffusion" fit rather than the "searchlight" one, matching what Unreal
38
+ * uses: searchlight is the better match to ground truth for a pencil beam, but
39
+ * diffusion is what a screen-space pass actually approximates, and mixing the
40
+ * two is how a profile ends up looking right in isolation and wrong in a scene.
41
+ */ function burleyScaling(albedo) {
42
+ const a = Math.min(Math.max(albedo, 0), 1);
43
+ return 1.9 - a + 3.5 * (a - 0.8) * (a - 0.8);
44
+ }
45
+ /**
46
+ * Radially symmetric Burley reflectance profile, without the `1/r` Jacobian.
47
+ *
48
+ * `R(r) = (e^(-r/d) + e^(-r/(3d))) / (8*pi*d*r)`
49
+ *
50
+ * The `1/r` term converts the 1D profile into a 2D disc density. A separable
51
+ * screen-space blur integrates along a line rather than over a disc, so it is
52
+ * dropped and the weights are renormalized by their own sum instead - the same
53
+ * approximation `burleyDiffusionWeight` in `shaders/diffusion.ts` documents, and
54
+ * it has to be the same one or the two paths would disagree about what a profile
55
+ * means. The constant factor goes with it, since normalization removes it.
56
+ */ function burleyProfile(r, d) {
57
+ const safeD = Math.max(d, 1e-6);
58
+ const x = Math.abs(r) / safeD;
59
+ return (Math.exp(-Math.min(x, 40)) + Math.exp(-Math.min(x / 3, 40))) / safeD;
60
+ }
61
+ /**
62
+ * Inverse of the Burley CDF, `F(r) = 1 - e^(-r/d)/4 - 3*e^(-r/(3d))/4`.
63
+ *
64
+ * Solved by bisection rather than Newton: the derivative is well behaved but the
65
+ * CDF flattens hard in the tail, and a Newton step from a poor bracket there
66
+ * overshoots into negative radii. This runs once per profile change, so twenty
67
+ * bisection steps cost nothing worth optimizing.
68
+ */ function invertBurleyCdf(u, d) {
69
+ const target = Math.min(Math.max(u, 0), 0.999);
70
+ const cdf = (r)=>1 - 0.25 * Math.exp(-r / d) - 0.75 * Math.exp(-r / (3 * d));
71
+ let lo = 0;
72
+ // The profile has unbounded support; 24d carries >99.9% of the energy.
73
+ let hi = d * 24;
74
+ for(let i = 0; i < 40; i++){
75
+ const mid = (lo + hi) * 0.5;
76
+ if (cdf(mid) < target) {
77
+ lo = mid;
78
+ } else {
79
+ hi = mid;
80
+ }
81
+ }
82
+ return (lo + hi) * 0.5;
83
+ }
84
+ /**
85
+ * Pre-integrates a profile into the separable kernel the SSS blur passes sample.
86
+ *
87
+ * Why this runs on the CPU at all: the kernel is a function of the profile and
88
+ * nothing else, profiles change when someone drags a slider, and the alternative
89
+ * is two `exp` calls per tap per channel per pixel per pass. It is also how
90
+ * Unreal does it - the `SSProfiles` texture in a UE capture holds baked weights,
91
+ * not profile parameters - and matching that is the point of the exercise.
92
+ *
93
+ * Sample placement is importance-sampled against the profile's own CDF, so taps
94
+ * cluster where the energy is and thin out in the tail. A uniform placement
95
+ * spends most of its taps on the tail, which is both where the profile is
96
+ * flattest and where the depth-aware rejection is most likely to throw the tap
97
+ * away.
98
+ *
99
+ * @param profile - Profile to bake.
100
+ * @param tapsPerSide - Taps per side; the returned kernel has `n+1` entries.
101
+ * @returns Half the kernel: entry 0 is the centre, entries 1..n walk outwards
102
+ * with increasing positive offsets. Offsets are normalized against the widest
103
+ * channel radius, so the shader scales them by one screen-space radius and
104
+ * mirrors each one.
105
+ *
106
+ * @internal
107
+ */ function bakeSubsurfaceKernel(profile, tapsPerSide = SSS_KERNEL_TAPS_PER_SIDE) {
108
+ const albedo = profile.surfaceAlbedo;
109
+ const mfpColor = profile.meanFreePathColor;
110
+ const mfpDistance = Math.max(profile.meanFreePathDistance, 0);
111
+ // Per-channel shaping distance. Kept in millimetres throughout: the offsets
112
+ // come out normalized, so the only thing that matters here is the ratio
113
+ // between channels and the ratio of each to the widest.
114
+ const d = [
115
+ Math.max(mfpColor.x, 0) * mfpDistance / burleyScaling(albedo.x),
116
+ Math.max(mfpColor.y, 0) * mfpDistance / burleyScaling(albedo.y),
117
+ Math.max(mfpColor.z, 0) * mfpDistance / burleyScaling(albedo.z)
118
+ ];
119
+ const maxD = Math.max(d[0], d[1], d[2]);
120
+ const taps = [];
121
+ if (maxD <= 1e-6) {
122
+ // Degenerate profile: a single centre tap is an exact identity kernel, which
123
+ // is the right answer for "no scattering" and keeps the LUT well-formed.
124
+ taps.push({
125
+ offset: 0,
126
+ weight: [
127
+ 1,
128
+ 1,
129
+ 1
130
+ ]
131
+ });
132
+ for(let i = 0; i < tapsPerSide; i++){
133
+ taps.push({
134
+ offset: 0,
135
+ weight: [
136
+ 0,
137
+ 0,
138
+ 0
139
+ ]
140
+ });
141
+ }
142
+ return {
143
+ taps,
144
+ worldRadius: 0
145
+ };
146
+ }
147
+ // Importance-sample the widest channel: it is the one that sets the extent, so
148
+ // its CDF is what places taps where any channel still has energy. Sampling
149
+ // each channel's own CDF would need a different offset per channel, which a
150
+ // single texture fetch per tap cannot express.
151
+ const offsets = [
152
+ 0
153
+ ];
154
+ for(let i = 1; i <= tapsPerSide; i++){
155
+ // Stratified midpoints over the half-profile. The last stratum stops short
156
+ // of 1 because the CDF's inverse diverges there.
157
+ const u = (i - 0.5) / tapsPerSide;
158
+ offsets.push(invertBurleyCdf(u * 0.97, maxD));
159
+ }
160
+ const scale = 1 / offsets[offsets.length - 1];
161
+ const sum = [
162
+ 0,
163
+ 0,
164
+ 0
165
+ ];
166
+ const halfWeights = [];
167
+ for(let i = 0; i < offsets.length; i++){
168
+ // Each tap stands for the span between its neighbours' midpoints, so a
169
+ // sparse tail tap carries proportionally more energy than a dense centre
170
+ // one. Without this the tail is under-weighted by exactly the factor the
171
+ // importance sampling spread it by.
172
+ const prev = i > 0 ? offsets[i - 1] : -offsets[1];
173
+ const next = i < offsets.length - 1 ? offsets[i + 1] : offsets[i] + (offsets[i] - prev);
174
+ const span = (next - prev) * 0.5;
175
+ const w = [
176
+ burleyProfile(offsets[i], d[0]) * span,
177
+ burleyProfile(offsets[i], d[1]) * span,
178
+ burleyProfile(offsets[i], d[2]) * span
179
+ ];
180
+ halfWeights.push(w);
181
+ // The centre tap appears once, every other tap is mirrored.
182
+ const multiplicity = i === 0 ? 1 : 2;
183
+ sum[0] += w[0] * multiplicity;
184
+ sum[1] += w[1] * multiplicity;
185
+ sum[2] += w[2] * multiplicity;
186
+ }
187
+ const norm = [
188
+ sum[0] > 1e-12 ? 1 / sum[0] : 0,
189
+ sum[1] > 1e-12 ? 1 / sum[1] : 0,
190
+ sum[2] > 1e-12 ? 1 / sum[2] : 0
191
+ ];
192
+ for(let i = 0; i <= tapsPerSide; i++){
193
+ const w = halfWeights[i];
194
+ taps.push({
195
+ offset: offsets[i] * scale,
196
+ weight: [
197
+ w[0] * norm[0],
198
+ w[1] * norm[1],
199
+ w[2] * norm[2]
200
+ ]
201
+ });
202
+ }
203
+ // Offsets were normalized against the outermost tap, so that tap's position -
204
+ // in millimetres - is what ±1 stands for. Converting it here is what keeps the
205
+ // definition of "one radius" in one place.
206
+ return {
207
+ taps,
208
+ worldRadius: offsets[offsets.length - 1] * profile.worldUnitsPerMillimetre
209
+ };
210
+ }
211
+ const tmpExtinction = new Vector3();
212
+ /**
213
+ * Pre-integrates a profile's Beer-Lambert transmission falloff.
214
+ *
215
+ * `T_c(t) = exp(-sigma_c * t)`, where sigma comes from the profile's own mean
216
+ * free path. The channel spread is where the look comes from: for skin the red
217
+ * coefficient is several times smaller than blue's, so light that has crossed a
218
+ * finger or an earlobe arrives red no matter what colour it started as.
219
+ *
220
+ * Samples are spaced geometrically rather than uniformly. The curve is an
221
+ * exponential, so a uniform spacing would spend most of its entries on a tail
222
+ * that has already decayed to nothing while under-resolving the thin end - and
223
+ * the thin end is the only part that is bright enough to see.
224
+ *
225
+ * @param profile - Profile to bake.
226
+ * @param sampleCount - Entries in the returned table.
227
+ * @returns The table and the thickness its last entry stands for.
228
+ *
229
+ * @internal
230
+ */ function bakeTransmissionLUT(profile, sampleCount = SSS_TRANSMISSION_SAMPLES) {
231
+ const sigma = profile.getExtinctionCoefficient(tmpExtinction);
232
+ // Range out to where even the least-absorbed channel has gone dark. exp(-8) is
233
+ // about 3e-4, which is below anything an 8-bit display resolves, so carrying
234
+ // the table further would only add entries that are all zero.
235
+ const minSigma = Math.max(Math.min(sigma.x, sigma.y, sigma.z), 1e-6);
236
+ const maxThickness = 8 / minSigma;
237
+ const samples = [];
238
+ for(let i = 0; i < sampleCount; i++){
239
+ // Geometric from a small fraction of the range up to all of it, with the
240
+ // first entry pinned at zero thickness so the table starts at full
241
+ // transmission exactly rather than nearly.
242
+ const t = i === 0 ? 0 : maxThickness * Math.pow(SSS_TRANSMISSION_MIN_RATIO, 1 - (i - 1) / Math.max(sampleCount - 2, 1));
243
+ samples.push([
244
+ Math.exp(-Math.min(sigma.x * t, 80)),
245
+ Math.exp(-Math.min(sigma.y * t, 80)),
246
+ Math.exp(-Math.min(sigma.z * t, 80))
247
+ ]);
248
+ }
249
+ return {
250
+ samples,
251
+ maxThickness
252
+ };
253
+ }
254
+ /**
255
+ * Ratio of the thinnest non-zero entry in the transmission table to the thickest.
256
+ *
257
+ * Exported because the shader has to invert the baker's spacing to look the
258
+ * table up, and the two are one mapping written twice: a reader that assumed
259
+ * uniform spacing would find the right table at the wrong index.
260
+ *
261
+ * @internal
262
+ */ const SSS_TRANSMISSION_MIN_RATIO = 1 / 512;
263
+
264
+ export { SSS_KERNEL_LUT_HEADER_COLUMNS, SSS_KERNEL_TAPS, SSS_KERNEL_TAPS_PER_SIDE, SSS_TRANSMISSION_MIN_RATIO, SSS_TRANSMISSION_SAMPLES, bakeSubsurfaceKernel, bakeTransmissionLUT };
265
+ //# sourceMappingURL=sss_kernel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sss_kernel.js","sources":["../../src/material/sss_kernel.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\nimport type { SubsurfaceProfile } from './subsurfaceprofile';\n\n/**\n * Taps stored per profile in the kernel LUT, per side of the kernel centre.\n *\n * The full separable kernel is `2 * SSS_KERNEL_TAPS_PER_SIDE + 1` wide. Unreal's\n * separable path uses 13 + 9 + 6 taps across its three kernels; this is the same\n * order of magnitude, and the quality presets stride across it rather than\n * baking a different table per preset.\n */\nexport const SSS_KERNEL_TAPS_PER_SIDE = 15;\n\n/**\n * Entries in a baked kernel row: the centre tap plus one side.\n *\n * Only half the kernel is stored because it is symmetric about its centre and\n * the shader mirrors each tap as it walks outwards. The weights are normalized\n * for the *full* mirrored kernel, so a consumer that does not mirror would come\n * out half as bright.\n */\nexport const SSS_KERNEL_TAPS = SSS_KERNEL_TAPS_PER_SIDE + 1;\n\n/** One pre-integrated tap: where to sample, and how much of each channel to take. */\nexport interface SubsurfaceKernelTap {\n /** Offset from the kernel centre, normalized so 1 is the profile's widest channel radius. */\n offset: number;\n /** Per-channel weight, normalized so the full mirrored kernel sums to one per channel. */\n weight: [number, number, number];\n}\n\n/** A baked kernel and the world-space distance its normalized offsets are measured against. */\nexport interface SubsurfaceKernel {\n taps: SubsurfaceKernelTap[];\n /**\n * World-space distance corresponding to a normalized offset of 1 - the radius\n * the blur pass projects into screen space. Returned alongside the taps rather\n * than recomputed by the caller so the two cannot disagree about what ±1 means.\n */\n worldRadius: number;\n}\n\n/**\n * Entries in a baked transmission table.\n *\n * Unreal's own is 32 wide, which its capture shows holding a per-channel\n * Beer-Lambert falloff sampled across thickness. Matching the width is not the\n * point - it is simply enough resolution for a curve this smooth.\n */\nexport const SSS_TRANSMISSION_SAMPLES = 32;\n\n/**\n * Columns of the kernel LUT that precede the baked taps.\n *\n * One, holding `(diffusionWorldRadius, transmissionMaxThickness, 0, 0)` - the\n * two scales the rest of the row is measured against. Named because the baker\n * writes it and the shader reads it, and an off-by-one between them silently\n * reads a weight as a radius.\n */\nexport const SSS_KERNEL_LUT_HEADER_COLUMNS = 1;\n\n/** A baked transmission table and the thickness range it spans. */\nexport interface SubsurfaceTransmission {\n /** `exp(-sigma * t)` per channel, from `t = 0` out to `maxThickness`. */\n samples: Array<[number, number, number]>;\n /**\n * Thickness, in world units, at which the table ends. The shader normalizes\n * its measured thickness against this before looking up, so it is what the\n * last entry means.\n */\n maxThickness: number;\n}\n\n/**\n * Christensen-Burley shaping parameter.\n *\n * The \"diffusion\" fit rather than the \"searchlight\" one, matching what Unreal\n * uses: searchlight is the better match to ground truth for a pencil beam, but\n * diffusion is what a screen-space pass actually approximates, and mixing the\n * two is how a profile ends up looking right in isolation and wrong in a scene.\n */\nfunction burleyScaling(albedo: number): number {\n const a = Math.min(Math.max(albedo, 0), 1);\n return 1.9 - a + 3.5 * (a - 0.8) * (a - 0.8);\n}\n\n/**\n * Radially symmetric Burley reflectance profile, without the `1/r` Jacobian.\n *\n * `R(r) = (e^(-r/d) + e^(-r/(3d))) / (8*pi*d*r)`\n *\n * The `1/r` term converts the 1D profile into a 2D disc density. A separable\n * screen-space blur integrates along a line rather than over a disc, so it is\n * dropped and the weights are renormalized by their own sum instead - the same\n * approximation `burleyDiffusionWeight` in `shaders/diffusion.ts` documents, and\n * it has to be the same one or the two paths would disagree about what a profile\n * means. The constant factor goes with it, since normalization removes it.\n */\nfunction burleyProfile(r: number, d: number): number {\n const safeD = Math.max(d, 1e-6);\n const x = Math.abs(r) / safeD;\n return (Math.exp(-Math.min(x, 40)) + Math.exp(-Math.min(x / 3, 40))) / safeD;\n}\n\n/**\n * Inverse of the Burley CDF, `F(r) = 1 - e^(-r/d)/4 - 3*e^(-r/(3d))/4`.\n *\n * Solved by bisection rather than Newton: the derivative is well behaved but the\n * CDF flattens hard in the tail, and a Newton step from a poor bracket there\n * overshoots into negative radii. This runs once per profile change, so twenty\n * bisection steps cost nothing worth optimizing.\n */\nfunction invertBurleyCdf(u: number, d: number): number {\n const target = Math.min(Math.max(u, 0), 0.999);\n const cdf = (r: number) => 1 - 0.25 * Math.exp(-r / d) - 0.75 * Math.exp(-r / (3 * d));\n let lo = 0;\n // The profile has unbounded support; 24d carries >99.9% of the energy.\n let hi = d * 24;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) * 0.5;\n if (cdf(mid) < target) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n return (lo + hi) * 0.5;\n}\n\n/**\n * Pre-integrates a profile into the separable kernel the SSS blur passes sample.\n *\n * Why this runs on the CPU at all: the kernel is a function of the profile and\n * nothing else, profiles change when someone drags a slider, and the alternative\n * is two `exp` calls per tap per channel per pixel per pass. It is also how\n * Unreal does it - the `SSProfiles` texture in a UE capture holds baked weights,\n * not profile parameters - and matching that is the point of the exercise.\n *\n * Sample placement is importance-sampled against the profile's own CDF, so taps\n * cluster where the energy is and thin out in the tail. A uniform placement\n * spends most of its taps on the tail, which is both where the profile is\n * flattest and where the depth-aware rejection is most likely to throw the tap\n * away.\n *\n * @param profile - Profile to bake.\n * @param tapsPerSide - Taps per side; the returned kernel has `n+1` entries.\n * @returns Half the kernel: entry 0 is the centre, entries 1..n walk outwards\n * with increasing positive offsets. Offsets are normalized against the widest\n * channel radius, so the shader scales them by one screen-space radius and\n * mirrors each one.\n *\n * @internal\n */\nexport function bakeSubsurfaceKernel(\n profile: SubsurfaceProfile,\n tapsPerSide = SSS_KERNEL_TAPS_PER_SIDE\n): SubsurfaceKernel {\n const albedo = profile.surfaceAlbedo;\n const mfpColor = profile.meanFreePathColor;\n const mfpDistance = Math.max(profile.meanFreePathDistance, 0);\n\n // Per-channel shaping distance. Kept in millimetres throughout: the offsets\n // come out normalized, so the only thing that matters here is the ratio\n // between channels and the ratio of each to the widest.\n const d: [number, number, number] = [\n (Math.max(mfpColor.x, 0) * mfpDistance) / burleyScaling(albedo.x),\n (Math.max(mfpColor.y, 0) * mfpDistance) / burleyScaling(albedo.y),\n (Math.max(mfpColor.z, 0) * mfpDistance) / burleyScaling(albedo.z)\n ];\n const maxD = Math.max(d[0], d[1], d[2]);\n const taps: SubsurfaceKernelTap[] = [];\n\n if (maxD <= 1e-6) {\n // Degenerate profile: a single centre tap is an exact identity kernel, which\n // is the right answer for \"no scattering\" and keeps the LUT well-formed.\n taps.push({ offset: 0, weight: [1, 1, 1] });\n for (let i = 0; i < tapsPerSide; i++) {\n taps.push({ offset: 0, weight: [0, 0, 0] });\n }\n return { taps, worldRadius: 0 };\n }\n\n // Importance-sample the widest channel: it is the one that sets the extent, so\n // its CDF is what places taps where any channel still has energy. Sampling\n // each channel's own CDF would need a different offset per channel, which a\n // single texture fetch per tap cannot express.\n const offsets: number[] = [0];\n for (let i = 1; i <= tapsPerSide; i++) {\n // Stratified midpoints over the half-profile. The last stratum stops short\n // of 1 because the CDF's inverse diverges there.\n const u = (i - 0.5) / tapsPerSide;\n offsets.push(invertBurleyCdf(u * 0.97, maxD));\n }\n\n const scale = 1 / offsets[offsets.length - 1];\n const sum: [number, number, number] = [0, 0, 0];\n const halfWeights: Array<[number, number, number]> = [];\n\n for (let i = 0; i < offsets.length; i++) {\n // Each tap stands for the span between its neighbours' midpoints, so a\n // sparse tail tap carries proportionally more energy than a dense centre\n // one. Without this the tail is under-weighted by exactly the factor the\n // importance sampling spread it by.\n const prev = i > 0 ? offsets[i - 1] : -offsets[1];\n const next = i < offsets.length - 1 ? offsets[i + 1] : offsets[i] + (offsets[i] - prev);\n const span = (next - prev) * 0.5;\n const w: [number, number, number] = [\n burleyProfile(offsets[i], d[0]) * span,\n burleyProfile(offsets[i], d[1]) * span,\n burleyProfile(offsets[i], d[2]) * span\n ];\n halfWeights.push(w);\n // The centre tap appears once, every other tap is mirrored.\n const multiplicity = i === 0 ? 1 : 2;\n sum[0] += w[0] * multiplicity;\n sum[1] += w[1] * multiplicity;\n sum[2] += w[2] * multiplicity;\n }\n\n const norm: [number, number, number] = [\n sum[0] > 1e-12 ? 1 / sum[0] : 0,\n sum[1] > 1e-12 ? 1 / sum[1] : 0,\n sum[2] > 1e-12 ? 1 / sum[2] : 0\n ];\n\n for (let i = 0; i <= tapsPerSide; i++) {\n const w = halfWeights[i];\n taps.push({\n offset: offsets[i] * scale,\n weight: [w[0] * norm[0], w[1] * norm[1], w[2] * norm[2]]\n });\n }\n\n // Offsets were normalized against the outermost tap, so that tap's position -\n // in millimetres - is what ±1 stands for. Converting it here is what keeps the\n // definition of \"one radius\" in one place.\n return { taps, worldRadius: offsets[offsets.length - 1] * profile.worldUnitsPerMillimetre };\n}\n\nconst tmpExtinction = new Vector3();\n\n/**\n * Pre-integrates a profile's Beer-Lambert transmission falloff.\n *\n * `T_c(t) = exp(-sigma_c * t)`, where sigma comes from the profile's own mean\n * free path. The channel spread is where the look comes from: for skin the red\n * coefficient is several times smaller than blue's, so light that has crossed a\n * finger or an earlobe arrives red no matter what colour it started as.\n *\n * Samples are spaced geometrically rather than uniformly. The curve is an\n * exponential, so a uniform spacing would spend most of its entries on a tail\n * that has already decayed to nothing while under-resolving the thin end - and\n * the thin end is the only part that is bright enough to see.\n *\n * @param profile - Profile to bake.\n * @param sampleCount - Entries in the returned table.\n * @returns The table and the thickness its last entry stands for.\n *\n * @internal\n */\nexport function bakeTransmissionLUT(\n profile: SubsurfaceProfile,\n sampleCount = SSS_TRANSMISSION_SAMPLES\n): SubsurfaceTransmission {\n const sigma = profile.getExtinctionCoefficient(tmpExtinction);\n // Range out to where even the least-absorbed channel has gone dark. exp(-8) is\n // about 3e-4, which is below anything an 8-bit display resolves, so carrying\n // the table further would only add entries that are all zero.\n const minSigma = Math.max(Math.min(sigma.x, sigma.y, sigma.z), 1e-6);\n const maxThickness = 8 / minSigma;\n const samples: Array<[number, number, number]> = [];\n\n for (let i = 0; i < sampleCount; i++) {\n // Geometric from a small fraction of the range up to all of it, with the\n // first entry pinned at zero thickness so the table starts at full\n // transmission exactly rather than nearly.\n const t =\n i === 0\n ? 0\n : maxThickness * Math.pow(SSS_TRANSMISSION_MIN_RATIO, 1 - (i - 1) / Math.max(sampleCount - 2, 1));\n samples.push([\n Math.exp(-Math.min(sigma.x * t, 80)),\n Math.exp(-Math.min(sigma.y * t, 80)),\n Math.exp(-Math.min(sigma.z * t, 80))\n ]);\n }\n\n return { samples, maxThickness };\n}\n\n/**\n * Ratio of the thinnest non-zero entry in the transmission table to the thickest.\n *\n * Exported because the shader has to invert the baker's spacing to look the\n * table up, and the two are one mapping written twice: a reader that assumed\n * uniform spacing would find the right table at the wrong index.\n *\n * @internal\n */\nexport const SSS_TRANSMISSION_MIN_RATIO = 1 / 512;\n"],"names":["SSS_KERNEL_TAPS_PER_SIDE","SSS_KERNEL_TAPS","SSS_TRANSMISSION_SAMPLES","SSS_KERNEL_LUT_HEADER_COLUMNS","burleyScaling","albedo","a","Math","min","max","burleyProfile","r","d","safeD","x","abs","exp","invertBurleyCdf","u","target","cdf","lo","hi","i","mid","bakeSubsurfaceKernel","profile","tapsPerSide","surfaceAlbedo","mfpColor","meanFreePathColor","mfpDistance","meanFreePathDistance","y","z","maxD","taps","push","offset","weight","worldRadius","offsets","scale","length","sum","halfWeights","prev","next","span","w","multiplicity","norm","worldUnitsPerMillimetre","tmpExtinction","Vector3","bakeTransmissionLUT","sampleCount","sigma","getExtinctionCoefficient","minSigma","maxThickness","samples","t","pow","SSS_TRANSMISSION_MIN_RATIO"],"mappings":";;AAGA;;;;;;;IAQaA,MAAAA,wBAAAA,GAA2B;AAExC;;;;;;;AAOC,IACM,MAAMC,eAAkBD,GAAAA,wBAAAA,GAA2B;AAqB1D;;;;;;IAOaE,MAAAA,wBAAAA,GAA2B;AAExC;;;;;;;IAQaC,MAAAA,6BAAAA,GAAgC;AAc7C;;;;;;;IAQA,SAASC,cAAcC,MAAc,EAAA;IACnC,MAAMC,CAAAA,GAAIC,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAACJ,QAAQ,CAAI,CAAA,EAAA,CAAA,CAAA;IACxC,OAAO,GAAA,GAAMC,IAAI,GAAOA,IAAAA,IAAI,GAAE,CAAA,IAAMA,CAAAA,GAAI,GAAE,CAAA;AAC5C;AAEA;;;;;;;;;;;AAWC,IACD,SAASI,aAAAA,CAAcC,CAAS,EAAEC,CAAS,EAAA;AACzC,IAAA,MAAMC,KAAQN,GAAAA,IAAAA,CAAKE,GAAG,CAACG,CAAG,EAAA,IAAA,CAAA;AAC1B,IAAA,MAAME,CAAIP,GAAAA,IAAAA,CAAKQ,GAAG,CAACJ,CAAKE,CAAAA,GAAAA,KAAAA;IACxB,OAAQN,CAAAA,IAAKS,CAAAA,GAAG,CAAC,CAACT,IAAAA,CAAKC,GAAG,CAACM,CAAAA,EAAG,OAAOP,IAAKS,CAAAA,GAAG,CAAC,CAACT,IAAAA,CAAKC,GAAG,CAACM,CAAAA,GAAI,CAAG,EAAA,EAAA,CAAA,CAAG,IAAKD,KAAAA;AACzE;AAEA;;;;;;;AAOC,IACD,SAASI,eAAAA,CAAgBC,CAAS,EAAEN,CAAS,EAAA;IAC3C,MAAMO,MAAAA,GAASZ,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAACS,GAAG,CAAI,CAAA,EAAA,KAAA,CAAA;AACxC,IAAA,MAAME,MAAM,CAACT,CAAAA,GAAc,IAAI,IAAOJ,GAAAA,IAAAA,CAAKS,GAAG,CAAC,CAACL,IAAIC,CAAK,CAAA,GAAA,IAAA,GAAOL,KAAKS,GAAG,CAAC,CAACL,CAAK,IAAA,IAAIC,CAAAA,CAAAA,CAAAA;AACnF,IAAA,IAAIS,EAAK,GAAA,CAAA;;AAET,IAAA,IAAIC,KAAKV,CAAI,GAAA,EAAA;AACb,IAAA,IAAK,IAAIW,CAAAA,GAAI,CAAGA,EAAAA,CAAAA,GAAI,IAAIA,CAAK,EAAA,CAAA;AAC3B,QAAA,MAAMC,GAAM,GAACH,CAAAA,EAAAA,GAAKC,EAAC,IAAK,GAAA;QACxB,IAAIF,GAAAA,CAAII,OAAOL,MAAQ,EAAA;YACrBE,EAAKG,GAAAA,GAAAA;SACA,MAAA;YACLF,EAAKE,GAAAA,GAAAA;AACP;AACF;AACA,IAAA,OAAO,CAACH,EAAKC,GAAAA,EAAC,IAAK,GAAA;AACrB;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBC,IACM,SAASG,oBAAAA,CACdC,OAA0B,EAC1BC,cAAc3B,wBAAwB,EAAA;IAEtC,MAAMK,MAAAA,GAASqB,QAAQE,aAAa;IACpC,MAAMC,QAAAA,GAAWH,QAAQI,iBAAiB;AAC1C,IAAA,MAAMC,cAAcxB,IAAKE,CAAAA,GAAG,CAACiB,OAAAA,CAAQM,oBAAoB,EAAE,CAAA,CAAA;;;;AAK3D,IAAA,MAAMpB,CAA8B,GAAA;QACjCL,IAAKE,CAAAA,GAAG,CAACoB,QAASf,CAAAA,CAAC,EAAE,CAAKiB,CAAAA,GAAAA,WAAAA,GAAe3B,aAAcC,CAAAA,MAAAA,CAAOS,CAAC,CAAA;QAC/DP,IAAKE,CAAAA,GAAG,CAACoB,QAASI,CAAAA,CAAC,EAAE,CAAKF,CAAAA,GAAAA,WAAAA,GAAe3B,aAAcC,CAAAA,MAAAA,CAAO4B,CAAC,CAAA;QAC/D1B,IAAKE,CAAAA,GAAG,CAACoB,QAASK,CAAAA,CAAC,EAAE,CAAKH,CAAAA,GAAAA,WAAAA,GAAe3B,aAAcC,CAAAA,MAAAA,CAAO6B,CAAC;AACjE,KAAA;AACD,IAAA,MAAMC,IAAO5B,GAAAA,IAAAA,CAAKE,GAAG,CAACG,CAAC,CAAC,CAAA,CAAE,EAAEA,CAAC,CAAC,CAAA,CAAE,EAAEA,CAAC,CAAC,CAAE,CAAA,CAAA;AACtC,IAAA,MAAMwB,OAA8B,EAAE;AAEtC,IAAA,IAAID,QAAQ,IAAM,EAAA;;;AAGhBC,QAAAA,IAAAA,CAAKC,IAAI,CAAC;YAAEC,MAAQ,EAAA,CAAA;YAAGC,MAAQ,EAAA;AAAC,gBAAA,CAAA;AAAG,gBAAA,CAAA;AAAG,gBAAA;AAAE;AAAC,SAAA,CAAA;AACzC,QAAA,IAAK,IAAIhB,CAAAA,GAAI,CAAGA,EAAAA,CAAAA,GAAII,aAAaJ,CAAK,EAAA,CAAA;AACpCa,YAAAA,IAAAA,CAAKC,IAAI,CAAC;gBAAEC,MAAQ,EAAA,CAAA;gBAAGC,MAAQ,EAAA;AAAC,oBAAA,CAAA;AAAG,oBAAA,CAAA;AAAG,oBAAA;AAAE;AAAC,aAAA,CAAA;AAC3C;QACA,OAAO;AAAEH,YAAAA,IAAAA;YAAMI,WAAa,EAAA;AAAE,SAAA;AAChC;;;;;AAMA,IAAA,MAAMC,OAAoB,GAAA;AAAC,QAAA;AAAE,KAAA;AAC7B,IAAA,IAAK,IAAIlB,CAAAA,GAAI,CAAGA,EAAAA,CAAAA,IAAKI,aAAaJ,CAAK,EAAA,CAAA;;;AAGrC,QAAA,MAAML,CAAI,GAACK,CAAAA,CAAAA,GAAI,GAAE,IAAKI,WAAAA;AACtBc,QAAAA,OAAAA,CAAQJ,IAAI,CAACpB,eAAgBC,CAAAA,CAAAA,GAAI,IAAMiB,EAAAA,IAAAA,CAAAA,CAAAA;AACzC;AAEA,IAAA,MAAMO,QAAQ,CAAID,GAAAA,OAAO,CAACA,OAAQE,CAAAA,MAAM,GAAG,CAAE,CAAA;AAC7C,IAAA,MAAMC,GAAgC,GAAA;AAAC,QAAA,CAAA;AAAG,QAAA,CAAA;AAAG,QAAA;AAAE,KAAA;AAC/C,IAAA,MAAMC,cAA+C,EAAE;AAEvD,IAAA,IAAK,IAAItB,CAAI,GAAA,CAAA,EAAGA,IAAIkB,OAAQE,CAAAA,MAAM,EAAEpB,CAAK,EAAA,CAAA;;;;;QAKvC,MAAMuB,IAAAA,GAAOvB,CAAI,GAAA,CAAA,GAAIkB,OAAO,CAAClB,CAAI,GAAA,CAAA,CAAE,GAAG,CAACkB,OAAO,CAAC,CAAE,CAAA;QACjD,MAAMM,IAAAA,GAAOxB,IAAIkB,OAAQE,CAAAA,MAAM,GAAG,CAAIF,GAAAA,OAAO,CAAClB,CAAI,GAAA,CAAA,CAAE,GAAGkB,OAAO,CAAClB,EAAE,IAAIkB,OAAO,CAAClB,CAAAA,CAAE,GAAGuB,IAAG,CAAA;AACrF,QAAA,MAAME,IAAO,GAACD,CAAAA,IAAAA,GAAOD,IAAG,IAAK,GAAA;AAC7B,QAAA,MAAMG,CAA8B,GAAA;AAClCvC,YAAAA,aAAAA,CAAc+B,OAAO,CAAClB,CAAAA,CAAE,EAAEX,CAAC,CAAC,EAAE,CAAIoC,GAAAA,IAAAA;AAClCtC,YAAAA,aAAAA,CAAc+B,OAAO,CAAClB,CAAAA,CAAE,EAAEX,CAAC,CAAC,EAAE,CAAIoC,GAAAA,IAAAA;AAClCtC,YAAAA,aAAAA,CAAc+B,OAAO,CAAClB,CAAAA,CAAE,EAAEX,CAAC,CAAC,EAAE,CAAIoC,GAAAA;AACnC,SAAA;AACDH,QAAAA,WAAAA,CAAYR,IAAI,CAACY,CAAAA,CAAAA;;QAEjB,MAAMC,YAAAA,GAAe3B,CAAM,KAAA,CAAA,GAAI,CAAI,GAAA,CAAA;AACnCqB,QAAAA,GAAG,CAAC,CAAE,CAAA,IAAIK,CAAC,CAAC,EAAE,GAAGC,YAAAA;AACjBN,QAAAA,GAAG,CAAC,CAAE,CAAA,IAAIK,CAAC,CAAC,EAAE,GAAGC,YAAAA;AACjBN,QAAAA,GAAG,CAAC,CAAE,CAAA,IAAIK,CAAC,CAAC,EAAE,GAAGC,YAAAA;AACnB;AAEA,IAAA,MAAMC,IAAiC,GAAA;QACrCP,GAAG,CAAC,EAAE,GAAG,KAAA,GAAQ,IAAIA,GAAG,CAAC,EAAE,GAAG,CAAA;QAC9BA,GAAG,CAAC,EAAE,GAAG,KAAA,GAAQ,IAAIA,GAAG,CAAC,EAAE,GAAG,CAAA;QAC9BA,GAAG,CAAC,EAAE,GAAG,KAAA,GAAQ,IAAIA,GAAG,CAAC,EAAE,GAAG;AAC/B,KAAA;AAED,IAAA,IAAK,IAAIrB,CAAAA,GAAI,CAAGA,EAAAA,CAAAA,IAAKI,aAAaJ,CAAK,EAAA,CAAA;QACrC,MAAM0B,CAAAA,GAAIJ,WAAW,CAACtB,CAAE,CAAA;AACxBa,QAAAA,IAAAA,CAAKC,IAAI,CAAC;YACRC,MAAQG,EAAAA,OAAO,CAAClB,CAAAA,CAAE,GAAGmB,KAAAA;YACrBH,MAAQ,EAAA;AAACU,gBAAAA,CAAC,CAAC,CAAA,CAAE,GAAGE,IAAI,CAAC,CAAE,CAAA;AAAEF,gBAAAA,CAAC,CAAC,CAAA,CAAE,GAAGE,IAAI,CAAC,CAAE,CAAA;AAAEF,gBAAAA,CAAC,CAAC,CAAA,CAAE,GAAGE,IAAI,CAAC,CAAE;AAAC;AAC1D,SAAA,CAAA;AACF;;;;IAKA,OAAO;AAAEf,QAAAA,IAAAA;QAAMI,WAAaC,EAAAA,OAAO,CAACA,OAAQE,CAAAA,MAAM,GAAG,CAAE,CAAA,GAAGjB,QAAQ0B;AAAwB,KAAA;AAC5F;AAEA,MAAMC,gBAAgB,IAAIC,OAAAA,EAAAA;AAE1B;;;;;;;;;;;;;;;;;;AAkBC,IACM,SAASC,mBAAAA,CACd7B,OAA0B,EAC1B8B,cAActD,wBAAwB,EAAA;IAEtC,MAAMuD,KAAAA,GAAQ/B,OAAQgC,CAAAA,wBAAwB,CAACL,aAAAA,CAAAA;;;;AAI/C,IAAA,MAAMM,QAAWpD,GAAAA,IAAAA,CAAKE,GAAG,CAACF,KAAKC,GAAG,CAACiD,KAAM3C,CAAAA,CAAC,EAAE2C,KAAMxB,CAAAA,CAAC,EAAEwB,KAAAA,CAAMvB,CAAC,CAAG,EAAA,IAAA,CAAA;AAC/D,IAAA,MAAM0B,eAAe,CAAID,GAAAA,QAAAA;AACzB,IAAA,MAAME,UAA2C,EAAE;AAEnD,IAAA,IAAK,IAAItC,CAAAA,GAAI,CAAGA,EAAAA,CAAAA,GAAIiC,aAAajC,CAAK,EAAA,CAAA;;;;AAIpC,QAAA,MAAMuC,IACJvC,CAAM,KAAA,CAAA,GACF,IACAqC,YAAerD,GAAAA,IAAAA,CAAKwD,GAAG,CAACC,0BAAAA,EAA4B,IAAI,CAACzC,IAAI,CAAA,IAAKhB,KAAKE,GAAG,CAAC+C,cAAc,CAAG,EAAA,CAAA,CAAA,CAAA;AAClGK,QAAAA,OAAAA,CAAQxB,IAAI,CAAC;YACX9B,IAAKS,CAAAA,GAAG,CAAC,CAACT,IAAAA,CAAKC,GAAG,CAACiD,KAAAA,CAAM3C,CAAC,GAAGgD,CAAG,EAAA,EAAA,CAAA,CAAA;YAChCvD,IAAKS,CAAAA,GAAG,CAAC,CAACT,IAAAA,CAAKC,GAAG,CAACiD,KAAAA,CAAMxB,CAAC,GAAG6B,CAAG,EAAA,EAAA,CAAA,CAAA;YAChCvD,IAAKS,CAAAA,GAAG,CAAC,CAACT,IAAAA,CAAKC,GAAG,CAACiD,KAAAA,CAAMvB,CAAC,GAAG4B,CAAG,EAAA,EAAA,CAAA;AACjC,SAAA,CAAA;AACH;IAEA,OAAO;AAAED,QAAAA,OAAAA;AAASD,QAAAA;AAAa,KAAA;AACjC;AAEA;;;;;;;;AAQC,IACM,MAAMI,0BAA6B,GAAA,CAAA,GAAI;;;;"}