@zephyr3d/scene 0.9.26 → 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 (506) 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 +146 -30
  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 +300 -56
  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 +177 -3
  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 +178 -200
  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 +30475 -19865
  109. package/dist/index.js +67 -12
  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/hairstrand.js +235 -235
  118. package/dist/material/hairstrand.js.map +1 -1
  119. package/dist/material/lambert.js +4 -1
  120. package/dist/material/lambert.js.map +1 -1
  121. package/dist/material/material.js +362 -300
  122. package/dist/material/material.js.map +1 -1
  123. package/dist/material/meshmaterial.js +118 -45
  124. package/dist/material/meshmaterial.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  126. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  128. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  130. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  132. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  133. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  134. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  135. package/dist/material/mixins/lit.js +223 -83
  136. package/dist/material/mixins/lit.js.map +1 -1
  137. package/dist/material/mixins/pbr/common.js +31 -206
  138. package/dist/material/mixins/pbr/common.js.map +1 -1
  139. package/dist/material/mtoon.js +1 -1
  140. package/dist/material/mtoon.js.map +1 -1
  141. package/dist/material/pbrmr.js +3 -0
  142. package/dist/material/pbrmr.js.map +1 -1
  143. package/dist/material/pbrsg.js +3 -0
  144. package/dist/material/pbrsg.js.map +1 -1
  145. package/dist/material/sdf_debug.js +78 -0
  146. package/dist/material/sdf_debug.js.map +1 -0
  147. package/dist/material/shader/helper.js +733 -190
  148. package/dist/material/shader/helper.js.map +1 -1
  149. package/dist/material/shader/terrain_blend.js +204 -43
  150. package/dist/material/shader/terrain_blend.js.map +1 -1
  151. package/dist/material/skin.js +331 -297
  152. package/dist/material/skin.js.map +1 -1
  153. package/dist/material/skinprofile.js +1058 -0
  154. package/dist/material/skinprofile.js.map +1 -0
  155. package/dist/material/sss.js +353 -0
  156. package/dist/material/sss.js.map +1 -0
  157. package/dist/material/sss_kernel.js +265 -0
  158. package/dist/material/sss_kernel.js.map +1 -0
  159. package/dist/material/sssprofile.js +879 -0
  160. package/dist/material/sssprofile.js.map +1 -0
  161. package/dist/material/subsurfaceprofile.js +4 -8
  162. package/dist/material/subsurfaceprofile.js.map +1 -1
  163. package/dist/material/terrain-cm.js +464 -188
  164. package/dist/material/terrain-cm.js.map +1 -1
  165. package/dist/material/unlit.js +3 -0
  166. package/dist/material/unlit.js.map +1 -1
  167. package/dist/material/water.js +2009 -201
  168. package/dist/material/water.js.map +1 -1
  169. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  172. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  173. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  174. package/dist/physics/character.js +226 -0
  175. package/dist/physics/character.js.map +1 -0
  176. package/dist/physics/collider.js +209 -0
  177. package/dist/physics/collider.js.map +1 -0
  178. package/dist/physics/events.js +79 -0
  179. package/dist/physics/events.js.map +1 -0
  180. package/dist/physics/joint.js +272 -0
  181. package/dist/physics/joint.js.map +1 -0
  182. package/dist/physics/node_physics.js +234 -0
  183. package/dist/physics/node_physics.js.map +1 -0
  184. package/dist/physics/part.js +91 -0
  185. package/dist/physics/part.js.map +1 -0
  186. package/dist/physics/rigid_body.js +379 -0
  187. package/dist/physics/rigid_body.js.map +1 -0
  188. package/dist/physics/vehicle.js +335 -0
  189. package/dist/physics/vehicle.js.map +1 -0
  190. package/dist/physics/world.js +25 -0
  191. package/dist/physics/world.js.map +1 -0
  192. package/dist/posteffect/bloom.js +49 -14
  193. package/dist/posteffect/bloom.js.map +1 -1
  194. package/dist/posteffect/motionblur.js +668 -63
  195. package/dist/posteffect/motionblur.js.map +1 -1
  196. package/dist/posteffect/posteffect.js +12 -1
  197. package/dist/posteffect/posteffect.js.map +1 -1
  198. package/dist/posteffect/postsss.js +572 -0
  199. package/dist/posteffect/postsss.js.map +1 -0
  200. package/dist/posteffect/sao.js +48 -50
  201. package/dist/posteffect/sao.js.map +1 -1
  202. package/dist/posteffect/skinsss.js +605 -355
  203. package/dist/posteffect/skinsss.js.map +1 -1
  204. package/dist/posteffect/ssgi.js +91 -162
  205. package/dist/posteffect/ssgi.js.map +1 -1
  206. package/dist/posteffect/ssr.js +3 -11
  207. package/dist/posteffect/ssr.js.map +1 -1
  208. package/dist/posteffect/sss.js +34 -15
  209. package/dist/posteffect/sss.js.map +1 -1
  210. package/dist/posteffect/taa.js +1 -0
  211. package/dist/posteffect/taa.js.map +1 -1
  212. package/dist/render/abuffer_oit.js +40 -39
  213. package/dist/render/abuffer_oit.js.map +1 -1
  214. package/dist/render/clipmap.js +328 -62
  215. package/dist/render/clipmap.js.map +1 -1
  216. package/dist/render/cluster_light.js +958 -224
  217. package/dist/render/cluster_light.js.map +1 -1
  218. package/dist/render/cull_visitor.js +26 -5
  219. package/dist/render/cull_visitor.js.map +1 -1
  220. package/dist/render/debug_views.js +37 -0
  221. package/dist/render/debug_views.js.map +1 -0
  222. package/dist/render/depthpass.js +5 -1
  223. package/dist/render/depthpass.js.map +1 -1
  224. package/dist/render/drawable_mixin.js +53 -6
  225. package/dist/render/drawable_mixin.js.map +1 -1
  226. package/dist/render/dualdepthpeeling_oit.js +53 -53
  227. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  228. package/dist/render/envlight.js +196 -113
  229. package/dist/render/envlight.js.map +1 -1
  230. package/dist/render/fbm_wavegenerator.js +8 -13
  231. package/dist/render/fbm_wavegenerator.js.map +1 -1
  232. package/dist/render/fft_wavegenerator.js +268 -136
  233. package/dist/render/fft_wavegenerator.js.map +1 -1
  234. package/dist/render/gerstner_wavegenerator.js +113 -28
  235. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  236. package/dist/render/gi/probe_volume.js +1334 -0
  237. package/dist/render/gi/probe_volume.js.map +1 -0
  238. package/dist/render/gi/scene_gi.js +282 -0
  239. package/dist/render/gi/scene_gi.js.map +1 -0
  240. package/dist/render/gi/voxel_atlas.js +198 -0
  241. package/dist/render/gi/voxel_atlas.js.map +1 -0
  242. package/dist/render/gi/voxel_lighting.js +652 -0
  243. package/dist/render/gi/voxel_lighting.js.map +1 -0
  244. package/dist/render/gi/voxel_scene.js +642 -0
  245. package/dist/render/gi/voxel_scene.js.map +1 -0
  246. package/dist/render/gi/voxelize_pass.js +223 -0
  247. package/dist/render/gi/voxelize_pass.js.map +1 -0
  248. package/dist/render/globalbindgroup_allocator.js +3 -2
  249. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  250. package/dist/render/gpu_picking.js +9 -36
  251. package/dist/render/gpu_picking.js.map +1 -1
  252. package/dist/render/hzb.js +80 -22
  253. package/dist/render/hzb.js.map +1 -1
  254. package/dist/render/instance_culling.js +499 -0
  255. package/dist/render/instance_culling.js.map +1 -0
  256. package/dist/render/lightpass.js +23 -9
  257. package/dist/render/lightpass.js.map +1 -1
  258. package/dist/render/lod.js +46 -0
  259. package/dist/render/lod.js.map +1 -0
  260. package/dist/render/oit.js +11 -11
  261. package/dist/render/oit.js.map +1 -1
  262. package/dist/render/primitive.js +301 -9
  263. package/dist/render/primitive.js.map +1 -1
  264. package/dist/render/primitive_readback.js +209 -0
  265. package/dist/render/primitive_readback.js.map +1 -0
  266. package/dist/render/render_queue.js +198 -11
  267. package/dist/render/render_queue.js.map +1 -1
  268. package/dist/render/renderer.js +14 -7
  269. package/dist/render/renderer.js.map +1 -1
  270. package/dist/render/rendergraph/blackboard.js +15 -1
  271. package/dist/render/rendergraph/blackboard.js.map +1 -1
  272. package/dist/render/rendergraph/executor.js +136 -0
  273. package/dist/render/rendergraph/executor.js.map +1 -1
  274. package/dist/render/rendergraph/forward_plus_builder.js +585 -59
  275. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  276. package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
  277. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
  278. package/dist/render/rendergraph/history_resources.js +8 -1
  279. package/dist/render/rendergraph/history_resources.js.map +1 -1
  280. package/dist/render/rendergraph/scene_render_context.js +31 -2
  281. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  282. package/dist/render/rendergraph/types.js.map +1 -1
  283. package/dist/render/renderpass.js +28 -5
  284. package/dist/render/renderpass.js.map +1 -1
  285. package/dist/render/sdf/box_allocator.js +98 -0
  286. package/dist/render/sdf/box_allocator.js.map +1 -0
  287. package/dist/render/sdf/global_sdf.js +865 -0
  288. package/dist/render/sdf/global_sdf.js.map +1 -0
  289. package/dist/render/sdf/scene_sdf.js +562 -0
  290. package/dist/render/sdf/scene_sdf.js.map +1 -0
  291. package/dist/render/sdf/sdf_atlas.js +227 -0
  292. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  293. package/dist/render/sdf/sdf_programs.js +42 -0
  294. package/dist/render/sdf/sdf_programs.js.map +1 -0
  295. package/dist/render/sdf/sdf_view.js +199 -0
  296. package/dist/render/sdf/sdf_view.js.map +1 -0
  297. package/dist/render/sdf/waterline.js +610 -0
  298. package/dist/render/sdf/waterline.js.map +1 -0
  299. package/dist/render/shadow_mask_pass.js +142 -25
  300. package/dist/render/shadow_mask_pass.js.map +1 -1
  301. package/dist/render/shore_wave_generator.js +1193 -0
  302. package/dist/render/shore_wave_generator.js.map +1 -0
  303. package/dist/render/sky.js +516 -86
  304. package/dist/render/sky.js.map +1 -1
  305. package/dist/render/transmission_thickness_pass.js +477 -0
  306. package/dist/render/transmission_thickness_pass.js.map +1 -0
  307. package/dist/render/underwater.js +524 -0
  308. package/dist/render/underwater.js.map +1 -0
  309. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  310. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  311. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  312. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  313. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  314. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  315. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  316. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  317. package/dist/render/volumetric_cloud/resources.js +380 -0
  318. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  319. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  320. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  321. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  322. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  323. package/dist/render/water_caustics.js +1195 -0
  324. package/dist/render/water_caustics.js.map +1 -0
  325. package/dist/render/water_foam.js +627 -0
  326. package/dist/render/water_foam.js.map +1 -0
  327. package/dist/render/water_interaction.js +1795 -0
  328. package/dist/render/water_interaction.js.map +1 -0
  329. package/dist/render/weightedblended_oit.js +36 -36
  330. package/dist/render/weightedblended_oit.js.map +1 -1
  331. package/dist/scene/basesprite.js +9 -4
  332. package/dist/scene/basesprite.js.map +1 -1
  333. package/dist/scene/batchgroup.js +108 -12
  334. package/dist/scene/batchgroup.js.map +1 -1
  335. package/dist/scene/environment.js +28 -7
  336. package/dist/scene/environment.js.map +1 -1
  337. package/dist/scene/foliage.js +1020 -0
  338. package/dist/scene/foliage.js.map +1 -0
  339. package/dist/scene/foliage_buckets.js +147 -0
  340. package/dist/scene/foliage_buckets.js.map +1 -0
  341. package/dist/scene/foliage_mask.js +358 -0
  342. package/dist/scene/foliage_mask.js.map +1 -0
  343. package/dist/scene/hair.js +15 -4
  344. package/dist/scene/hair.js.map +1 -1
  345. package/dist/scene/light.js +179 -13
  346. package/dist/scene/light.js.map +1 -1
  347. package/dist/scene/mesh.js +327 -45
  348. package/dist/scene/mesh.js.map +1 -1
  349. package/dist/scene/meshdrawable.js +6 -0
  350. package/dist/scene/meshdrawable.js.map +1 -1
  351. package/dist/scene/msdftext.js +9 -3
  352. package/dist/scene/msdftext.js.map +1 -1
  353. package/dist/scene/msdftextsprite.js +9 -3
  354. package/dist/scene/msdftextsprite.js.map +1 -1
  355. package/dist/scene/particlesys.js +8 -2
  356. package/dist/scene/particlesys.js.map +1 -1
  357. package/dist/scene/physics_settings.js +157 -0
  358. package/dist/scene/physics_settings.js.map +1 -0
  359. package/dist/scene/scene.js +190 -44
  360. package/dist/scene/scene.js.map +1 -1
  361. package/dist/scene/scene_node.js +147 -6
  362. package/dist/scene/scene_node.js.map +1 -1
  363. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  364. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  365. package/dist/scene/terrain-cm/grass.js +881 -42
  366. package/dist/scene/terrain-cm/grass.js.map +1 -1
  367. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  368. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  369. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  370. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  371. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  372. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  373. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  374. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  375. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  376. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  377. package/dist/scene/update_queue.js +54 -0
  378. package/dist/scene/update_queue.js.map +1 -0
  379. package/dist/scene/water.js +997 -96
  380. package/dist/scene/water.js.map +1 -1
  381. package/dist/scene/water_surface_sampler.js +324 -0
  382. package/dist/scene/water_surface_sampler.js.map +1 -0
  383. package/dist/scene/wind.js +317 -0
  384. package/dist/scene/wind.js.map +1 -0
  385. package/dist/shaders/atmosphere.js +388 -166
  386. package/dist/shaders/atmosphere.js.map +1 -1
  387. package/dist/shaders/fog.js +100 -32
  388. package/dist/shaders/fog.js.map +1 -1
  389. package/dist/shaders/gi.js +365 -0
  390. package/dist/shaders/gi.js.map +1 -0
  391. package/dist/shaders/ltc_rect.js +202 -0
  392. package/dist/shaders/ltc_rect.js.map +1 -0
  393. package/dist/shaders/misc.js +1 -10
  394. package/dist/shaders/misc.js.map +1 -1
  395. package/dist/shaders/noise.js +5 -1
  396. package/dist/shaders/noise.js.map +1 -1
  397. package/dist/shaders/probes.js +309 -0
  398. package/dist/shaders/probes.js.map +1 -0
  399. package/dist/shaders/sdf.js +537 -0
  400. package/dist/shaders/sdf.js.map +1 -0
  401. package/dist/shaders/shadow.js +104 -70
  402. package/dist/shaders/shadow.js.map +1 -1
  403. package/dist/shaders/skin_brdf.js +243 -0
  404. package/dist/shaders/skin_brdf.js.map +1 -0
  405. package/dist/shaders/ssr.js +6 -159
  406. package/dist/shaders/ssr.js.map +1 -1
  407. package/dist/shaders/temporal.js +38 -27
  408. package/dist/shaders/temporal.js.map +1 -1
  409. package/dist/shaders/water.js +40 -87
  410. package/dist/shaders/water.js.map +1 -1
  411. package/dist/shaders/water_medium.js +42 -0
  412. package/dist/shaders/water_medium.js.map +1 -0
  413. package/dist/shadow/dom.js +110 -19
  414. package/dist/shadow/dom.js.map +1 -1
  415. package/dist/shadow/esm.js +3 -3
  416. package/dist/shadow/esm.js.map +1 -1
  417. package/dist/shadow/pcf_opt.js +15 -48
  418. package/dist/shadow/pcf_opt.js.map +1 -1
  419. package/dist/shadow/pcf_pd.js +15 -53
  420. package/dist/shadow/pcf_pd.js.map +1 -1
  421. package/dist/shadow/pcss.js +34 -9
  422. package/dist/shadow/pcss.js.map +1 -1
  423. package/dist/shadow/shadow_impl.js +3 -8
  424. package/dist/shadow/shadow_impl.js.map +1 -1
  425. package/dist/shadow/shadow_region.js +87 -49
  426. package/dist/shadow/shadow_region.js.map +1 -1
  427. package/dist/shadow/shadowmapper.js +93 -53
  428. package/dist/shadow/shadowmapper.js.map +1 -1
  429. package/dist/shadow/ssm.js +18 -72
  430. package/dist/shadow/ssm.js.map +1 -1
  431. package/dist/shadow/vsm.js +3 -3
  432. package/dist/shadow/vsm.js.map +1 -1
  433. package/dist/shapes/shape.js +44 -1
  434. package/dist/shapes/shape.js.map +1 -1
  435. package/dist/utility/buoyancy.js +287 -0
  436. package/dist/utility/buoyancy.js.map +1 -0
  437. package/dist/utility/physical.js +10 -1
  438. package/dist/utility/physical.js.map +1 -1
  439. package/dist/utility/pmrem.js +17 -43
  440. package/dist/utility/pmrem.js.map +1 -1
  441. package/dist/utility/sdf/bake.js +435 -0
  442. package/dist/utility/sdf/bake.js.map +1 -0
  443. package/dist/utility/sdf/bvh.js +576 -0
  444. package/dist/utility/sdf/bvh.js.map +1 -0
  445. package/dist/utility/serialization/manager.js +36 -6
  446. package/dist/utility/serialization/manager.js.map +1 -1
  447. package/dist/utility/serialization/scene/animation.js +77 -7
  448. package/dist/utility/serialization/scene/animation.js.map +1 -1
  449. package/dist/utility/serialization/scene/batch.js +11 -4
  450. package/dist/utility/serialization/scene/batch.js.map +1 -1
  451. package/dist/utility/serialization/scene/camera.js +140 -279
  452. package/dist/utility/serialization/scene/camera.js.map +1 -1
  453. package/dist/utility/serialization/scene/cloth.js +25 -0
  454. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  455. package/dist/utility/serialization/scene/common.js +14 -6
  456. package/dist/utility/serialization/scene/common.js.map +1 -1
  457. package/dist/utility/serialization/scene/foliage.js +821 -0
  458. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  459. package/dist/utility/serialization/scene/hair.js +11 -4
  460. package/dist/utility/serialization/scene/hair.js.map +1 -1
  461. package/dist/utility/serialization/scene/light.js +115 -7
  462. package/dist/utility/serialization/scene/light.js.map +1 -1
  463. package/dist/utility/serialization/scene/material.js +388 -220
  464. package/dist/utility/serialization/scene/material.js.map +1 -1
  465. package/dist/utility/serialization/scene/mesh.js +69 -4
  466. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  467. package/dist/utility/serialization/scene/node.js +140 -5
  468. package/dist/utility/serialization/scene/node.js.map +1 -1
  469. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  470. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  471. package/dist/utility/serialization/scene/particle.js +11 -4
  472. package/dist/utility/serialization/scene/particle.js.map +1 -1
  473. package/dist/utility/serialization/scene/physics.js +120 -0
  474. package/dist/utility/serialization/scene/physics.js.map +1 -0
  475. package/dist/utility/serialization/scene/primitive.js +124 -10
  476. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  477. package/dist/utility/serialization/scene/scene.js +1687 -51
  478. package/dist/utility/serialization/scene/scene.js.map +1 -1
  479. package/dist/utility/serialization/scene/sprite.js +11 -4
  480. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  481. package/dist/utility/serialization/scene/terrain.js +163 -33
  482. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  483. package/dist/utility/serialization/scene/text.js +11 -4
  484. package/dist/utility/serialization/scene/text.js.map +1 -1
  485. package/dist/utility/serialization/scene/water.js +2473 -114
  486. package/dist/utility/serialization/scene/water.js.map +1 -1
  487. package/dist/utility/serialization/types.js.map +1 -1
  488. package/dist/utility/shprojector.js +97 -109
  489. package/dist/utility/shprojector.js.map +1 -1
  490. package/dist/utility/textures/foam.js +170 -0
  491. package/dist/utility/textures/foam.js.map +1 -0
  492. package/dist/utility/textures/ggxlut.js +17 -43
  493. package/dist/utility/textures/ggxlut.js.map +1 -1
  494. package/dist/utility/textures/ltcdata.js +4 -4
  495. package/dist/utility/textures/ltcdata.js.map +1 -1
  496. package/dist/utility/textures/ltclut.js +16 -6
  497. package/dist/utility/textures/ltclut.js.map +1 -1
  498. package/dist/utility/unsupported.js +24 -0
  499. package/dist/utility/unsupported.js.map +1 -0
  500. package/dist/values.js +13 -1
  501. package/dist/values.js.map +1 -1
  502. package/package.json +25 -12
  503. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  504. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  505. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  506. package/src/asset/meshoptimizer/LICENSE +21 -0
@@ -1,11 +1,11 @@
1
1
  import { ShadowImpl } from './shadow_impl.js';
2
2
  import { LIGHT_TYPE_POINT } from '../values.js';
3
- import { ndcToShadowCoord3, shadowCoordDepthInRange, applyShadowDepthBias } from '../shaders/shadow.js';
3
+ import { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow.js';
4
4
  import { computeShadowBias } from './shader.js';
5
5
  import { ShaderHelper } from '../material/shader/helper.js';
6
6
  import { getDevice } from '../app/api.js';
7
7
  import { fetchSampler } from '../utility/misc.js';
8
- import { Vector4, REVERSE_Z } from '@zephyr3d/base';
8
+ import { Vector4, CubeFace, REVERSE_Z } from '@zephyr3d/base';
9
9
 
10
10
  /**
11
11
  * Opacity layers, which is three rather than four because the fourth channel of
@@ -108,7 +108,8 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
108
108
  * interior unshadowed.
109
109
  *
110
110
  * Exact for directional lights, whose orthographic projection makes device
111
- * depth a linear function of world depth. Spot and point lights project
111
+ * depth a linear function of world depth, and for point and rect lights,
112
+ * whose cube maps store distance from the light. Spot lights project
112
113
  * perspectively, so there the value is only accurate near the middle of the
113
114
  * shadow camera's range - which is where hair lit by one usually sits.
114
115
  */ get layerDistance() {
@@ -190,8 +191,20 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
190
191
  // The light camera is finalised by the time the casters are drawn, so this is
191
192
  // where the world-to-device depth scale becomes known. It stays valid for the
192
193
  // lighting pass that follows, which reads the same converted params back.
193
- const range = shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;
194
+ // A cube map stores radial distance over the light's range instead, which is
195
+ // what the layer span must then be measured against.
196
+ const range = isCube(shadowMapParams) ? shadowMapParams.depthRange ?? 1 : shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;
194
197
  this._depthRange = range > 1e-6 ? range : 1;
198
+ if (isCube(shadowMapParams)) {
199
+ // These framebuffers are this implementation's own, so the face the shadow
200
+ // mapper selected on the shared one has to be selected on them too.
201
+ const face = shadowMapParams.cubeFace ?? CubeFace.PX;
202
+ if (pass === 0) {
203
+ implData.depthFramebuffer.setDepthAttachmentCubeFace(face);
204
+ } else {
205
+ implData.opacityFramebuffer.setColorAttachmentCubeFace(0, face);
206
+ }
207
+ }
195
208
  getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);
196
209
  }
197
210
  setCasterRenderStates(_shadowMapParams, stateSet) {
@@ -207,13 +220,14 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
207
220
  stateSet.useBlendingState().enable(true).setBlendEquation('add', 'add').setBlendFuncRGB('one', 'one').setBlendFuncAlpha('one', 'zero');
208
221
  stateSet.useDepthState().enableTest(false).enableWrite(false);
209
222
  }
210
- getShadowMapClearColor(_shadowMapParams) {
223
+ getShadowMapClearColor(shadowMapParams) {
224
+ // Radial distance in a cube map is linear, so reverse-Z does not flip it.
225
+ const farthest = REVERSE_Z && !isCube(shadowMapParams) ? 0 : 1;
211
226
  if (this._geometryPass === 1) {
212
227
  // No hair over this texel means no absorption. Alpha carries z0, and the
213
- // sentinel below makes an uncovered texel read as "nothing in front".
214
- return new Vector4(0, 0, 0, REVERSE_Z ? 0 : 1);
228
+ // sentinel makes an uncovered texel read as "nothing in front".
229
+ return new Vector4(0, 0, 0, farthest);
215
230
  }
216
- const farthest = REVERSE_Z ? 0 : 1;
217
231
  return new Vector4(farthest, farthest, farthest, 1);
218
232
  }
219
233
  getShadowMapColorFormat(_shadowMapParams) {
@@ -273,7 +287,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
273
287
  // and cleared at the end of each frame, so holding directly-created textures
274
288
  // in it leaks them at whatever rate the scene renders.
275
289
  const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);
276
- const result = device.pool.fetchTemporalTexture2D(false, format, width, height, false);
290
+ const result = isCube(shadowMapParams) ? device.pool.fetchTemporalTextureCube(false, format, width, false) : device.pool.fetchTemporalTexture2D(false, format, width, height, false);
277
291
  // Pass 0 borrows the shadow map's own depth attachment, which is otherwise
278
292
  // unused - this implementation asks for no colour there - so the hardware
279
293
  // depth test resolves the frontmost strand for it. Pass 1 gets no depth,
@@ -334,9 +348,11 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
334
348
  * behind the front and the clamp below flattens the whole technique to no
335
349
  * shadow at all.
336
350
  * @internal
337
- */ layerCoord(scope, depth, z0, layerSpan) {
351
+ */ layerCoord(scope, depth, z0, layerSpan, radial) {
338
352
  const pb = scope.$builder;
339
- const delta = REVERSE_Z ? pb.sub(z0, depth) : pb.sub(depth, z0);
353
+ // A cube map's radial distance grows away from the light whatever the depth
354
+ // convention.
355
+ const delta = REVERSE_Z && !radial ? pb.sub(z0, depth) : pb.sub(depth, z0);
340
356
  return pb.div(pb.max(delta, 0), layerSpan);
341
357
  }
342
358
  /**
@@ -354,7 +370,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
354
370
  // two cases that matter - an opaque caster and a fully transparent one - are
355
371
  // the same value there.
356
372
  const hasAlpha = geometryPass === 1 && !!alpha;
357
- const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}`;
373
+ const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}${isCube(shadowMapParams) ? '_c' : ''}`;
358
374
  const params = hasAlpha ? [
359
375
  pb.vec3('worldPos'),
360
376
  pb.float('alpha')
@@ -370,7 +386,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
370
386
  this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;
371
387
  // Distance behind the frontmost strand, in layer-span units. A fragment at
372
388
  // or in front of z0 lands at zero and fills every layer.
373
- this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan);
389
+ this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan, isCube(shadowMapParams));
374
390
  // Layer k's far boundary sits at (k+1)/3 of the span, and a fragment
375
391
  // contributes to every layer whose boundary lies behind it. The last
376
392
  // layer has no far boundary: it extends to the end of the caster volume,
@@ -417,9 +433,33 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
417
433
  return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;
418
434
  }
419
435
  computeShadow(shadowMapParams, scope, shadowVertex, NdotL) {
420
- const funcName = 'lib_computeShadowDOM';
421
436
  const pb = scope.$builder;
422
437
  const that = this;
438
+ if (isCube(shadowMapParams)) {
439
+ // The shadow matrix is the identity for a cube map, so the "shadow vertex"
440
+ // is the receiver's world position; its depth is the radial distance the
441
+ // casters stored, over the same range.
442
+ pb.func('lib_computeShadowDOMCube', [
443
+ pb.vec4('shadowVertex'),
444
+ pb.float('NdotL')
445
+ ], function() {
446
+ this.$l.posRange = ShaderHelper.getLightPositionAndRangeForShadow(this);
447
+ this.$l.dir = pb.sub(this.shadowVertex.xyz, this.posRange.xyz);
448
+ this.$l.depth = pb.div(pb.length(this.dir), this.posRange.w);
449
+ this.$l.shadow = pb.float(1);
450
+ this.$if(pb.lessThanEqual(this.depth, 1), function() {
451
+ // The kernel needs the bias for the same reason as the 2D map below.
452
+ if (that._filterSize > 1) {
453
+ this.$l.bias = computeShadowBias(shadowMapParams.lightType, this, this.depth, this.NdotL, true);
454
+ this.depth = applyShadowDepthBias(this, this.depth, this.bias, false);
455
+ }
456
+ this.shadow = that.transmittanceCube(this, this.dir, this.depth);
457
+ });
458
+ this.$return(this.shadow);
459
+ });
460
+ return pb.getGlobalScope().lib_computeShadowDOMCube(shadowVertex, NdotL);
461
+ }
462
+ const funcName = 'lib_computeShadowDOM';
423
463
  pb.func(funcName, [
424
464
  pb.vec4('shadowVertex'),
425
465
  pb.float('NdotL')
@@ -495,22 +535,70 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
495
535
  return pb.getGlobalScope()[funcName](shadowCoord);
496
536
  }
497
537
  /**
538
+ * {@link DOM.transmittance} for a cube map: the same kernel, laid out on the
539
+ * face around the receiver's direction.
540
+ *
541
+ * @remarks
542
+ * The taps step one texel at a time on the unit cube, where a face texel spans
543
+ * `2 / size`, in a plane perpendicular to the ray - which matches the face's
544
+ * own grid at its centre and differs only to second order off it.
545
+ * @internal
546
+ */ transmittanceCube(scope, dir, receiverDepth) {
547
+ const pb = scope.$builder;
548
+ const that = this;
549
+ const size = this._filterSize;
550
+ const funcName = `lib_domTransmittanceCube_${size}`;
551
+ pb.func(funcName, [
552
+ pb.vec3('dir'),
553
+ pb.float('receiverDepth')
554
+ ], function() {
555
+ if (size <= 1) {
556
+ this.$return(that.layerTransmittance(this, this.dir, this.receiverDepth, true));
557
+ } else {
558
+ this.$l.unitDir = pb.normalize(this.dir);
559
+ this.$l.onCube = pb.div(this.unitDir, pb.max(pb.max(pb.abs(this.unitDir.x), pb.abs(this.unitDir.y)), pb.abs(this.unitDir.z)));
560
+ this.$l.helper = this.$choice(pb.lessThan(pb.abs(this.unitDir.y), 0.99), pb.vec3(0, 1, 0), pb.vec3(1, 0, 0));
561
+ this.$l.side = pb.normalize(pb.cross(this.helper, this.unitDir));
562
+ this.$l.up = pb.cross(this.unitDir, this.side);
563
+ this.$l.texelSize = pb.div(2, ShaderHelper.getShadowCameraParams(this).z);
564
+ this.$l.sum = pb.float(0);
565
+ this.$l.tapDir = pb.vec3();
566
+ const radius = (size - 1) / 2;
567
+ for(let y = -radius; y <= radius; y++){
568
+ for(let x = -radius; x <= radius; x++){
569
+ this.tapDir = pb.add(this.onCube, pb.mul(pb.add(pb.mul(this.side, x), pb.mul(this.up, y)), this.texelSize));
570
+ this.sum = pb.add(this.sum, that.layerTransmittance(this, this.tapDir, this.receiverDepth, true));
571
+ }
572
+ }
573
+ this.$return(pb.div(this.sum, size * size));
574
+ }
575
+ });
576
+ return pb.getGlobalScope()[funcName](dir, receiverDepth);
577
+ }
578
+ /**
498
579
  * Transmittance from a single shadow map texel.
499
580
  * @internal
500
581
  */ tapTransmittance(scope, uv, receiverDepth) {
582
+ return this.layerTransmittance(scope, uv, receiverDepth, false);
583
+ }
584
+ /**
585
+ * Transmittance from the texel at `coord` - a map UV, or for a cube map a
586
+ * direction from the light.
587
+ * @internal
588
+ */ layerTransmittance(scope, coord, receiverDepth, radial) {
501
589
  const pb = scope.$builder;
502
590
  const that = this;
503
- const funcName = 'lib_domTap';
591
+ const funcName = radial ? 'lib_domTapCube' : 'lib_domTap';
504
592
  pb.func(funcName, [
505
- pb.vec2('uv'),
593
+ radial ? pb.vec3('coord') : pb.vec2('coord'),
506
594
  pb.float('receiverDepth')
507
595
  ], function() {
508
- this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.uv, 0);
596
+ this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.coord, 0);
509
597
  this.$l.layers = this.texel.rgb;
510
598
  this.$l.z0 = this.texel.a;
511
599
  this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;
512
600
  this.$l.density = ShaderHelper.getShadowImplParams(this).y;
513
- this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan);
601
+ this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan, radial);
514
602
  // The layers are cumulative, so opacity at an arbitrary depth is a lerp
515
603
  // between the two bracketing layer values. Scaling t by the layer count puts
516
604
  // the integer part on the near layer and the fraction between the pair.
@@ -538,9 +626,12 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
538
626
  // would have.
539
627
  this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));
540
628
  });
541
- return pb.getGlobalScope()[funcName](uv, receiverDepth);
629
+ return pb.getGlobalScope()[funcName](coord, receiverDepth);
542
630
  }
543
631
  }
632
+ /** Whether the map is a point-projection cube (point and rect lights). @internal */ function isCube(shadowMapParams) {
633
+ return shadowMapParams.lightType === LIGHT_TYPE_POINT;
634
+ }
544
635
 
545
636
  export { DOM };
546
637
  //# sourceMappingURL=dom.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dom.js","sources":["../../src/shadow/dom.ts"],"sourcesContent":["import type {\r\n BindGroup,\r\n FrameBuffer,\r\n PBGlobalScope,\r\n PBInsideFunctionScope,\r\n PBShaderExp,\r\n RenderStateSet,\r\n Texture2D,\r\n TextureFormat\r\n} from '@zephyr3d/device';\r\nimport { ShadowImpl } from './shadow_impl';\r\nimport type { ShadowMapParams, ShadowMapType } from './shadowmapper';\r\nimport { LIGHT_TYPE_POINT } from '../values';\r\nimport { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow';\r\nimport { computeShadowBias } from './shader';\r\nimport { ShaderHelper } from '../material/shader/helper';\r\nimport { getDevice } from '../app/api';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport { REVERSE_Z, Vector4, type Nullable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Opacity layers, which is three rather than four because the fourth channel of\r\n * the result texture carries the depth the layers are measured from. Keeping\r\n * both in one texture is what lets the receiver read the whole technique through\r\n * the single shadow-map binding the lighting shaders declare.\r\n * @internal\r\n */\r\nconst DOM_LAYER_COUNT = 3;\r\n\r\n/** @internal Caster-pass uniform holding the frontmost depth from geometry pass 0. */\r\nconst UNIFORM_NAME_DOM_FRONT_DEPTH = 'Z_domFrontDepth';\r\n\r\n/**\r\n * Transmittance a fully opaque caster is recorded as, since zero has no finite\r\n * optical depth to blend. Dark enough to read as black, and small enough in the\r\n * exponent that several opaque layers can stack without saturating half floats.\r\n * @internal\r\n */\r\nconst DOM_MIN_TRANSMITTANCE = 0.001;\r\n\r\n/** @internal */\r\ntype DOMImplData = {\r\n /**\r\n * Frontmost caster depth, written by geometry pass 0 and sampled by pass 1.\r\n * Separate from the result texture on purpose: a texture cannot be a render\r\n * target and a sampled resource in the same pass.\r\n */\r\n frontDepth: Texture2D;\r\n /** RGB = cumulative optical depth per layer, A = the depth those layers start at. */\r\n result: Texture2D;\r\n /** Targets {@link DOMImplData.frontDepth}, reusing the shared depth attachment. */\r\n depthFramebuffer: FrameBuffer;\r\n /** Targets {@link DOMImplData.result}. No depth attachment - pass 1 does not test. */\r\n opacityFramebuffer: FrameBuffer;\r\n};\r\n\r\n/**\r\n * Deep opacity map shadows.\r\n *\r\n * @remarks\r\n * Hair is the case an ordinary shadow map cannot express. A shadow map answers\r\n * \"is this point behind the nearest caster\", which is the right question for a\r\n * wall and the wrong one for ten thousand strands: light entering a groom is not\r\n * blocked at its surface, it is attenuated gradually as it passes more and more\r\n * fibres. A binary test renders that as a hard edge with everything behind it\r\n * uniformly black.\r\n *\r\n * A deep opacity map (Yuksel & Keyser 2008) records the attenuation instead of\r\n * the boundary. Geometry pass 0 writes the frontmost caster depth `z0` per texel.\r\n * Pass 1 rasterises the casters again and each fragment adds its optical depth to\r\n * every layer lying behind it, giving cumulative absorption sampled at three\r\n * depths measured *from `z0`* rather than from the light. Because the layers\r\n * follow the hair surface, three of them resolve what a plain opacity shadow map\r\n * needs dozens of uniformly spaced ones to match.\r\n *\r\n * Recording optical depth rather than coverage is what keeps it exact for solid\r\n * casters as well as thin ones, so a scene does not have to reserve this mode for\r\n * its hair: see the caster output for why the two differ.\r\n *\r\n * WebGPU only, and deliberately so: the strand geometry this exists to shadow is\r\n * itself WebGPU only, so supporting the WebGL fallbacks - cascade atlases instead\r\n * of array layers, RGBA8-packed depth instead of float - would double the surface\r\n * area to serve no material.\r\n *\r\n * @internal\r\n */\r\nexport class DOM extends ShadowImpl {\r\n /** @internal */\r\n private _layerDistance: number;\r\n /** @internal */\r\n private _density: number;\r\n /** @internal Width of the sampling kernel in texels; 1 disables filtering. */\r\n private _filterSize: number;\r\n /** @internal */\r\n private readonly _paramsScratch: Vector4;\r\n /**\r\n * @internal\r\n * Which geometry pass is being rasterised. Lives on the implementation rather\r\n * than in `implData` because {@link DOM.getShaderHash} has no access to the\r\n * params, and the hash must separate the two passes or they share a program.\r\n */\r\n private _geometryPass: number;\r\n /**\r\n * @internal\r\n * Depth the shadow camera spans, captured when the map is rendered. Needed to\r\n * express {@link DOM.layerDistance} in world units: the shader compares device\r\n * depths, and for the orthographic projection a directional light uses those\r\n * are the world depth divided by exactly this.\r\n */\r\n private _depthRange: number;\r\n constructor(layerDistance = 0.25, density = 1, filterSize = 5) {\r\n super();\r\n this._layerDistance = layerDistance;\r\n this._density = density;\r\n this._filterSize = DOM.clampFilterSize(filterSize);\r\n this._paramsScratch = new Vector4();\r\n this._geometryPass = 0;\r\n this._depthRange = 1;\r\n }\r\n /** @internal */\r\n private static clampFilterSize(val: number) {\r\n return val !== 1 && val !== 3 && val !== 5 && val !== 7 ? 5 : val;\r\n }\r\n /**\r\n * Width of the sampling kernel, in shadow map texels. One of 1, 3, 5 or 7.\r\n *\r\n * @remarks\r\n * The graded transmittance this technique records runs along the light, not\r\n * across the map, so at the silhouette of a groom - where the change is one of\r\n * coverage rather than of depth - a single tap is as abrupt as an unfiltered\r\n * shadow map. This is the kernel that softens that edge, and it is the same\r\n * knob PCF's kernel size is, with the difference that each tap here costs a\r\n * layer lookup rather than a depth comparison.\r\n *\r\n * Set to 1 to sample once, which is measurably cheaper and visibly harder.\r\n */\r\n get filterSize() {\r\n return this._filterSize;\r\n }\r\n set filterSize(val) {\r\n this._filterSize = DOM.clampFilterSize(val);\r\n }\r\n /**\r\n * Depth the layers span, in world units along the light direction.\r\n *\r\n * @remarks\r\n * Set it to roughly the thickness of the hair. Too small and everything past\r\n * the outer strands saturates the last layer, which is a hard shadow again;\r\n * too large and all three layers land inside the first strand, leaving the\r\n * interior unshadowed.\r\n *\r\n * Exact for directional lights, whose orthographic projection makes device\r\n * depth a linear function of world depth. Spot and point lights project\r\n * perspectively, so there the value is only accurate near the middle of the\r\n * shadow camera's range - which is where hair lit by one usually sits.\r\n */\r\n get layerDistance() {\r\n return this._layerDistance;\r\n }\r\n set layerDistance(val) {\r\n this._layerDistance = val > 0 ? val : 0.0001;\r\n }\r\n /**\r\n * Artistic multiplier on the absorption the casters actually recorded.\r\n *\r\n * @remarks\r\n * One reproduces alpha compositing exactly and is the right default. Raise it\r\n * to deepen the interior of a groom without moving the layers, lower it to let\r\n * more light through than the geometry strictly would.\r\n */\r\n get density() {\r\n return this._density;\r\n }\r\n set density(val) {\r\n this._density = val < 0 ? 0 : val;\r\n }\r\n getType() {\r\n return 'dom' as const;\r\n }\r\n resourceDirty() {\r\n return this._resourceDirty;\r\n }\r\n getShadowMapBorder() {\r\n // Margin so the kernel's outer taps still land inside the map at the edges of\r\n // the shadow region, matching what the PCF implementations reserve.\r\n return this._filterSize;\r\n }\r\n getDepthScale() {\r\n return 1;\r\n }\r\n setDepthScale(_val: number) {}\r\n /**\r\n * Layer geometry and density, for both the caster and the receiver. `z` and\r\n * `w` are unused.\r\n *\r\n * @remarks\r\n * `x` is the layer span converted from world units into the device-depth\r\n * difference the shaders actually compare, using the range captured when the\r\n * map was rendered.\r\n */\r\n getParams(out?: Vector4) {\r\n const result = out ?? this._paramsScratch;\r\n result.setXYZW(this._layerDistance / this._depthRange, this._density, 0, 0);\r\n return result;\r\n }\r\n getGeometryPassCount() {\r\n return 2;\r\n }\r\n supportsCascades() {\r\n // Each split would need its own depth and layer set, and both already share\r\n // the one texture the receiver can bind.\r\n return false;\r\n }\r\n clipsCasterAlpha() {\r\n // Neither pass wants the clip. Pass 1 integrates the alpha, and clipping is\r\n // destructive to it in both of the forms the material applies: a dithered\r\n // caster survives with probability alpha and then contributes the absorption\r\n // of that same alpha, counting it twice, and a hard cutoff drops the sub-pixel\r\n // strands that carry most of a groom's transmittance.\r\n //\r\n // Pass 0 skips it for a different reason. Its job is to find the frontmost\r\n // strand, and under dithering the clip makes that choice per-pixel random -\r\n // the layers would then start at a depth that flickers between strands, and\r\n // every opacity reading behind it inherits the jitter.\r\n //\r\n // The case this gives up is a caster whose alpha is a real mask rather than a\r\n // coverage value, such as a hair card with cut-out texels: pass 0 will place\r\n // z0 on the card's surface even where it is fully transparent. Strand\r\n // geometry, which is what this technique is for, has no such texels.\r\n return false;\r\n }\r\n beginGeometryPass(shadowMapParams: ShadowMapParams, pass: number) {\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n this._geometryPass = pass;\r\n // The light camera is finalised by the time the casters are drawn, so this is\r\n // where the world-to-device depth scale becomes known. It stays valid for the\r\n // lighting pass that follows, which reads the same converted params back.\r\n const range = shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;\r\n this._depthRange = range > 1e-6 ? range : 1;\r\n getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);\r\n }\r\n setCasterRenderStates(_shadowMapParams: ShadowMapParams, stateSet: RenderStateSet) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n // Every strand between z0 and the last layer has to contribute, so the pass\r\n // must not depth-test against the frontmost surface pass 0 resolved, and must\r\n // not write depth of its own - its framebuffer has no depth attachment at all.\r\n // Optical depth sums across the three layer channels; alpha instead carries\r\n // z0, which every fragment reads from the same texel, so replacing is correct\r\n // where summing would multiply it by the number of overlapping strands.\r\n stateSet\r\n .useBlendingState()\r\n .enable(true)\r\n .setBlendEquation('add', 'add')\r\n .setBlendFuncRGB('one', 'one')\r\n .setBlendFuncAlpha('one', 'zero');\r\n stateSet.useDepthState().enableTest(false).enableWrite(false);\r\n }\r\n getShadowMapClearColor(_shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass === 1) {\r\n // No hair over this texel means no absorption. Alpha carries z0, and the\r\n // sentinel below makes an uncovered texel read as \"nothing in front\".\r\n return new Vector4(0, 0, 0, REVERSE_Z ? 0 : 1);\r\n }\r\n const farthest = REVERSE_Z ? 0 : 1;\r\n return new Vector4(farthest, farthest, farthest, 1);\r\n }\r\n getShadowMapColorFormat(_shadowMapParams: ShadowMapParams) {\r\n // Null keeps the framebuffer the caller allocates depth-only. The colour this\r\n // technique needs is allocated here, against framebuffers of its own, so\r\n // letting the caller also allocate a full-size colour attachment would waste\r\n // it outright.\r\n return null;\r\n }\r\n getShadowMapDepthFormat(_shadowMapParams: ShadowMapParams) {\r\n return this.preferredShadowMapDepthFormat();\r\n }\r\n useNativeShadowMap(_shadowMapParams: ShadowMapParams) {\r\n // The receiver needs the actual stored values - a depth to measure offsets\r\n // from and three sums to interpolate - not the result of a hardware compare.\r\n return false;\r\n }\r\n getShadowMap(shadowMapParams: ShadowMapParams) {\r\n return (shadowMapParams.implData as DOMImplData).result as ShadowMapType;\r\n }\r\n /**\r\n * Format for both targets.\r\n *\r\n * @remarks\r\n * Full float wherever the accumulation pass can blend into it, and the reason\r\n * is the anchor depth, not the absorption sums. `z0` is stored absolute, in\r\n * units of the shadow camera's whole depth range, and every layer coordinate\r\n * on both sides of the technique is a difference against it divided by the\r\n * layer span. At half precision its quantisation step is about 2^-11 of the\r\n * stored value - roughly `0.0005 * depthRange` in world units - which for a\r\n * shadow camera spanning a large scene is comparable to the depth of the hair\r\n * itself. The error is independent per texel, so it does not read as bias but\r\n * as blotches: patches of a backlit groom whose receivers land in front of\r\n * their quantised `z0` and come out fully lit. A layer span large enough to\r\n * drown the noise hides it, but throws away the graded falloff the technique\r\n * exists for.\r\n *\r\n * Half float remains the fallback for devices whose blending cannot target\r\n * full float; there the practical mitigation is a tight shadow distance.\r\n * @internal\r\n */\r\n private colorFormat(): TextureFormat {\r\n const caps = getDevice().getDeviceCaps().textureCaps;\r\n if (caps.supportFloatColorBuffer && caps.supportFloatBlending) {\r\n return 'rgba32f';\r\n }\r\n return caps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba32f';\r\n }\r\n doUpdateResources(shadowMapParams: ShadowMapParams) {\r\n const device = getDevice();\r\n const sharedDepth = shadowMapParams.shadowMapFramebuffer!.getDepthAttachment()!;\r\n const width = sharedDepth.width;\r\n const height = sharedDepth.height;\r\n const format = this.colorFormat();\r\n // Everything here is pooled, per frame, the way the blur targets of VSM and\r\n // ESM are. `implData` cannot cache across frames even though it looks like it\r\n // could: it lives on a ShadowMapParams that is recycled between every light\r\n // and cleared at the end of each frame, so holding directly-created textures\r\n // in it leaks them at whatever rate the scene renders.\r\n const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n const result = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n // Pass 0 borrows the shadow map's own depth attachment, which is otherwise\r\n // unused - this implementation asks for no colour there - so the hardware\r\n // depth test resolves the frontmost strand for it. Pass 1 gets no depth,\r\n // which is both what stops it testing and what frees `frontDepth` to be\r\n // sampled while `result` is written.\r\n const depthFramebuffer = device.pool.createTemporalFramebuffer(true, [frontDepth], sharedDepth);\r\n const opacityFramebuffer = device.pool.createTemporalFramebuffer(true, [result], null);\r\n // The framebuffers hold the references now; these drop the fetch counts so\r\n // both textures return to the pool when the frame ends.\r\n device.pool.releaseTexture(frontDepth);\r\n device.pool.releaseTexture(result);\r\n shadowMapParams.implData = {\r\n frontDepth,\r\n result,\r\n depthFramebuffer,\r\n opacityFramebuffer\r\n } satisfies DOMImplData;\r\n shadowMapParams.shadowMap = result;\r\n shadowMapParams.shadowMapSampler = result.getDefaultSampler(false);\r\n this._resourceDirty = false;\r\n }\r\n postRenderShadowMap(_shadowMapParams: ShadowMapParams) {}\r\n getShaderHash() {\r\n // The two geometry passes emit different caster fragments and the shadow pass\r\n // keys its programs on this hash, so the pass index has to appear in it. The\r\n // kernel is unrolled into the receiver, so it belongs here too.\r\n return `${DOM_LAYER_COUNT}_${this._geometryPass}_${this._filterSize}`;\r\n }\r\n declareCasterUniforms(scope: PBGlobalScope, _shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const pb = scope.$builder;\r\n // sampleType before uniform(), matching how the receiver's shadow map is\r\n // declared: the binding is created from the accumulated descriptor.\r\n const tex = pb.tex2D();\r\n tex.sampleType('unfilterable-float');\r\n scope[UNIFORM_NAME_DOM_FRONT_DEPTH] = tex.uniform(0);\r\n }\r\n applyCasterUniforms(bindGroup: BindGroup, shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n bindGroup.setTexture(\r\n UNIFORM_NAME_DOM_FRONT_DEPTH,\r\n implData.frontDepth,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n }\r\n /**\r\n * How far a depth lies behind the frontmost strand, in layer-span units.\r\n *\r\n * @remarks\r\n * Both callers measure \"deeper into the hair than z0\", but which direction that\r\n * is depends on the depth encoding: under reverse-Z a farther surface has the\r\n * *smaller* value, so the plain subtraction is negative for every fragment\r\n * behind the front and the clamp below flattens the whole technique to no\r\n * shadow at all.\r\n * @internal\r\n */\r\n private layerCoord(\r\n scope: PBInsideFunctionScope,\r\n depth: PBShaderExp,\r\n z0: PBShaderExp,\r\n layerSpan: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const delta = REVERSE_Z ? pb.sub(z0, depth) : pb.sub(depth, z0);\r\n return pb.div(pb.max(delta, 0), layerSpan);\r\n }\r\n /**\r\n * Caster output.\r\n *\r\n * Pass 0 writes the frontmost depth. Pass 1 writes this fragment's optical depth\r\n * into the layers behind it, for additive blending to sum, and carries z0\r\n * through alpha so the receiver can find where the layers start.\r\n */\r\n computeShadowMapDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp,\r\n alpha: Nullable<PBShaderExp>\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const geometryPass = this._geometryPass;\r\n // Alpha travels as a parameter. Reaching into the caller's scope for its\r\n // `outColor` would be reading a local of a different shader function, and the\r\n // two cases that matter - an opaque caster and a fully transparent one - are\r\n // the same value there.\r\n const hasAlpha = geometryPass === 1 && !!alpha;\r\n const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}`;\r\n const params = hasAlpha ? [pb.vec3('worldPos'), pb.float('alpha')] : [pb.vec3('worldPos')];\r\n pb.func(funcName, params, function () {\r\n this.$l.depth = that.casterDepth(shadowMapParams, this, this.worldPos);\r\n if (geometryPass === 0) {\r\n this.$return(pb.vec4(this.depth, 0, 0, 1));\r\n } else {\r\n this.$l.z0 = pb.textureLoad(\r\n this[UNIFORM_NAME_DOM_FRONT_DEPTH],\r\n pb.ivec2(this.$builtins.fragCoord.xy),\r\n 0\r\n ).x;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n // Distance behind the frontmost strand, in layer-span units. A fragment at\r\n // or in front of z0 lands at zero and fills every layer.\r\n this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan);\r\n // Layer k's far boundary sits at (k+1)/3 of the span, and a fragment\r\n // contributes to every layer whose boundary lies behind it. The last\r\n // layer has no far boundary: it extends to the end of the caster volume,\r\n // so a fragment deeper than the span still lands in it and the third\r\n // layer holds the cumulative absorption of *everything* behind z0.\r\n // Dropping deep fragments instead - step(t, 1) - deletes the hair behind\r\n // the front slice from the map entirely, and any receiver deeper than\r\n // the span reads only that slice: wherever it happens to be sparse, the\r\n // middle of a dense backlit groom comes out fully lit in blotches.\r\n this.$l.mask = pb.vec3(pb.step(this.t, 1 / 3), pb.step(this.t, 2 / 3), 1);\r\n // A caster that computes no fragment colour covers fully.\r\n this.$l.casterAlpha = hasAlpha ? this.alpha : pb.float(1);\r\n // Optical depth rather than raw coverage, because what has to be additive\r\n // here is the exponent, not the alpha. Compositing N layers multiplies\r\n // their transmittances - prod(1 - a) - and blending can only sum, so each\r\n // fragment contributes -log(1 - a) and the receiver's exp(-sum) reproduces\r\n // that product exactly.\r\n //\r\n // Summing alpha instead makes exp(-sum) an approximation that only holds\r\n // while alpha is small, which is true of a sub-pixel strand and false of\r\n // anything solid: a single opaque caster would sum to 1 and shadow to\r\n // exp(-1), a 37% grey rather than black.\r\n //\r\n // The floor bounds what alpha = 1 encodes. It has to be finite to blend,\r\n // and 0.001 transmittance is already black; it also leaves room for\r\n // several opaque layers to stack without leaving half precision.\r\n this.$l.opticalDepth = pb.neg(pb.log(pb.max(pb.sub(1, this.casterAlpha), DOM_MIN_TRANSMITTANCE)));\r\n this.$return(pb.vec4(pb.mul(this.mask, this.opticalDepth), this.z0));\r\n }\r\n });\r\n const global = pb.getGlobalScope();\r\n return (hasAlpha ? global[funcName](worldPos, alpha!) : global[funcName](worldPos)) as PBShaderExp;\r\n }\r\n /**\r\n * Normalized light-space depth of a caster fragment, in the encoding the\r\n * receiver reconstructs.\r\n * @internal\r\n */\r\n private casterDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n if (shadowMapParams.lightType === LIGHT_TYPE_POINT) {\r\n const lightSpacePos = pb.mul(ShaderHelper.getLightViewMatrixForShadow(scope), pb.vec4(worldPos, 1));\r\n return pb.clamp(\r\n pb.div(pb.length(lightSpacePos.xyz), ShaderHelper.getLightPositionAndRangeForShadow(scope).w),\r\n 0,\r\n 1\r\n );\r\n }\r\n return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;\r\n }\r\n computeShadow(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp\r\n ) {\r\n const funcName = 'lib_computeShadowDOM';\r\n const pb = scope.$builder;\r\n const that = this;\r\n pb.func(funcName, [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.shadowCoord = pb.div(this.shadowVertex.xyz, this.shadowVertex.w);\r\n this.$l.shadowCoord = ndcToShadowCoord3(this, this.shadowCoord.xyz);\r\n this.$l.inRange = pb.all(\r\n pb.bvec2(\r\n pb.all(\r\n pb.bvec4(\r\n pb.greaterThanEqual(this.shadowCoord.x, 0),\r\n pb.lessThanEqual(this.shadowCoord.x, 1),\r\n pb.greaterThanEqual(this.shadowCoord.y, 0),\r\n pb.lessThanEqual(this.shadowCoord.y, 1)\r\n )\r\n ),\r\n shadowCoordDepthInRange(this, this.shadowCoord.z)\r\n )\r\n );\r\n this.$l.shadow = pb.float(1);\r\n this.$if(this.inRange, function () {\r\n // A single tap needs no bias: it reads the texel the receiver itself\r\n // wrote, so its own surface sits exactly at z0 and contributes nothing.\r\n // A kernel breaks that. Neighbouring texels record the frontmost surface\r\n // at their own position, which on anything sloped is nearer the light\r\n // than the receiver, and the receiver then reads itself as being behind a\r\n // caster. On a solid surface that is the full jump from no absorption to\r\n // all of it, so it shows up as the banding an unbiased shadow map has.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(\r\n shadowMapParams.lightType,\r\n this,\r\n this.shadowCoord.z,\r\n this.NdotL,\r\n false\r\n );\r\n this.shadowCoord.z = applyShadowDepthBias(this, this.shadowCoord.z, this.bias, true);\r\n }\r\n this.shadow = that.transmittance(this, this.shadowCoord);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope()[funcName](shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n computeShadowCSM(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp,\r\n _split: PBShaderExp\r\n ) {\r\n // Cascades would need a depth and a layer set per split, which no longer fits\r\n // the one texture the single shadow-map binding allows. Callers keep working\r\n // by shadowing from the first cascade's map.\r\n return this.computeShadow(shadowMapParams, scope, shadowVertex, NdotL);\r\n }\r\n /**\r\n * Fraction of light surviving the hair in front of the receiver, averaged over\r\n * the filter kernel.\r\n *\r\n * @remarks\r\n * The averaging is over transmittance, one value per tap, rather than over the\r\n * stored texels. Blending the texels first would interpolate `z0` across the\r\n * silhouette of the groom, where one side holds a real strand depth and the\r\n * other the empty-texel sentinel, and the depth halfway between them describes\r\n * nothing - every layer reading taken against it would be measured from the\r\n * wrong origin. Averaging the results instead asks a well-posed question of\r\n * each texel and combines only the answers, which is also what makes this an\r\n * antialiased edge rather than a blurred one.\r\n * @internal\r\n */\r\n private transmittance(scope: PBInsideFunctionScope, shadowCoord: PBShaderExp): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittance_${size}`;\r\n pb.func(funcName, [pb.vec3('shadowCoord')], function () {\r\n if (size <= 1) {\r\n this.$return(that.tapTransmittance(this, this.shadowCoord.xy, this.shadowCoord.z));\r\n } else {\r\n // cameraParams.z carries the shadow map size, and this implementation\r\n // never splits into cascades, so the map is exactly that wide.\r\n this.$l.texelSize = pb.div(1, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapUV = pb.vec2();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapUV = pb.add(this.shadowCoord.xy, pb.mul(pb.vec2(x, y), this.texelSize));\r\n this.sum = pb.add(this.sum, that.tapTransmittance(this, this.tapUV, this.shadowCoord.z));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](shadowCoord) as PBShaderExp;\r\n }\r\n /**\r\n * Transmittance from a single shadow map texel.\r\n * @internal\r\n */\r\n private tapTransmittance(\r\n scope: PBInsideFunctionScope,\r\n uv: PBShaderExp,\r\n receiverDepth: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const funcName = 'lib_domTap';\r\n pb.func(funcName, [pb.vec2('uv'), pb.float('receiverDepth')], function () {\r\n this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.uv, 0);\r\n this.$l.layers = this.texel.rgb;\r\n this.$l.z0 = this.texel.a;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n this.$l.density = ShaderHelper.getShadowImplParams(this).y;\r\n this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan);\r\n // The layers are cumulative, so opacity at an arbitrary depth is a lerp\r\n // between the two bracketing layer values. Scaling t by the layer count puts\r\n // the integer part on the near layer and the fraction between the pair.\r\n this.$l.scaled = pb.clamp(pb.mul(this.t, DOM_LAYER_COUNT), 0, DOM_LAYER_COUNT);\r\n this.$l.index = pb.floor(this.scaled);\r\n this.$l.frac = pb.sub(this.scaled, this.index);\r\n // Nothing has been traversed before the first layer, so the near value at\r\n // index 0 is zero rather than layers.x.\r\n this.$l.near = pb.float(0);\r\n this.$l.far = this.layers.x;\r\n this.$if(pb.greaterThanEqual(this.index, 2), function () {\r\n this.near = this.layers.y;\r\n this.far = this.layers.z;\r\n }).$elseif(pb.greaterThanEqual(this.index, 1), function () {\r\n this.near = this.layers.x;\r\n this.far = this.layers.y;\r\n });\r\n // Optical depth is what accumulates linearly through a medium, so the lerp\r\n // between two layer readings is meaningful in a way that lerping stored\r\n // alphas would not have been.\r\n this.$l.absorption = pb.mix(this.near, this.far, this.frac);\r\n // Beer-Lambert. With the casters recording -log(1 - alpha) this is exactly\r\n // prod(1 - alpha) over everything crossed, so a solid caster reaches black\r\n // and a stack of thin strands reaches the same value alpha compositing them\r\n // would have.\r\n this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));\r\n });\r\n return pb.getGlobalScope()[funcName](uv, receiverDepth) as PBShaderExp;\r\n }\r\n}\r\n"],"names":["DOM_LAYER_COUNT","UNIFORM_NAME_DOM_FRONT_DEPTH","DOM_MIN_TRANSMITTANCE","DOM","ShadowImpl","layerDistance","density","filterSize","_layerDistance","_density","_filterSize","clampFilterSize","_paramsScratch","Vector4","_geometryPass","_depthRange","val","getType","resourceDirty","_resourceDirty","getShadowMapBorder","getDepthScale","setDepthScale","_val","getParams","out","result","setXYZW","getGeometryPassCount","supportsCascades","clipsCasterAlpha","beginGeometryPass","shadowMapParams","pass","implData","range","cameraParams","y","x","getDevice","setFramebuffer","depthFramebuffer","opacityFramebuffer","setCasterRenderStates","_shadowMapParams","stateSet","useBlendingState","enable","setBlendEquation","setBlendFuncRGB","setBlendFuncAlpha","useDepthState","enableTest","enableWrite","getShadowMapClearColor","REVERSE_Z","farthest","getShadowMapColorFormat","getShadowMapDepthFormat","preferredShadowMapDepthFormat","useNativeShadowMap","getShadowMap","caps","getDeviceCaps","textureCaps","supportFloatColorBuffer","supportFloatBlending","supportHalfFloatColorBuffer","doUpdateResources","device","sharedDepth","shadowMapFramebuffer","getDepthAttachment","width","height","format","colorFormat","frontDepth","pool","fetchTemporalTexture2D","createTemporalFramebuffer","releaseTexture","shadowMap","shadowMapSampler","getDefaultSampler","postRenderShadowMap","getShaderHash","declareCasterUniforms","scope","pb","$builder","tex","tex2D","sampleType","uniform","applyCasterUniforms","bindGroup","setTexture","fetchSampler","layerCoord","depth","z0","layerSpan","delta","sub","div","max","computeShadowMapDepth","worldPos","alpha","that","geometryPass","hasAlpha","funcName","params","vec3","float","func","$l","casterDepth","$return","vec4","textureLoad","ivec2","$builtins","fragCoord","xy","ShaderHelper","getShadowImplParams","t","mask","step","casterAlpha","opticalDepth","neg","log","mul","global","getGlobalScope","lightType","LIGHT_TYPE_POINT","lightSpacePos","getLightViewMatrixForShadow","clamp","length","xyz","getLightPositionAndRangeForShadow","w","emulateDepthClamp","$inputs","clamppedDepth","z","computeShadow","shadowVertex","NdotL","shadowCoord","ndcToShadowCoord3","inRange","all","bvec2","bvec4","greaterThanEqual","lessThanEqual","shadowCoordDepthInRange","shadow","$if","bias","computeShadowBias","applyShadowDepthBias","transmittance","computeShadowCSM","_split","size","tapTransmittance","texelSize","getShadowCameraParams","sum","tapUV","vec2","radius","add","uv","receiverDepth","texel","textureSampleLevel","layers","rgb","a","scaled","index","floor","frac","near","far","$elseif","absorption","mix","exp"],"mappings":"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"}
1
+ {"version":3,"file":"dom.js","sources":["../../src/shadow/dom.ts"],"sourcesContent":["import type {\r\n BindGroup,\r\n FrameBuffer,\r\n PBGlobalScope,\r\n PBInsideFunctionScope,\r\n PBShaderExp,\r\n RenderStateSet,\r\n Texture2D,\r\n TextureCube,\r\n TextureFormat\r\n} from '@zephyr3d/device';\r\nimport { ShadowImpl } from './shadow_impl';\r\nimport type { ShadowMapParams, ShadowMapType } from './shadowmapper';\r\nimport { LIGHT_TYPE_POINT } from '../values';\r\nimport { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow';\r\nimport { computeShadowBias } from './shader';\r\nimport { ShaderHelper } from '../material/shader/helper';\r\nimport { getDevice } from '../app/api';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport { CubeFace, REVERSE_Z, Vector4, type Nullable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Opacity layers, which is three rather than four because the fourth channel of\r\n * the result texture carries the depth the layers are measured from. Keeping\r\n * both in one texture is what lets the receiver read the whole technique through\r\n * the single shadow-map binding the lighting shaders declare.\r\n * @internal\r\n */\r\nconst DOM_LAYER_COUNT = 3;\r\n\r\n/** @internal Caster-pass uniform holding the frontmost depth from geometry pass 0. */\r\nconst UNIFORM_NAME_DOM_FRONT_DEPTH = 'Z_domFrontDepth';\r\n\r\n/**\r\n * Transmittance a fully opaque caster is recorded as, since zero has no finite\r\n * optical depth to blend. Dark enough to read as black, and small enough in the\r\n * exponent that several opaque layers can stack without saturating half floats.\r\n * @internal\r\n */\r\nconst DOM_MIN_TRANSMITTANCE = 0.001;\r\n\r\n/** @internal */\r\ntype DOMImplData = {\r\n /**\r\n * Frontmost caster depth, written by geometry pass 0 and sampled by pass 1.\r\n * Separate from the result texture on purpose: a texture cannot be a render\r\n * target and a sampled resource in the same pass.\r\n *\r\n * 2D even for a cube map: the shadow mapper draws both passes of one face\r\n * before moving to the next, so one face's worth is all pass 1 ever reads.\r\n */\r\n frontDepth: Texture2D;\r\n /**\r\n * RGB = cumulative optical depth per layer, A = the depth those layers start\r\n * at. A cube for point-projection lights (point and rect).\r\n */\r\n result: Texture2D | TextureCube;\r\n /** Targets {@link DOMImplData.frontDepth}, reusing the shared depth attachment. */\r\n depthFramebuffer: FrameBuffer;\r\n /** Targets {@link DOMImplData.result}. No depth attachment - pass 1 does not test. */\r\n opacityFramebuffer: FrameBuffer;\r\n};\r\n\r\n/**\r\n * Deep opacity map shadows.\r\n *\r\n * @remarks\r\n * Hair is the case an ordinary shadow map cannot express. A shadow map answers\r\n * \"is this point behind the nearest caster\", which is the right question for a\r\n * wall and the wrong one for ten thousand strands: light entering a groom is not\r\n * blocked at its surface, it is attenuated gradually as it passes more and more\r\n * fibres. A binary test renders that as a hard edge with everything behind it\r\n * uniformly black.\r\n *\r\n * A deep opacity map (Yuksel & Keyser 2008) records the attenuation instead of\r\n * the boundary. Geometry pass 0 writes the frontmost caster depth `z0` per texel.\r\n * Pass 1 rasterises the casters again and each fragment adds its optical depth to\r\n * every layer lying behind it, giving cumulative absorption sampled at three\r\n * depths measured *from `z0`* rather than from the light. Because the layers\r\n * follow the hair surface, three of them resolve what a plain opacity shadow map\r\n * needs dozens of uniformly spaced ones to match.\r\n *\r\n * Recording optical depth rather than coverage is what keeps it exact for solid\r\n * casters as well as thin ones, so a scene does not have to reserve this mode for\r\n * its hair: see the caster output for why the two differ.\r\n *\r\n * WebGPU only, and deliberately so: the strand geometry this exists to shadow is\r\n * itself WebGPU only, so supporting the WebGL fallbacks - cascade atlases instead\r\n * of array layers, RGBA8-packed depth instead of float - would double the surface\r\n * area to serve no material.\r\n *\r\n * @internal\r\n */\r\nexport class DOM extends ShadowImpl {\r\n /** @internal */\r\n private _layerDistance: number;\r\n /** @internal */\r\n private _density: number;\r\n /** @internal Width of the sampling kernel in texels; 1 disables filtering. */\r\n private _filterSize: number;\r\n /** @internal */\r\n private readonly _paramsScratch: Vector4;\r\n /**\r\n * @internal\r\n * Which geometry pass is being rasterised. Lives on the implementation rather\r\n * than in `implData` because {@link DOM.getShaderHash} has no access to the\r\n * params, and the hash must separate the two passes or they share a program.\r\n */\r\n private _geometryPass: number;\r\n /**\r\n * @internal\r\n * Depth the shadow camera spans, captured when the map is rendered. Needed to\r\n * express {@link DOM.layerDistance} in world units: the shader compares device\r\n * depths, and for the orthographic projection a directional light uses those\r\n * are the world depth divided by exactly this.\r\n */\r\n private _depthRange: number;\r\n constructor(layerDistance = 0.25, density = 1, filterSize = 5) {\r\n super();\r\n this._layerDistance = layerDistance;\r\n this._density = density;\r\n this._filterSize = DOM.clampFilterSize(filterSize);\r\n this._paramsScratch = new Vector4();\r\n this._geometryPass = 0;\r\n this._depthRange = 1;\r\n }\r\n /** @internal */\r\n private static clampFilterSize(val: number) {\r\n return val !== 1 && val !== 3 && val !== 5 && val !== 7 ? 5 : val;\r\n }\r\n /**\r\n * Width of the sampling kernel, in shadow map texels. One of 1, 3, 5 or 7.\r\n *\r\n * @remarks\r\n * The graded transmittance this technique records runs along the light, not\r\n * across the map, so at the silhouette of a groom - where the change is one of\r\n * coverage rather than of depth - a single tap is as abrupt as an unfiltered\r\n * shadow map. This is the kernel that softens that edge, and it is the same\r\n * knob PCF's kernel size is, with the difference that each tap here costs a\r\n * layer lookup rather than a depth comparison.\r\n *\r\n * Set to 1 to sample once, which is measurably cheaper and visibly harder.\r\n */\r\n get filterSize() {\r\n return this._filterSize;\r\n }\r\n set filterSize(val) {\r\n this._filterSize = DOM.clampFilterSize(val);\r\n }\r\n /**\r\n * Depth the layers span, in world units along the light direction.\r\n *\r\n * @remarks\r\n * Set it to roughly the thickness of the hair. Too small and everything past\r\n * the outer strands saturates the last layer, which is a hard shadow again;\r\n * too large and all three layers land inside the first strand, leaving the\r\n * interior unshadowed.\r\n *\r\n * Exact for directional lights, whose orthographic projection makes device\r\n * depth a linear function of world depth, and for point and rect lights,\r\n * whose cube maps store distance from the light. Spot lights project\r\n * perspectively, so there the value is only accurate near the middle of the\r\n * shadow camera's range - which is where hair lit by one usually sits.\r\n */\r\n get layerDistance() {\r\n return this._layerDistance;\r\n }\r\n set layerDistance(val) {\r\n this._layerDistance = val > 0 ? val : 0.0001;\r\n }\r\n /**\r\n * Artistic multiplier on the absorption the casters actually recorded.\r\n *\r\n * @remarks\r\n * One reproduces alpha compositing exactly and is the right default. Raise it\r\n * to deepen the interior of a groom without moving the layers, lower it to let\r\n * more light through than the geometry strictly would.\r\n */\r\n get density() {\r\n return this._density;\r\n }\r\n set density(val) {\r\n this._density = val < 0 ? 0 : val;\r\n }\r\n getType() {\r\n return 'dom' as const;\r\n }\r\n resourceDirty() {\r\n return this._resourceDirty;\r\n }\r\n getShadowMapBorder() {\r\n // Margin so the kernel's outer taps still land inside the map at the edges of\r\n // the shadow region, matching what the PCF implementations reserve.\r\n return this._filterSize;\r\n }\r\n getDepthScale() {\r\n return 1;\r\n }\r\n setDepthScale(_val: number) {}\r\n /**\r\n * Layer geometry and density, for both the caster and the receiver. `z` and\r\n * `w` are unused.\r\n *\r\n * @remarks\r\n * `x` is the layer span converted from world units into the device-depth\r\n * difference the shaders actually compare, using the range captured when the\r\n * map was rendered.\r\n */\r\n getParams(out?: Vector4) {\r\n const result = out ?? this._paramsScratch;\r\n result.setXYZW(this._layerDistance / this._depthRange, this._density, 0, 0);\r\n return result;\r\n }\r\n getGeometryPassCount() {\r\n return 2;\r\n }\r\n supportsCascades() {\r\n // Each split would need its own depth and layer set, and both already share\r\n // the one texture the receiver can bind.\r\n return false;\r\n }\r\n clipsCasterAlpha() {\r\n // Neither pass wants the clip. Pass 1 integrates the alpha, and clipping is\r\n // destructive to it in both of the forms the material applies: a dithered\r\n // caster survives with probability alpha and then contributes the absorption\r\n // of that same alpha, counting it twice, and a hard cutoff drops the sub-pixel\r\n // strands that carry most of a groom's transmittance.\r\n //\r\n // Pass 0 skips it for a different reason. Its job is to find the frontmost\r\n // strand, and under dithering the clip makes that choice per-pixel random -\r\n // the layers would then start at a depth that flickers between strands, and\r\n // every opacity reading behind it inherits the jitter.\r\n //\r\n // The case this gives up is a caster whose alpha is a real mask rather than a\r\n // coverage value, such as a hair card with cut-out texels: pass 0 will place\r\n // z0 on the card's surface even where it is fully transparent. Strand\r\n // geometry, which is what this technique is for, has no such texels.\r\n return false;\r\n }\r\n beginGeometryPass(shadowMapParams: ShadowMapParams, pass: number) {\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n this._geometryPass = pass;\r\n // The light camera is finalised by the time the casters are drawn, so this is\r\n // where the world-to-device depth scale becomes known. It stays valid for the\r\n // lighting pass that follows, which reads the same converted params back.\r\n // A cube map stores radial distance over the light's range instead, which is\r\n // what the layer span must then be measured against.\r\n const range = isCube(shadowMapParams)\r\n ? (shadowMapParams.depthRange ?? 1)\r\n : shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;\r\n this._depthRange = range > 1e-6 ? range : 1;\r\n if (isCube(shadowMapParams)) {\r\n // These framebuffers are this implementation's own, so the face the shadow\r\n // mapper selected on the shared one has to be selected on them too.\r\n const face = shadowMapParams.cubeFace ?? CubeFace.PX;\r\n if (pass === 0) {\r\n implData.depthFramebuffer.setDepthAttachmentCubeFace(face);\r\n } else {\r\n implData.opacityFramebuffer.setColorAttachmentCubeFace(0, face);\r\n }\r\n }\r\n getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);\r\n }\r\n setCasterRenderStates(_shadowMapParams: ShadowMapParams, stateSet: RenderStateSet) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n // Every strand between z0 and the last layer has to contribute, so the pass\r\n // must not depth-test against the frontmost surface pass 0 resolved, and must\r\n // not write depth of its own - its framebuffer has no depth attachment at all.\r\n // Optical depth sums across the three layer channels; alpha instead carries\r\n // z0, which every fragment reads from the same texel, so replacing is correct\r\n // where summing would multiply it by the number of overlapping strands.\r\n stateSet\r\n .useBlendingState()\r\n .enable(true)\r\n .setBlendEquation('add', 'add')\r\n .setBlendFuncRGB('one', 'one')\r\n .setBlendFuncAlpha('one', 'zero');\r\n stateSet.useDepthState().enableTest(false).enableWrite(false);\r\n }\r\n getShadowMapClearColor(shadowMapParams: ShadowMapParams) {\r\n // Radial distance in a cube map is linear, so reverse-Z does not flip it.\r\n const farthest = REVERSE_Z && !isCube(shadowMapParams) ? 0 : 1;\r\n if (this._geometryPass === 1) {\r\n // No hair over this texel means no absorption. Alpha carries z0, and the\r\n // sentinel makes an uncovered texel read as \"nothing in front\".\r\n return new Vector4(0, 0, 0, farthest);\r\n }\r\n return new Vector4(farthest, farthest, farthest, 1);\r\n }\r\n getShadowMapColorFormat(_shadowMapParams: ShadowMapParams) {\r\n // Null keeps the framebuffer the caller allocates depth-only. The colour this\r\n // technique needs is allocated here, against framebuffers of its own, so\r\n // letting the caller also allocate a full-size colour attachment would waste\r\n // it outright.\r\n return null;\r\n }\r\n getShadowMapDepthFormat(_shadowMapParams: ShadowMapParams) {\r\n return this.preferredShadowMapDepthFormat();\r\n }\r\n useNativeShadowMap(_shadowMapParams: ShadowMapParams) {\r\n // The receiver needs the actual stored values - a depth to measure offsets\r\n // from and three sums to interpolate - not the result of a hardware compare.\r\n return false;\r\n }\r\n getShadowMap(shadowMapParams: ShadowMapParams) {\r\n return (shadowMapParams.implData as DOMImplData).result as ShadowMapType;\r\n }\r\n /**\r\n * Format for both targets.\r\n *\r\n * @remarks\r\n * Full float wherever the accumulation pass can blend into it, and the reason\r\n * is the anchor depth, not the absorption sums. `z0` is stored absolute, in\r\n * units of the shadow camera's whole depth range, and every layer coordinate\r\n * on both sides of the technique is a difference against it divided by the\r\n * layer span. At half precision its quantisation step is about 2^-11 of the\r\n * stored value - roughly `0.0005 * depthRange` in world units - which for a\r\n * shadow camera spanning a large scene is comparable to the depth of the hair\r\n * itself. The error is independent per texel, so it does not read as bias but\r\n * as blotches: patches of a backlit groom whose receivers land in front of\r\n * their quantised `z0` and come out fully lit. A layer span large enough to\r\n * drown the noise hides it, but throws away the graded falloff the technique\r\n * exists for.\r\n *\r\n * Half float remains the fallback for devices whose blending cannot target\r\n * full float; there the practical mitigation is a tight shadow distance.\r\n * @internal\r\n */\r\n private colorFormat(): TextureFormat {\r\n const caps = getDevice().getDeviceCaps().textureCaps;\r\n if (caps.supportFloatColorBuffer && caps.supportFloatBlending) {\r\n return 'rgba32f';\r\n }\r\n return caps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba32f';\r\n }\r\n doUpdateResources(shadowMapParams: ShadowMapParams) {\r\n const device = getDevice();\r\n const sharedDepth = shadowMapParams.shadowMapFramebuffer!.getDepthAttachment()!;\r\n const width = sharedDepth.width;\r\n const height = sharedDepth.height;\r\n const format = this.colorFormat();\r\n // Everything here is pooled, per frame, the way the blur targets of VSM and\r\n // ESM are. `implData` cannot cache across frames even though it looks like it\r\n // could: it lives on a ShadowMapParams that is recycled between every light\r\n // and cleared at the end of each frame, so holding directly-created textures\r\n // in it leaks them at whatever rate the scene renders.\r\n const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n const result = isCube(shadowMapParams)\r\n ? device.pool.fetchTemporalTextureCube(false, format, width, false)\r\n : device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n // Pass 0 borrows the shadow map's own depth attachment, which is otherwise\r\n // unused - this implementation asks for no colour there - so the hardware\r\n // depth test resolves the frontmost strand for it. Pass 1 gets no depth,\r\n // which is both what stops it testing and what frees `frontDepth` to be\r\n // sampled while `result` is written.\r\n const depthFramebuffer = device.pool.createTemporalFramebuffer(true, [frontDepth], sharedDepth);\r\n const opacityFramebuffer = device.pool.createTemporalFramebuffer(true, [result], null);\r\n // The framebuffers hold the references now; these drop the fetch counts so\r\n // both textures return to the pool when the frame ends.\r\n device.pool.releaseTexture(frontDepth);\r\n device.pool.releaseTexture(result);\r\n shadowMapParams.implData = {\r\n frontDepth,\r\n result,\r\n depthFramebuffer,\r\n opacityFramebuffer\r\n } satisfies DOMImplData;\r\n shadowMapParams.shadowMap = result;\r\n shadowMapParams.shadowMapSampler = result.getDefaultSampler(false);\r\n this._resourceDirty = false;\r\n }\r\n postRenderShadowMap(_shadowMapParams: ShadowMapParams) {}\r\n getShaderHash() {\r\n // The two geometry passes emit different caster fragments and the shadow pass\r\n // keys its programs on this hash, so the pass index has to appear in it. The\r\n // kernel is unrolled into the receiver, so it belongs here too.\r\n return `${DOM_LAYER_COUNT}_${this._geometryPass}_${this._filterSize}`;\r\n }\r\n declareCasterUniforms(scope: PBGlobalScope, _shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const pb = scope.$builder;\r\n // sampleType before uniform(), matching how the receiver's shadow map is\r\n // declared: the binding is created from the accumulated descriptor.\r\n const tex = pb.tex2D();\r\n tex.sampleType('unfilterable-float');\r\n scope[UNIFORM_NAME_DOM_FRONT_DEPTH] = tex.uniform(0);\r\n }\r\n applyCasterUniforms(bindGroup: BindGroup, shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n bindGroup.setTexture(\r\n UNIFORM_NAME_DOM_FRONT_DEPTH,\r\n implData.frontDepth,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n }\r\n /**\r\n * How far a depth lies behind the frontmost strand, in layer-span units.\r\n *\r\n * @remarks\r\n * Both callers measure \"deeper into the hair than z0\", but which direction that\r\n * is depends on the depth encoding: under reverse-Z a farther surface has the\r\n * *smaller* value, so the plain subtraction is negative for every fragment\r\n * behind the front and the clamp below flattens the whole technique to no\r\n * shadow at all.\r\n * @internal\r\n */\r\n private layerCoord(\r\n scope: PBInsideFunctionScope,\r\n depth: PBShaderExp,\r\n z0: PBShaderExp,\r\n layerSpan: PBShaderExp,\r\n radial: boolean\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n // A cube map's radial distance grows away from the light whatever the depth\r\n // convention.\r\n const delta = REVERSE_Z && !radial ? pb.sub(z0, depth) : pb.sub(depth, z0);\r\n return pb.div(pb.max(delta, 0), layerSpan);\r\n }\r\n /**\r\n * Caster output.\r\n *\r\n * Pass 0 writes the frontmost depth. Pass 1 writes this fragment's optical depth\r\n * into the layers behind it, for additive blending to sum, and carries z0\r\n * through alpha so the receiver can find where the layers start.\r\n */\r\n computeShadowMapDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp,\r\n alpha: Nullable<PBShaderExp>\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const geometryPass = this._geometryPass;\r\n // Alpha travels as a parameter. Reaching into the caller's scope for its\r\n // `outColor` would be reading a local of a different shader function, and the\r\n // two cases that matter - an opaque caster and a fully transparent one - are\r\n // the same value there.\r\n const hasAlpha = geometryPass === 1 && !!alpha;\r\n const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}${isCube(shadowMapParams) ? '_c' : ''}`;\r\n const params = hasAlpha ? [pb.vec3('worldPos'), pb.float('alpha')] : [pb.vec3('worldPos')];\r\n pb.func(funcName, params, function () {\r\n this.$l.depth = that.casterDepth(shadowMapParams, this, this.worldPos);\r\n if (geometryPass === 0) {\r\n this.$return(pb.vec4(this.depth, 0, 0, 1));\r\n } else {\r\n this.$l.z0 = pb.textureLoad(\r\n this[UNIFORM_NAME_DOM_FRONT_DEPTH],\r\n pb.ivec2(this.$builtins.fragCoord.xy),\r\n 0\r\n ).x;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n // Distance behind the frontmost strand, in layer-span units. A fragment at\r\n // or in front of z0 lands at zero and fills every layer.\r\n this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan, isCube(shadowMapParams));\r\n // Layer k's far boundary sits at (k+1)/3 of the span, and a fragment\r\n // contributes to every layer whose boundary lies behind it. The last\r\n // layer has no far boundary: it extends to the end of the caster volume,\r\n // so a fragment deeper than the span still lands in it and the third\r\n // layer holds the cumulative absorption of *everything* behind z0.\r\n // Dropping deep fragments instead - step(t, 1) - deletes the hair behind\r\n // the front slice from the map entirely, and any receiver deeper than\r\n // the span reads only that slice: wherever it happens to be sparse, the\r\n // middle of a dense backlit groom comes out fully lit in blotches.\r\n this.$l.mask = pb.vec3(pb.step(this.t, 1 / 3), pb.step(this.t, 2 / 3), 1);\r\n // A caster that computes no fragment colour covers fully.\r\n this.$l.casterAlpha = hasAlpha ? this.alpha : pb.float(1);\r\n // Optical depth rather than raw coverage, because what has to be additive\r\n // here is the exponent, not the alpha. Compositing N layers multiplies\r\n // their transmittances - prod(1 - a) - and blending can only sum, so each\r\n // fragment contributes -log(1 - a) and the receiver's exp(-sum) reproduces\r\n // that product exactly.\r\n //\r\n // Summing alpha instead makes exp(-sum) an approximation that only holds\r\n // while alpha is small, which is true of a sub-pixel strand and false of\r\n // anything solid: a single opaque caster would sum to 1 and shadow to\r\n // exp(-1), a 37% grey rather than black.\r\n //\r\n // The floor bounds what alpha = 1 encodes. It has to be finite to blend,\r\n // and 0.001 transmittance is already black; it also leaves room for\r\n // several opaque layers to stack without leaving half precision.\r\n this.$l.opticalDepth = pb.neg(pb.log(pb.max(pb.sub(1, this.casterAlpha), DOM_MIN_TRANSMITTANCE)));\r\n this.$return(pb.vec4(pb.mul(this.mask, this.opticalDepth), this.z0));\r\n }\r\n });\r\n const global = pb.getGlobalScope();\r\n return (hasAlpha ? global[funcName](worldPos, alpha!) : global[funcName](worldPos)) as PBShaderExp;\r\n }\r\n /**\r\n * Normalized light-space depth of a caster fragment, in the encoding the\r\n * receiver reconstructs.\r\n * @internal\r\n */\r\n private casterDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n if (shadowMapParams.lightType === LIGHT_TYPE_POINT) {\r\n const lightSpacePos = pb.mul(ShaderHelper.getLightViewMatrixForShadow(scope), pb.vec4(worldPos, 1));\r\n return pb.clamp(\r\n pb.div(pb.length(lightSpacePos.xyz), ShaderHelper.getLightPositionAndRangeForShadow(scope).w),\r\n 0,\r\n 1\r\n );\r\n }\r\n return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;\r\n }\r\n computeShadow(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n if (isCube(shadowMapParams)) {\r\n // The shadow matrix is the identity for a cube map, so the \"shadow vertex\"\r\n // is the receiver's world position; its depth is the radial distance the\r\n // casters stored, over the same range.\r\n pb.func('lib_computeShadowDOMCube', [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.posRange = ShaderHelper.getLightPositionAndRangeForShadow(this);\r\n this.$l.dir = pb.sub(this.shadowVertex.xyz, this.posRange.xyz);\r\n this.$l.depth = pb.div(pb.length(this.dir), this.posRange.w);\r\n this.$l.shadow = pb.float(1);\r\n this.$if(pb.lessThanEqual(this.depth, 1), function () {\r\n // The kernel needs the bias for the same reason as the 2D map below.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(shadowMapParams.lightType, this, this.depth, this.NdotL, true);\r\n this.depth = applyShadowDepthBias(this, this.depth, this.bias, false);\r\n }\r\n this.shadow = that.transmittanceCube(this, this.dir, this.depth);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope().lib_computeShadowDOMCube(shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n const funcName = 'lib_computeShadowDOM';\r\n pb.func(funcName, [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.shadowCoord = pb.div(this.shadowVertex.xyz, this.shadowVertex.w);\r\n this.$l.shadowCoord = ndcToShadowCoord3(this, this.shadowCoord.xyz);\r\n this.$l.inRange = pb.all(\r\n pb.bvec2(\r\n pb.all(\r\n pb.bvec4(\r\n pb.greaterThanEqual(this.shadowCoord.x, 0),\r\n pb.lessThanEqual(this.shadowCoord.x, 1),\r\n pb.greaterThanEqual(this.shadowCoord.y, 0),\r\n pb.lessThanEqual(this.shadowCoord.y, 1)\r\n )\r\n ),\r\n shadowCoordDepthInRange(this, this.shadowCoord.z)\r\n )\r\n );\r\n this.$l.shadow = pb.float(1);\r\n this.$if(this.inRange, function () {\r\n // A single tap needs no bias: it reads the texel the receiver itself\r\n // wrote, so its own surface sits exactly at z0 and contributes nothing.\r\n // A kernel breaks that. Neighbouring texels record the frontmost surface\r\n // at their own position, which on anything sloped is nearer the light\r\n // than the receiver, and the receiver then reads itself as being behind a\r\n // caster. On a solid surface that is the full jump from no absorption to\r\n // all of it, so it shows up as the banding an unbiased shadow map has.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(\r\n shadowMapParams.lightType,\r\n this,\r\n this.shadowCoord.z,\r\n this.NdotL,\r\n false\r\n );\r\n this.shadowCoord.z = applyShadowDepthBias(this, this.shadowCoord.z, this.bias, true);\r\n }\r\n this.shadow = that.transmittance(this, this.shadowCoord);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope()[funcName](shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n computeShadowCSM(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp,\r\n _split: PBShaderExp\r\n ) {\r\n // Cascades would need a depth and a layer set per split, which no longer fits\r\n // the one texture the single shadow-map binding allows. Callers keep working\r\n // by shadowing from the first cascade's map.\r\n return this.computeShadow(shadowMapParams, scope, shadowVertex, NdotL);\r\n }\r\n /**\r\n * Fraction of light surviving the hair in front of the receiver, averaged over\r\n * the filter kernel.\r\n *\r\n * @remarks\r\n * The averaging is over transmittance, one value per tap, rather than over the\r\n * stored texels. Blending the texels first would interpolate `z0` across the\r\n * silhouette of the groom, where one side holds a real strand depth and the\r\n * other the empty-texel sentinel, and the depth halfway between them describes\r\n * nothing - every layer reading taken against it would be measured from the\r\n * wrong origin. Averaging the results instead asks a well-posed question of\r\n * each texel and combines only the answers, which is also what makes this an\r\n * antialiased edge rather than a blurred one.\r\n * @internal\r\n */\r\n private transmittance(scope: PBInsideFunctionScope, shadowCoord: PBShaderExp): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittance_${size}`;\r\n pb.func(funcName, [pb.vec3('shadowCoord')], function () {\r\n if (size <= 1) {\r\n this.$return(that.tapTransmittance(this, this.shadowCoord.xy, this.shadowCoord.z));\r\n } else {\r\n // cameraParams.z carries the shadow map size, and this implementation\r\n // never splits into cascades, so the map is exactly that wide.\r\n this.$l.texelSize = pb.div(1, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapUV = pb.vec2();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapUV = pb.add(this.shadowCoord.xy, pb.mul(pb.vec2(x, y), this.texelSize));\r\n this.sum = pb.add(this.sum, that.tapTransmittance(this, this.tapUV, this.shadowCoord.z));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](shadowCoord) as PBShaderExp;\r\n }\r\n /**\r\n * {@link DOM.transmittance} for a cube map: the same kernel, laid out on the\r\n * face around the receiver's direction.\r\n *\r\n * @remarks\r\n * The taps step one texel at a time on the unit cube, where a face texel spans\r\n * `2 / size`, in a plane perpendicular to the ray - which matches the face's\r\n * own grid at its centre and differs only to second order off it.\r\n * @internal\r\n */\r\n private transmittanceCube(scope: PBInsideFunctionScope, dir: PBShaderExp, receiverDepth: PBShaderExp) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittanceCube_${size}`;\r\n pb.func(funcName, [pb.vec3('dir'), pb.float('receiverDepth')], function () {\r\n if (size <= 1) {\r\n this.$return(that.layerTransmittance(this, this.dir, this.receiverDepth, true));\r\n } else {\r\n this.$l.unitDir = pb.normalize(this.dir);\r\n this.$l.onCube = pb.div(\r\n this.unitDir,\r\n pb.max(pb.max(pb.abs(this.unitDir.x), pb.abs(this.unitDir.y)), pb.abs(this.unitDir.z))\r\n );\r\n this.$l.helper = this.$choice(\r\n pb.lessThan(pb.abs(this.unitDir.y), 0.99),\r\n pb.vec3(0, 1, 0),\r\n pb.vec3(1, 0, 0)\r\n );\r\n this.$l.side = pb.normalize(pb.cross(this.helper, this.unitDir));\r\n this.$l.up = pb.cross(this.unitDir, this.side);\r\n this.$l.texelSize = pb.div(2, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapDir = pb.vec3();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapDir = pb.add(\r\n this.onCube,\r\n pb.mul(pb.add(pb.mul(this.side, x), pb.mul(this.up, y)), this.texelSize)\r\n );\r\n this.sum = pb.add(this.sum, that.layerTransmittance(this, this.tapDir, this.receiverDepth, true));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](dir, receiverDepth) as PBShaderExp;\r\n }\r\n /**\r\n * Transmittance from a single shadow map texel.\r\n * @internal\r\n */\r\n private tapTransmittance(\r\n scope: PBInsideFunctionScope,\r\n uv: PBShaderExp,\r\n receiverDepth: PBShaderExp\r\n ): PBShaderExp {\r\n return this.layerTransmittance(scope, uv, receiverDepth, false);\r\n }\r\n /**\r\n * Transmittance from the texel at `coord` - a map UV, or for a cube map a\r\n * direction from the light.\r\n * @internal\r\n */\r\n private layerTransmittance(\r\n scope: PBInsideFunctionScope,\r\n coord: PBShaderExp,\r\n receiverDepth: PBShaderExp,\r\n radial: boolean\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const funcName = radial ? 'lib_domTapCube' : 'lib_domTap';\r\n pb.func(funcName, [radial ? pb.vec3('coord') : pb.vec2('coord'), pb.float('receiverDepth')], function () {\r\n this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.coord, 0);\r\n this.$l.layers = this.texel.rgb;\r\n this.$l.z0 = this.texel.a;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n this.$l.density = ShaderHelper.getShadowImplParams(this).y;\r\n this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan, radial);\r\n // The layers are cumulative, so opacity at an arbitrary depth is a lerp\r\n // between the two bracketing layer values. Scaling t by the layer count puts\r\n // the integer part on the near layer and the fraction between the pair.\r\n this.$l.scaled = pb.clamp(pb.mul(this.t, DOM_LAYER_COUNT), 0, DOM_LAYER_COUNT);\r\n this.$l.index = pb.floor(this.scaled);\r\n this.$l.frac = pb.sub(this.scaled, this.index);\r\n // Nothing has been traversed before the first layer, so the near value at\r\n // index 0 is zero rather than layers.x.\r\n this.$l.near = pb.float(0);\r\n this.$l.far = this.layers.x;\r\n this.$if(pb.greaterThanEqual(this.index, 2), function () {\r\n this.near = this.layers.y;\r\n this.far = this.layers.z;\r\n }).$elseif(pb.greaterThanEqual(this.index, 1), function () {\r\n this.near = this.layers.x;\r\n this.far = this.layers.y;\r\n });\r\n // Optical depth is what accumulates linearly through a medium, so the lerp\r\n // between two layer readings is meaningful in a way that lerping stored\r\n // alphas would not have been.\r\n this.$l.absorption = pb.mix(this.near, this.far, this.frac);\r\n // Beer-Lambert. With the casters recording -log(1 - alpha) this is exactly\r\n // prod(1 - alpha) over everything crossed, so a solid caster reaches black\r\n // and a stack of thin strands reaches the same value alpha compositing them\r\n // would have.\r\n this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));\r\n });\r\n return pb.getGlobalScope()[funcName](coord, receiverDepth) as PBShaderExp;\r\n }\r\n}\r\n\r\n/** Whether the map is a point-projection cube (point and rect lights). @internal */\r\nfunction isCube(shadowMapParams: ShadowMapParams) {\r\n return shadowMapParams.lightType === LIGHT_TYPE_POINT;\r\n}\r\n"],"names":["DOM_LAYER_COUNT","UNIFORM_NAME_DOM_FRONT_DEPTH","DOM_MIN_TRANSMITTANCE","DOM","ShadowImpl","layerDistance","density","filterSize","_layerDistance","_density","_filterSize","clampFilterSize","_paramsScratch","Vector4","_geometryPass","_depthRange","val","getType","resourceDirty","_resourceDirty","getShadowMapBorder","getDepthScale","setDepthScale","_val","getParams","out","result","setXYZW","getGeometryPassCount","supportsCascades","clipsCasterAlpha","beginGeometryPass","shadowMapParams","pass","implData","range","isCube","depthRange","cameraParams","y","x","face","cubeFace","CubeFace","PX","depthFramebuffer","setDepthAttachmentCubeFace","opacityFramebuffer","setColorAttachmentCubeFace","getDevice","setFramebuffer","setCasterRenderStates","_shadowMapParams","stateSet","useBlendingState","enable","setBlendEquation","setBlendFuncRGB","setBlendFuncAlpha","useDepthState","enableTest","enableWrite","getShadowMapClearColor","farthest","REVERSE_Z","getShadowMapColorFormat","getShadowMapDepthFormat","preferredShadowMapDepthFormat","useNativeShadowMap","getShadowMap","caps","getDeviceCaps","textureCaps","supportFloatColorBuffer","supportFloatBlending","supportHalfFloatColorBuffer","doUpdateResources","device","sharedDepth","shadowMapFramebuffer","getDepthAttachment","width","height","format","colorFormat","frontDepth","pool","fetchTemporalTexture2D","fetchTemporalTextureCube","createTemporalFramebuffer","releaseTexture","shadowMap","shadowMapSampler","getDefaultSampler","postRenderShadowMap","getShaderHash","declareCasterUniforms","scope","pb","$builder","tex","tex2D","sampleType","uniform","applyCasterUniforms","bindGroup","setTexture","fetchSampler","layerCoord","depth","z0","layerSpan","radial","delta","sub","div","max","computeShadowMapDepth","worldPos","alpha","that","geometryPass","hasAlpha","funcName","params","vec3","float","func","$l","casterDepth","$return","vec4","textureLoad","ivec2","$builtins","fragCoord","xy","ShaderHelper","getShadowImplParams","t","mask","step","casterAlpha","opticalDepth","neg","log","mul","global","getGlobalScope","lightType","LIGHT_TYPE_POINT","lightSpacePos","getLightViewMatrixForShadow","clamp","length","xyz","getLightPositionAndRangeForShadow","w","emulateDepthClamp","$inputs","clamppedDepth","z","computeShadow","shadowVertex","NdotL","posRange","dir","shadow","$if","lessThanEqual","bias","computeShadowBias","applyShadowDepthBias","transmittanceCube","lib_computeShadowDOMCube","shadowCoord","ndcToShadowCoord3","inRange","all","bvec2","bvec4","greaterThanEqual","shadowCoordDepthInRange","transmittance","computeShadowCSM","_split","size","tapTransmittance","texelSize","getShadowCameraParams","sum","tapUV","vec2","radius","add","receiverDepth","layerTransmittance","unitDir","normalize","onCube","abs","helper","$choice","lessThan","side","cross","up","tapDir","uv","coord","texel","textureSampleLevel","layers","rgb","a","scaled","index","floor","frac","near","far","$elseif","absorption","mix","exp"],"mappings":"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"}
@@ -204,7 +204,7 @@ class BlurBlitter extends GaussianBlurBlitter {
204
204
  }
205
205
  /** @internal */ fetchTemporalFramebuffer(autoRelease, lightType, numCascades, width, height, colorFormat, depthFormat, mipmapping) {
206
206
  const device = getDevice();
207
- const useTextureArray = numCascades > 1 && device.type !== 'webgl';
207
+ const useTextureArray = numCascades > 1;
208
208
  const colorAttachments = colorFormat ? useTextureArray ? [
209
209
  device.pool.fetchTemporalTexture2DArray(false, colorFormat, width, height, numCascades, mipmapping)
210
210
  ] : lightType === LIGHT_TYPE_POINT ? [
@@ -212,7 +212,7 @@ class BlurBlitter extends GaussianBlurBlitter {
212
212
  ] : [
213
213
  device.pool.fetchTemporalTexture2D(false, colorFormat, width, height, mipmapping)
214
214
  ] : null;
215
- const depthAttachment = depthFormat ? useTextureArray ? device.pool.fetchTemporalTexture2DArray(false, depthFormat, width, height, numCascades, false) : device.type !== 'webgl' && lightType === LIGHT_TYPE_POINT ? device.pool.fetchTemporalTextureCube(false, depthFormat, width, false) : device.pool.fetchTemporalTexture2D(false, depthFormat, width, height, false) : null;
215
+ const depthAttachment = depthFormat ? useTextureArray ? device.pool.fetchTemporalTexture2DArray(false, depthFormat, width, height, numCascades, false) : lightType === LIGHT_TYPE_POINT ? device.pool.fetchTemporalTextureCube(false, depthFormat, width, false) : device.pool.fetchTemporalTexture2D(false, depthFormat, width, height, false) : null;
216
216
  const fb = device.pool.createTemporalFramebuffer(autoRelease, colorAttachments, depthAttachment);
217
217
  if (colorAttachments) {
218
218
  device.pool.releaseTexture(colorAttachments[0]);
@@ -276,7 +276,7 @@ class BlurBlitter extends GaussianBlurBlitter {
276
276
  }
277
277
  getShadowMapColorFormat(_shadowMapParams) {
278
278
  const device = getDevice();
279
- return device.getDeviceCaps().textureCaps.supportFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearFloatTexture ? device.type === 'webgl' ? 'rgba32f' : 'rg32f' : device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? device.type === 'webgl' ? 'rgba16f' : 'rg16f' : 'rgba8unorm';
279
+ return device.getDeviceCaps().textureCaps.supportFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearFloatTexture ? 'rg32f' : device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rg16f' : 'rgba8unorm';
280
280
  }
281
281
  getShadowMapDepthFormat(_shadowMapParams) {
282
282
  return 'd24s8';