@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,6 +1,6 @@
1
1
  import { drawFullscreenQuad } from '../render/fullscreenquad.js';
2
2
  import { fetchSampler } from '../utility/misc.js';
3
- import { Matrix4x4, Vector3, Vector4 } from '@zephyr3d/base';
3
+ import { Vector3, Matrix4x4, Vector4 } from '@zephyr3d/base';
4
4
  import { uniformSphereSamples } from '../values.js';
5
5
  import { getDevice } from '../app/api.js';
6
6
 
@@ -17,7 +17,11 @@ const OZONE_ABSORPTION_SIGMA = [
17
17
  1.881,
18
18
  0.085
19
19
  ];
20
- /** @internal */ const CAMERA_POS_Y = 1;
20
+ /**
21
+ * Lowest observer altitude above the ground, in meters. Keeps the sky visible
22
+ * when the camera is at or below the virtual planet surface.
23
+ * @internal
24
+ */ const MIN_OBSERVER_ALTITUDE = 5;
21
25
  /** @internal */ function getDefaultAtmosphereParams() {
22
26
  return {
23
27
  plantRadius: 6360000,
@@ -27,12 +31,18 @@ const OZONE_ABSORPTION_SIGMA = [
27
31
  mieAnstropy: 0.8,
28
32
  ozoneCenter: 25000,
29
33
  ozoneWidth: 15000,
30
- apDistance: 4000,
34
+ groundAlbedo: new Vector3(0.401978, 0.401978, 0.401978),
35
+ apDistance: 96000,
36
+ apViewDistanceScale: 1,
37
+ apStartDepth: 100,
31
38
  cameraWorldMatrix: Matrix4x4.identity(),
32
39
  lightDir: new Vector3(1, 0, 0),
33
40
  lightColor: new Vector4(1, 1, 1, 10),
34
41
  cameraAspect: 1,
35
- cameraHeightScale: 1
42
+ cameraTanHalfFovy: 1,
43
+ cameraHeightScale: 1,
44
+ observerAltitude: MIN_OBSERVER_ALTITUDE,
45
+ skyViewReferential: Matrix4x4.identity()
36
46
  };
37
47
  }
38
48
  const defaultAtmosphereParams = getDefaultAtmosphereParams();
@@ -53,7 +63,9 @@ function checkParams(other) {
53
63
  ...defaultAtmosphereParams,
54
64
  lightDir: new Vector3(defaultAtmosphereParams.lightDir),
55
65
  lightColor: new Vector4(defaultAtmosphereParams.lightColor),
56
- cameraWorldMatrix: new Matrix4x4(defaultAtmosphereParams.cameraWorldMatrix)
66
+ groundAlbedo: new Vector3(defaultAtmosphereParams.groundAlbedo),
67
+ cameraWorldMatrix: new Matrix4x4(defaultAtmosphereParams.cameraWorldMatrix),
68
+ skyViewReferential: new Matrix4x4(defaultAtmosphereParams.skyViewReferential)
57
69
  };
58
70
  result.transmittance = true;
59
71
  result.multiScattering = true;
@@ -61,9 +73,13 @@ function checkParams(other) {
61
73
  result.aerialPerspective = true;
62
74
  } else {
63
75
  result.transmittance = currentAtmosphereParams.plantRadius !== other.plantRadius || currentAtmosphereParams.atmosphereHeight !== other.atmosphereHeight || currentAtmosphereParams.rayleighScatteringHeight !== other.rayleighScatteringHeight || currentAtmosphereParams.mieScatteringHeight !== other.mieScatteringHeight || currentAtmosphereParams.ozoneCenter !== other.ozoneCenter || currentAtmosphereParams.ozoneWidth !== other.ozoneWidth;
64
- result.multiScattering = result.transmittance || currentAtmosphereParams.mieAnstropy !== other.mieAnstropy;
65
- result.skyView = result.transmittance || result.multiScattering || currentAtmosphereParams.cameraHeightScale !== other.cameraHeightScale || !currentAtmosphereParams.lightDir.equalsTo(other.lightDir) || !currentAtmosphereParams.lightColor.equalsTo(other.lightColor) || !currentAtmosphereParams.cameraWorldMatrix.equalsTo(other.cameraWorldMatrix);
66
- result.aerialPerspective = result.transmittance || result.multiScattering || result.skyView || currentAtmosphereParams.apDistance !== other.apDistance || currentAtmosphereParams.cameraAspect !== other.cameraAspect;
76
+ // The multi-scattering LUT uses an isotropic phase and a unit light, so it depends on the
77
+ // medium only (see integralMultiScattering).
78
+ result.multiScattering = result.transmittance || !currentAtmosphereParams.groundAlbedo.equalsTo(other.groundAlbedo);
79
+ // The sky view LUT is a full lat-long sphere around the observer in its local frame: the camera
80
+ // orientation does not affect it, its altitude and the local light direction do.
81
+ result.skyView = result.transmittance || result.multiScattering || currentAtmosphereParams.mieAnstropy !== other.mieAnstropy || currentAtmosphereParams.observerAltitude !== other.observerAltitude || !currentAtmosphereParams.lightDir.equalsTo(other.lightDir) || !currentAtmosphereParams.lightColor.equalsTo(other.lightColor);
82
+ result.aerialPerspective = result.transmittance || result.multiScattering || result.skyView || currentAtmosphereParams.apDistance !== other.apDistance || currentAtmosphereParams.apViewDistanceScale !== other.apViewDistanceScale || currentAtmosphereParams.apStartDepth !== other.apStartDepth || currentAtmosphereParams.cameraAspect !== other.cameraAspect || currentAtmosphereParams.cameraTanHalfFovy !== other.cameraTanHalfFovy || !currentAtmosphereParams.cameraWorldMatrix.equalsTo(other.cameraWorldMatrix);
67
83
  }
68
84
  if (result.transmittance) {
69
85
  currentAtmosphereParams.plantRadius = other.plantRadius;
@@ -74,17 +90,21 @@ function checkParams(other) {
74
90
  currentAtmosphereParams.ozoneWidth = other.ozoneWidth;
75
91
  }
76
92
  if (result.multiScattering) {
77
- currentAtmosphereParams.mieAnstropy = other.mieAnstropy;
93
+ currentAtmosphereParams.groundAlbedo.set(other.groundAlbedo);
78
94
  }
79
95
  if (result.skyView) {
80
- currentAtmosphereParams.cameraHeightScale = other.cameraHeightScale;
96
+ currentAtmosphereParams.mieAnstropy = other.mieAnstropy;
97
+ currentAtmosphereParams.observerAltitude = other.observerAltitude;
81
98
  currentAtmosphereParams.lightDir.set(other.lightDir);
82
99
  currentAtmosphereParams.lightColor.set(other.lightColor);
83
- currentAtmosphereParams.cameraWorldMatrix.set(other.cameraWorldMatrix);
84
100
  }
85
101
  if (result.aerialPerspective) {
86
102
  currentAtmosphereParams.apDistance = other.apDistance;
103
+ currentAtmosphereParams.apViewDistanceScale = other.apViewDistanceScale;
104
+ currentAtmosphereParams.apStartDepth = other.apStartDepth;
87
105
  currentAtmosphereParams.cameraAspect = other.cameraAspect;
106
+ currentAtmosphereParams.cameraTanHalfFovy = other.cameraTanHalfFovy;
107
+ currentAtmosphereParams.cameraWorldMatrix.set(other.cameraWorldMatrix);
88
108
  }
89
109
  return result;
90
110
  }
@@ -99,20 +119,44 @@ function checkParams(other) {
99
119
  ], function() {
100
120
  this.$l.OS = pb.length(pb.sub(this.center, this.rayStart));
101
121
  this.$l.SH = pb.dot(pb.sub(this.center, this.rayStart), this.rayDir);
102
- this.$l.OH = pb.sqrt(pb.sub(pb.mul(this.OS, this.OS), pb.mul(this.SH, this.SH)));
103
- this.$l.PH = pb.sqrt(pb.sub(pb.mul(this.radius, this.radius), pb.mul(this.OH, this.OH)));
122
+ this.$l.OH = pb.sqrt(pb.max(pb.sub(pb.mul(this.OS, this.OS), pb.mul(this.SH, this.SH)), 0));
104
123
  this.$if(pb.greaterThan(this.OH, this.radius), function() {
105
124
  this.$return(pb.float(-1));
106
125
  });
126
+ this.$l.PH = pb.sqrt(pb.max(pb.sub(pb.mul(this.radius, this.radius), pb.mul(this.OH, this.OH)), 0));
107
127
  this.$l.t1 = pb.sub(this.SH, this.PH);
108
128
  this.$l.t2 = pb.add(this.SH, this.PH);
109
129
  this.$return(this.$choice(pb.lessThan(this.t1, 0), this.t2, this.t1));
110
130
  });
111
131
  return scope[funcName](f3Center, fRadius, f3RayStart, f3RayDir);
112
132
  }
113
- /** @internal */ function transmittanceToSky(scope, stParams, f3Pos, f3Dir, texLut) {
133
+ /**
134
+ * Far intersection of a ray with a sphere, -1 when missed. For a start inside the sphere this is
135
+ * where the ray leaves it: unlike {@link rayIntersectSphere} it cannot mistake a near root that float
136
+ * error nudged above 0 for the exit in IntegrateSingleScatteredLuminance).
137
+ * @internal
138
+ */ function rayIntersectSphereFar(scope, fRadius, f3RayStart, f3RayDir) {
114
139
  const pb = scope.$builder;
115
- const funcName = 'z_transmittanceToSky';
140
+ const funcName = 'z_rayIntersectSphereFar';
141
+ pb.func(funcName, [
142
+ pb.float('radius'),
143
+ pb.vec3('rayStart'),
144
+ pb.vec3('rayDir')
145
+ ], function() {
146
+ this.$l.OS = pb.length(this.rayStart);
147
+ this.$l.SH = pb.neg(pb.dot(this.rayStart, this.rayDir));
148
+ this.$l.OH = pb.sqrt(pb.max(pb.sub(pb.mul(this.OS, this.OS), pb.mul(this.SH, this.SH)), 0));
149
+ this.$if(pb.greaterThan(this.OH, this.radius), function() {
150
+ this.$return(pb.float(-1));
151
+ });
152
+ this.$l.PH = pb.sqrt(pb.max(pb.sub(pb.mul(this.radius, this.radius), pb.mul(this.OH, this.OH)), 0));
153
+ this.$return(pb.add(this.SH, this.PH));
154
+ });
155
+ return scope[funcName](fRadius, f3RayStart, f3RayDir);
156
+ }
157
+ /** @internal */ function transmittanceToSky(scope, stParams, f3Pos, f3Dir, texLut, planetShadow = true) {
158
+ const pb = scope.$builder;
159
+ const funcName = planetShadow ? 'z_transmittanceToSky' : 'z_transmittanceToSkyNoShadow';
116
160
  const Params = getAtmosphereParamsStruct(pb);
117
161
  pb.func(funcName, [
118
162
  Params('params'),
@@ -122,8 +166,27 @@ function checkParams(other) {
122
166
  this.$l.bottomRadius = this.params.plantRadius;
123
167
  this.$l.topRadius = pb.add(this.params.plantRadius, this.params.atmosphereHeight);
124
168
  this.$l.upVector = pb.normalize(this.p);
169
+ // Planet shadow. The LUT only parameterizes zenith..horizon: a direction below the horizon
170
+ // would clamp to the horizon texel and keep the sun lit after it has set. Test the planet
171
+ // analytically instead, from a point lifted 1m to stay clear of float error on the sphere
172
+ if (planetShadow) {
173
+ this.$l.tPlanet = rayIntersectSphere(this, pb.vec3(0), this.bottomRadius, pb.add(this.p, this.upVector), this.dir);
174
+ this.$if(pb.greaterThan(this.tPlanet, 0), function() {
175
+ this.$return(pb.vec3(0));
176
+ });
177
+ }
178
+ // Above the atmosphere the LUT has no entry: look it up from where the ray enters it.
179
+ this.$l.pos = this.p;
180
+ this.$if(pb.greaterThan(pb.length(this.p), this.topRadius), function() {
181
+ this.$l.tTop = rayIntersectSphere(this, pb.vec3(0), this.topRadius, this.p, this.dir);
182
+ this.$if(pb.lessThan(this.tTop, 0), function() {
183
+ this.$return(pb.vec3(1));
184
+ });
185
+ this.pos = pb.add(this.p, pb.mul(this.dir, this.tTop));
186
+ this.upVector = pb.normalize(this.pos);
187
+ });
125
188
  this.$l.cosTheta = pb.dot(this.upVector, this.dir);
126
- this.$l.r = pb.length(this.p);
189
+ this.$l.r = pb.min(pb.length(this.pos), this.topRadius);
127
190
  this.$l.uv = transmittanceLutToUV(this, this.bottomRadius, this.topRadius, this.cosTheta, this.r);
128
191
  this.$return(pb.textureSampleLevel(texLut, this.uv, 0).rgb);
129
192
  });
@@ -137,7 +200,7 @@ function checkParams(other) {
137
200
  pb.float('h')
138
201
  ], function() {
139
202
  this.$l.sigma = pb.mul(pb.vec3(RAYLEIGH_SIGMA[0], RAYLEIGH_SIGMA[1], RAYLEIGH_SIGMA[2]), 1e-6);
140
- this.$l.rho_h = pb.exp(pb.neg(pb.div(this.h, this.rayleighScatteringHeight)));
203
+ this.$l.rho_h = pb.exp(pb.neg(pb.div(pb.max(this.h, 0), this.rayleighScatteringHeight)));
141
204
  this.$return(pb.mul(this.sigma, this.rho_h));
142
205
  });
143
206
  return scope[funcName](fRayleighScatteringHeight, fH);
@@ -160,7 +223,7 @@ function checkParams(other) {
160
223
  pb.float('h')
161
224
  ], function() {
162
225
  this.$l.sigma = pb.mul(pb.vec3(MIE_SIGMA), 1e-6);
163
- this.$l.rho_h = pb.exp(pb.neg(pb.div(this.h, this.mieScatteringHeight)));
226
+ this.$l.rho_h = pb.exp(pb.neg(pb.div(pb.max(this.h, 0), this.mieScatteringHeight)));
164
227
  this.$return(pb.mul(this.sigma, this.rho_h));
165
228
  });
166
229
  return scope[funcName](fMieScatteringHeight, fH);
@@ -173,11 +236,8 @@ function checkParams(other) {
173
236
  pb.float('cosTheta')
174
237
  ], function() {
175
238
  this.$l.g2 = pb.mul(this.g, this.g);
176
- this.$l.a = 3 / (8 * Math.PI);
177
- this.$l.b = pb.div(pb.sub(1, this.g2), pb.add(2, this.g2));
178
- this.$l.c = pb.add(1, pb.mul(this.cosTheta, this.cosTheta));
179
- this.$l.d = pb.pow(pb.sub(pb.add(1, this.g2), pb.mul(this.g, this.cosTheta, 2)), 1.5);
180
- this.$return(pb.div(pb.mul(this.a, this.b, this.c), this.d));
239
+ this.$l.denom = pb.sub(pb.add(1, this.g2), pb.mul(this.g, this.cosTheta, 2));
240
+ this.$return(pb.div(pb.sub(1, this.g2), pb.mul(4 * Math.PI, this.denom, pb.sqrt(this.denom))));
181
241
  });
182
242
  return scope[funcName](fMieAnstropy, fCosTheta);
183
243
  }
@@ -189,7 +249,7 @@ function checkParams(other) {
189
249
  pb.float('h')
190
250
  ], function() {
191
251
  this.$l.sigma = pb.mul(pb.vec3(MIE_ABSORPTION_SIGMA), 1e-6);
192
- this.$l.rho_h = pb.exp(pb.neg(pb.div(this.h, this.mieScatteringHeight)));
252
+ this.$l.rho_h = pb.exp(pb.neg(pb.div(pb.max(this.h, 0), this.mieScatteringHeight)));
193
253
  this.$return(pb.mul(this.sigma, this.rho_h));
194
254
  });
195
255
  return scope[funcName](fMieScatteringHeight, fH);
@@ -208,10 +268,40 @@ function checkParams(other) {
208
268
  });
209
269
  return scope[funcName](fOzoneLevelCenterHeight, fOzoneLevelWidth, fH);
210
270
  }
211
- /** @internal */ function getSkyView(scope, stParams, f3EyePos, f3ViewDir, fMaxDis, texTransmittanceLut, texMultiScatteringLut, withGround = true) {
271
+ /**
272
+ * Sun light reflected by the virtual planet ground at `groundPos`, per unit illuminance: a Lambertian
273
+ * surface of albedo `groundAlbedo` lit through the atmosphere. Multiply by the throughput from the observer.
274
+ * @internal
275
+ */ function groundBounce(scope, stParams, f3GroundPos, f3LightDir, texTransmittanceLut) {
276
+ const pb = scope.$builder;
277
+ const Params = getAtmosphereParamsStruct(pb);
278
+ const funcName = 'z_groundBounce';
279
+ pb.func(funcName, [
280
+ Params('params'),
281
+ pb.vec3('groundPos'),
282
+ pb.vec3('lightDir')
283
+ ], function() {
284
+ this.$l.up = pb.normalize(this.groundPos);
285
+ this.$l.NdotL = pb.clamp(pb.dot(this.up, this.lightDir), 0, 1);
286
+ this.$l.transmittanceToLight = transmittanceToSky(this, this.params, this.groundPos, this.lightDir, texTransmittanceLut, false);
287
+ this.$return(pb.mul(this.transmittanceToLight, this.params.groundAlbedo, this.NdotL, 1 / Math.PI));
288
+ });
289
+ return scope[funcName](stParams, f3GroundPos, f3LightDir);
290
+ }
291
+ /**
292
+ * @internal
293
+ *
294
+ * Single scattering along a view ray, plus multiple scattering from the LUT.
295
+ *
296
+ * @param withGround - Stop the ray at the planet ground.
297
+ * @param groundLit - When the ray ends on the ground (not cut short by `maxDis`), add the sun light
298
+ * the ground reflects. Implies `withGround`.
299
+ * @param apScale - Scale the integrated segment lengths by `params.apViewDistanceScale`, for the
300
+ * aerial perspective. The medium is still sampled at the true positions.
301
+ */ function getSkyView(scope, stParams, f3EyePos, f3ViewDir, fMaxDis, texTransmittanceLut, texMultiScatteringLut, withGround = true, groundLit = false, apScale = false) {
212
302
  const pb = scope.$builder;
213
303
  const Params = getAtmosphereParamsStruct(pb);
214
- const funcName = 'z_getSkyView';
304
+ const funcName = `z_getSkyView${withGround ? '_G' : ''}${groundLit ? '_L' : ''}${apScale ? '_AP' : ''}`;
215
305
  pb.func(funcName, [
216
306
  Params('params'),
217
307
  pb.vec3('eyePos'),
@@ -220,37 +310,64 @@ function checkParams(other) {
220
310
  ], function() {
221
311
  const N_SAMPLE = 32;
222
312
  this.$l.color = pb.vec3(0);
223
- this.$l.dis = rayIntersectSphere(this, pb.vec3(0), pb.add(this.params.plantRadius, this.params.atmosphereHeight), this.eyePos, this.viewDir);
313
+ this.$l.topRadius = pb.add(this.params.plantRadius, this.params.atmosphereHeight);
314
+ this.$l.eye = this.eyePos;
315
+ this.$l.maxDistance = this.maxDis;
316
+ this.$l.dis = rayIntersectSphere(this, pb.vec3(0), this.topRadius, this.eye, this.viewDir);
224
317
  this.$if(pb.lessThan(this.dis, 0), function() {
225
- this.$return(pb.vec3(0));
318
+ this.$return(pb.vec4(0, 0, 0, 1));
319
+ });
320
+ this.$if(pb.greaterThan(pb.length(this.eye), this.topRadius), function() {
321
+ this.$l.tEnter = this.dis;
322
+ this.eye = pb.add(this.eye, pb.mul(this.viewDir, this.tEnter));
323
+ this.eye = pb.sub(this.eye, pb.normalize(this.eye));
324
+ this.$if(pb.greaterThanEqual(this.maxDistance, 0), function() {
325
+ this.maxDistance = pb.sub(this.maxDistance, this.tEnter);
326
+ this.$if(pb.lessThanEqual(this.maxDistance, 0), function() {
327
+ this.$return(pb.vec4(0, 0, 0, 1));
328
+ });
329
+ });
330
+ this.dis = pb.max(rayIntersectSphereFar(this, this.topRadius, this.eye, this.viewDir), 0);
226
331
  });
227
- if (withGround) {
228
- this.$l.d = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.eyePos, this.viewDir);
229
- this.$if(pb.greaterThan(this.d, 0), function() {
230
- this.dis = pb.min(this.dis, this.d);
332
+ this.$l.hitGround = pb.bool(false);
333
+ if (withGround || groundLit) {
334
+ this.$l.d = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.eye, this.viewDir);
335
+ this.$if(pb.and(pb.greaterThan(this.d, 0), pb.lessThanEqual(this.d, this.dis)), function() {
336
+ this.dis = this.d;
337
+ this.hitGround = pb.bool(true);
231
338
  });
232
339
  }
233
- this.$if(pb.greaterThanEqual(this.maxDis, 0), function() {
234
- this.dis = pb.min(this.dis, this.maxDis);
340
+ this.$if(pb.and(pb.greaterThanEqual(this.maxDistance, 0), pb.lessThan(this.maxDistance, this.dis)), function() {
341
+ this.dis = this.maxDistance;
342
+ this.hitGround = pb.bool(false);
235
343
  });
236
344
  this.$l.ds = pb.div(this.dis, N_SAMPLE);
237
- this.$l.p = pb.add(this.eyePos, pb.mul(this.viewDir, this.ds, 0.5));
345
+ this.$l.p = pb.add(this.eye, pb.mul(this.viewDir, this.ds, 0.5));
238
346
  this.$l.sunLuminance = pb.mul(this.params.lightColor.rgb, this.params.lightColor.a);
239
- this.$l.opticalDepth = pb.vec3(0);
347
+ this.$l.throughput = pb.vec3(1);
240
348
  this.$for(pb.int('i'), 0, N_SAMPLE, function() {
241
349
  this.$l.h = pb.sub(pb.length(this.p), this.params.plantRadius);
242
350
  this.$l.extinction = pb.add(rayleighCoefficient(this, this.params.rayleighScatteringHeight, this.h), mieCoefficient(this, this.params.mieScatteringHeight, this.h), ozoneAbsorption(this, this.params.ozoneCenter, this.params.ozoneWidth, this.h), mieAbsorption(this, this.params.mieScatteringHeight, this.h));
243
- this.opticalDepth = pb.add(this.opticalDepth, pb.mul(this.extinction, this.ds));
351
+ this.$l.sampleTransmittance = pb.exp(pb.neg(pb.mul(this.extinction, this.ds, apScale ? this.params.apViewDistanceScale : 1)));
244
352
  this.$l.t1 = transmittanceToSky(this, this.params, this.p, this.params.lightDir, texTransmittanceLut);
245
353
  this.$l.s = scattering(this, this.params, this.p, this.viewDir);
246
- this.$l.t2 = pb.exp(pb.neg(this.opticalDepth));
247
- this.$l.inScattering = pb.mul(this.t1, this.s, this.t2, this.ds, this.sunLuminance);
248
- this.color = pb.add(this.color, this.inScattering);
354
+ // Multi-scattering is diffuse light left after single scattering: not planet shadowed.
249
355
  this.$l.multiScattering = getMultiScattering(this, this.params, this.p, texMultiScatteringLut);
250
- this.color = pb.add(this.color, pb.mul(this.multiScattering, this.t2, this.ds, this.sunLuminance));
356
+ this.$l.S = pb.mul(pb.add(pb.mul(this.t1, this.s), this.multiScattering), this.sunLuminance);
357
+ // Integrate the source term analytically over the segment instead of weighting it by the
358
+ // transmittance to the segment end, which darkens long (horizon) steps.
359
+ this.$l.Sint = pb.div(pb.sub(this.S, pb.mul(this.S, this.sampleTransmittance)), pb.max(this.extinction, pb.vec3(1e-12)));
360
+ this.color = pb.add(this.color, pb.mul(this.throughput, this.Sint));
361
+ this.throughput = pb.mul(this.throughput, this.sampleTransmittance);
251
362
  this.p = pb.add(this.p, pb.mul(this.viewDir, this.ds));
252
363
  });
253
- this.$return(this.color);
364
+ if (groundLit) {
365
+ this.$if(this.hitGround, function() {
366
+ this.$l.groundPos = pb.add(this.eye, pb.mul(this.viewDir, this.dis));
367
+ this.color = pb.add(this.color, pb.mul(groundBounce(this, this.params, this.groundPos, this.params.lightDir, texTransmittanceLut), this.throughput, this.sunLuminance));
368
+ });
369
+ }
370
+ this.$return(pb.vec4(this.color, pb.dot(this.throughput, pb.vec3(1 / 3))));
254
371
  });
255
372
  return scope[funcName](stParams, f3EyePos, f3ViewDir, fMaxDis);
256
373
  }
@@ -283,35 +400,42 @@ function checkParams(other) {
283
400
  pb.vec3('samplePoint')
284
401
  ], function() {
285
402
  const uniformPhase = 1 / (4 * Math.PI);
286
- const sphereSolidAngle = 4 * Math.PI / N_DIRECTION;
287
403
  this.$l.G_2 = pb.vec3(0);
288
404
  this.$l.f_ms = pb.vec3(0);
289
405
  this.$for(pb.int('i'), 0, N_DIRECTION, function() {
290
406
  this.$l.viewDir = this.uniformSphereSamples.at(this.i).xyz;
291
407
  this.$l.dis = rayIntersectSphere(this, pb.vec3(0), pb.add(this.params.plantRadius, this.params.atmosphereHeight), this.samplePoint, this.viewDir);
292
408
  this.$l.d = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.samplePoint, this.viewDir);
293
- this.$if(pb.greaterThan(this.d, 0), function() {
294
- this.dis = pb.min(this.dis, this.d);
409
+ this.$l.hitGround = pb.and(pb.greaterThan(this.d, 0), pb.lessThanEqual(this.d, this.dis));
410
+ this.$if(this.hitGround, function() {
411
+ this.dis = this.d;
295
412
  });
296
413
  this.$l.ds = pb.div(this.dis, N_SAMPLE);
297
414
  this.$l.p = pb.add(this.samplePoint, pb.mul(this.viewDir, this.ds, 0.5));
298
- this.$l.opticalDepth = pb.vec3(0);
415
+ this.$l.throughput = pb.vec3(1);
299
416
  this.$for(pb.int('j'), 0, N_SAMPLE, function() {
300
417
  this.$l.h = pb.sub(pb.length(this.p), this.params.plantRadius);
301
418
  this.$l.sigma_s = pb.add(rayleighCoefficient(this, this.params.rayleighScatteringHeight, this.h), mieCoefficient(this, this.params.mieScatteringHeight, this.h));
302
419
  this.$l.sigma_a = pb.add(ozoneAbsorption(this, this.params.ozoneCenter, this.params.ozoneWidth, this.h), mieAbsorption(this, this.params.mieScatteringHeight, this.h));
303
420
  this.$l.sigma_t = pb.add(this.sigma_s, this.sigma_a);
304
- this.opticalDepth = pb.add(this.opticalDepth, pb.mul(this.sigma_t, this.ds));
421
+ this.$l.sampleTransmittance = pb.exp(pb.neg(pb.mul(this.sigma_t, this.ds)));
305
422
  this.$l.t1 = transmittanceToSky(this, this.params, this.p, this.lightDir, texTransmittanceLut);
306
- this.$l.s = scattering(this, this.params, this.p, this.viewDir);
307
- this.$l.t2 = pb.exp(pb.neg(this.opticalDepth));
308
- this.G_2 = pb.add(this.G_2, pb.mul(this.t1, this.s, this.t2, uniformPhase, this.ds));
309
- this.f_ms = pb.add(this.f_ms, pb.mul(this.t2, this.sigma_s, uniformPhase, this.ds));
423
+ this.$l.S = pb.mul(this.t1, this.sigma_s, uniformPhase);
424
+ this.$l.Sint = pb.div(pb.sub(this.S, pb.mul(this.S, this.sampleTransmittance)), pb.max(this.sigma_t, pb.vec3(1e-12)));
425
+ this.G_2 = pb.add(this.G_2, pb.mul(this.throughput, this.Sint));
426
+ this.f_ms = pb.add(this.f_ms, pb.mul(this.throughput, this.sigma_s, this.ds));
427
+ this.throughput = pb.mul(this.throughput, this.sampleTransmittance);
310
428
  this.p = pb.add(this.p, pb.mul(this.viewDir, this.ds));
311
429
  });
430
+ this.$if(this.hitGround, function() {
431
+ this.$l.groundPos = pb.add(this.samplePoint, pb.mul(this.viewDir, this.dis));
432
+ this.G_2 = pb.add(this.G_2, pb.mul(groundBounce(this, this.params, this.groundPos, this.lightDir, texTransmittanceLut), this.throughput));
433
+ });
312
434
  });
313
- this.G_2 = pb.mul(this.G_2, sphereSolidAngle);
314
- this.f_ms = pb.mul(this.f_ms, sphereSolidAngle);
435
+ // G_2: (4pi / N) * sum(L) is the illuminance, times the isotropic phase 1 / (4pi) gives the
436
+ // in-scattered luminance, i.e. the plain average over the N directions.
437
+ this.G_2 = pb.div(this.G_2, N_DIRECTION);
438
+ this.f_ms = pb.div(this.f_ms, N_DIRECTION);
315
439
  this.$return(pb.div(this.G_2, pb.sub(pb.vec3(1), this.f_ms)));
316
440
  });
317
441
  return scope[funcName](stParams, f3LightDir, f3SamplePoint);
@@ -371,7 +495,9 @@ function checkParams(other) {
371
495
  this.$l.H = pb.sqrt(pb.max(0, pb.sub(pb.mul(this.topRadius, this.topRadius), pb.mul(this.bottomRadius, this.bottomRadius))));
372
496
  this.$l.rho = pb.sqrt(pb.max(0, pb.sub(pb.mul(this.r, this.r), pb.mul(this.bottomRadius, this.bottomRadius))));
373
497
  this.$l.discriminant = pb.add(pb.mul(this.r, this.r, pb.sub(pb.mul(this.mu, this.mu), 1)), pb.mul(this.topRadius, this.topRadius));
374
- this.$l.d = pb.max(0, pb.sub(pb.sqrt(this.discriminant), pb.mul(this.mu, this.r)));
498
+ // r ~ topRadius (a ray entering from space) makes this top^2 - r^2 difference of two ~4e13 values,
499
+ // which float error can drive negative.
500
+ this.$l.d = pb.max(0, pb.sub(pb.sqrt(pb.max(this.discriminant, 0)), pb.mul(this.mu, this.r)));
375
501
  this.$l.d_min = pb.sub(this.topRadius, this.r);
376
502
  this.$l.d_max = pb.add(this.rho, this.H);
377
503
  this.$l.x_mu = pb.div(pb.sub(this.d, this.d_min), pb.sub(this.d_max, this.d_min));
@@ -380,33 +506,92 @@ function checkParams(other) {
380
506
  });
381
507
  return scope[funcName](fBottomRadius, fTopRadius, fMu, fR);
382
508
  }
383
- /** @internal */ function viewDirToUV(scope, f3ViewDir) {
509
+ /** @internal */ const SKY_VIEW_LUT_WIDTH = 256;
510
+ /** @internal */ const SKY_VIEW_LUT_HEIGHT = 128;
511
+ /**
512
+ * Zenith angle of the horizon, and the angle from the horizon down to the nadir, seen from the
513
+ * sky view LUT observer.
514
+ */ function skyViewHorizon(scope, stParams) {
384
515
  const pb = scope.$builder;
516
+ const Params = getAtmosphereParamsStruct(pb);
517
+ const funcName = 'z_skyViewHorizon';
518
+ pb.func(funcName, [
519
+ Params('params')
520
+ ], function() {
521
+ this.$l.altitude = this.params.observerAltitude;
522
+ this.$l.viewHeight = pb.add(this.params.plantRadius, this.altitude);
523
+ // sqrt(h^2 - R^2) written as sqrt(a * (2R + a)): at an altitude of meters against a radius of
524
+ // thousands of kilometers, h^2 - R^2 is pure fp32 cancellation.
525
+ this.$l.vHorizon = pb.sqrt(pb.mul(this.altitude, pb.add(pb.mul(this.params.plantRadius, 2), this.altitude)));
526
+ this.$l.beta = pb.acos(pb.clamp(pb.div(this.vHorizon, this.viewHeight), -1, 1));
527
+ this.$return(pb.vec2(pb.sub(Math.PI, this.beta), this.beta));
528
+ });
529
+ return scope[funcName](stParams);
530
+ }
531
+ /**
532
+ * Sky view LUT parameterization. Latitude is split at the observer's horizon, which lands exactly on v = 0.5, with texels concentrated towards it on both sides: a
533
+ * uniform latitude mapping interpolates the dark below-horizon texels into the sky just above it.
534
+ * v = 0 is the zenith.
535
+ *
536
+ * @internal
537
+ */ function viewDirToUV(scope, stParams, f3ViewDir) {
538
+ const pb = scope.$builder;
539
+ const Params = getAtmosphereParamsStruct(pb);
385
540
  const funcName = 'z_viewDirToUV';
386
541
  pb.func(funcName, [
542
+ Params('params'),
387
543
  pb.vec3('viewDir')
388
544
  ], function() {
389
- this.$l.uv = pb.vec2(pb.atan2(this.viewDir.z, this.viewDir.x), pb.asin(this.viewDir.y));
390
- this.uv = pb.div(this.uv, pb.vec2(2 * Math.PI, Math.PI));
391
- this.uv = pb.add(this.uv, pb.vec2(0.5));
392
- this.$return(this.uv);
545
+ this.$l.horizon = skyViewHorizon(this, this.params);
546
+ this.$l.zenithHorizonAngle = this.horizon.x;
547
+ this.$l.beta = this.horizon.y;
548
+ this.$l.viewZenithAngle = pb.acos(pb.clamp(this.viewDir.y, -1, 1));
549
+ this.$l.v = pb.float();
550
+ this.$if(pb.lessThan(this.viewZenithAngle, this.zenithHorizonAngle), function() {
551
+ this.$l.coord = pb.div(this.viewZenithAngle, this.zenithHorizonAngle);
552
+ this.v = pb.mul(pb.sub(1, pb.sqrt(pb.max(pb.sub(1, this.coord), 0))), 0.5);
553
+ }).$else(function() {
554
+ this.$l.coord = pb.div(pb.sub(this.viewZenithAngle, this.zenithHorizonAngle), this.beta);
555
+ this.v = pb.add(pb.mul(pb.sqrt(pb.max(this.coord, 0)), 0.5), 0.5);
556
+ });
557
+ this.$l.u = pb.add(pb.div(pb.atan2(this.viewDir.z, this.viewDir.x), 2 * Math.PI), 0.5);
558
+ // FromUnitToSubUvs: keep lookups inside the texel-center range.
559
+ this.$l.size = pb.vec2(SKY_VIEW_LUT_WIDTH, SKY_VIEW_LUT_HEIGHT);
560
+ this.$return(pb.mul(pb.add(pb.vec2(this.u, this.v), pb.div(pb.vec2(0.5), this.size)), pb.div(this.size, pb.add(this.size, pb.vec2(1)))));
393
561
  });
394
- return scope[funcName](f3ViewDir);
562
+ return scope[funcName](stParams, f3ViewDir);
395
563
  }
396
- /** @internal */ function uvToViewDir(scope, f2UV) {
564
+ /**
565
+ * Inverse of {@link viewDirToUV}.
566
+ *
567
+ * @internal
568
+ */ function uvToViewDir(scope, stParams, f2UV) {
397
569
  const pb = scope.$builder;
570
+ const Params = getAtmosphereParamsStruct(pb);
398
571
  const funcName = 'z_uvToViewDir';
399
572
  pb.func(funcName, [
573
+ Params('params'),
400
574
  pb.vec2('uv')
401
575
  ], function() {
402
- this.$l.theta = pb.mul(pb.sub(1, this.uv.y), Math.PI);
403
- this.$l.phi = pb.mul(pb.sub(pb.mul(this.uv.x, 2), 1), Math.PI);
404
- this.$l.x = pb.mul(pb.sin(this.theta), pb.cos(this.phi));
405
- this.$l.z = pb.mul(pb.sin(this.theta), pb.sin(this.phi));
406
- this.$l.y = pb.cos(this.theta);
407
- this.$return(pb.vec3(this.x, this.y, this.z));
576
+ // FromSubUvsToUnit
577
+ this.$l.size = pb.vec2(SKY_VIEW_LUT_WIDTH, SKY_VIEW_LUT_HEIGHT);
578
+ this.$l.unit = pb.mul(pb.sub(this.uv, pb.div(pb.vec2(0.5), this.size)), pb.div(this.size, pb.sub(this.size, pb.vec2(1))));
579
+ this.$l.horizon = skyViewHorizon(this, this.params);
580
+ this.$l.zenithHorizonAngle = this.horizon.x;
581
+ this.$l.beta = this.horizon.y;
582
+ this.$l.viewZenithAngle = pb.float();
583
+ this.$if(pb.lessThan(this.unit.y, 0.5), function() {
584
+ this.$l.coord = pb.sub(1, pb.mul(this.unit.y, 2));
585
+ this.viewZenithAngle = pb.mul(this.zenithHorizonAngle, pb.sub(1, pb.mul(this.coord, this.coord)));
586
+ }).$else(function() {
587
+ this.$l.coord = pb.sub(pb.mul(this.unit.y, 2), 1);
588
+ this.viewZenithAngle = pb.add(this.zenithHorizonAngle, pb.mul(this.beta, this.coord, this.coord));
589
+ });
590
+ this.$l.phi = pb.mul(pb.sub(pb.mul(this.unit.x, 2), 1), Math.PI);
591
+ this.$l.sinTheta = pb.sin(this.viewZenithAngle);
592
+ this.$return(pb.vec3(pb.mul(this.sinTheta, pb.cos(this.phi)), pb.cos(this.viewZenithAngle), pb.mul(this.sinTheta, pb.sin(this.phi))));
408
593
  });
409
- return scope[funcName](f2UV);
594
+ return scope[funcName](stParams, f2UV);
410
595
  }
411
596
  /** @internal */ function uvToTransmittanceLut(scope, f2UV, fBottomRadius, fTopRadius) {
412
597
  const pb = scope.$builder;
@@ -452,31 +637,80 @@ function sunBloom(scope, f3ViewDir, f3LightDir, f4LightColorAndIntensity, fSunSo
452
637
  });
453
638
  return scope[funcName](f3ViewDir, f3LightDir, f4LightColorAndIntensity, fSunSolidAngle);
454
639
  }
455
- /** @internal */ function skyBox(scope, stParams, f4SunColor, f3SkyBoxWorldPos, fSunSolidAngle, fIncludeSunDisk, texTransmittanceLut, texSkyViewLut) {
640
+ /**
641
+ * Default sun angular diameter (DirectionalLight LightSourceAngle), as a half apex angle
642
+ *
643
+ * @internal
644
+ **/ const SUN_DISK_HALF_APEX_ANGLE = 0.5 * 0.5357 * Math.PI / 180;
645
+ /**
646
+ * @internal
647
+ *
648
+ * Sky luminance along a view direction, plus the sun disk.
649
+ *
650
+ * @remarks
651
+ * `f3LocalDir` is in the observer's local frame (see {@link AtmosphereParams.skyViewReferential}).
652
+ * Inside the atmosphere the luminance comes from the sky view LUT; above it the LUT, which is
653
+ * parameterized around a horizon inside the atmosphere, does not apply and the view ray is marched
654
+ * per pixel instead, starting where it enters the atmosphere. That path draws the planet as seen from
655
+ * space: the lit virtual ground behind the full atmosphere.
656
+ *
657
+ * `sunColor` receives the light color attenuated towards the observer.
658
+ *
659
+ * @param fIncludeSunDisk - 0: no sun disk; 1: legacy stylized disk with glow; 2: physical disk.
660
+ * @param fPixelAngle - Angular size of a screen pixel in radians, for anti-aliasing the physical disk.
661
+ * @param fSunDiskMaxLuminance - Ceiling for the physical disk before its edge coverage is applied, in
662
+ * the unscaled luminance this function returns (the output clamp divided by the luminance scale).
663
+ */ function skyBox(scope, stParams, f4SunColor, f3LocalDir, fSunSolidAngle, fIncludeSunDisk, fPixelAngle, fSunDiskMaxLuminance, texTransmittanceLut, texSkyViewLut, texMultiScatteringLut) {
456
664
  const pb = scope.$builder;
457
665
  const funcName = 'v_skybox';
458
666
  const Params = getAtmosphereParamsStruct(pb);
459
667
  pb.func(funcName, [
460
668
  Params('params'),
461
669
  pb.vec4('sunColor').out(),
462
- pb.vec3('worldPos'),
670
+ pb.vec3('localDir'),
463
671
  pb.float('sunSolidAngle'),
464
- pb.int('includeSunDisk')
672
+ pb.int('includeSunDisk'),
673
+ pb.float('pixelAngle'),
674
+ pb.float('sunDiskMaxLuminance')
465
675
  ], function() {
676
+ this.$l.viewDir = pb.normalize(this.localDir);
677
+ this.$l.eyePos = pb.vec3(0, pb.add(this.params.plantRadius, this.params.observerAltitude), 0);
466
678
  this.$l.rgb = pb.vec3(0);
467
- this.$l.viewDir = pb.normalize(this.worldPos);
468
- this.rgb = pb.add(this.rgb, pb.textureSampleLevel(texSkyViewLut, viewDirToUV(this, this.viewDir), 0).rgb);
469
- this.$l.groundDistance = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, pb.vec3(0, pb.add(this.params.plantRadius, pb.mul(CAMERA_POS_Y, this.params.cameraHeightScale)), 0), this.viewDir);
470
- this.$l.sunTransmittance = transmittanceToSky(this, this.params, pb.vec3(0, pb.add(this.params.cameraHeightScale, this.params.plantRadius), 0), this.params.lightDir, texTransmittanceLut);
679
+ this.$if(pb.lessThan(this.params.observerAltitude, this.params.atmosphereHeight), function() {
680
+ this.rgb = pb.textureSampleLevel(texSkyViewLut, viewDirToUV(this, this.params, this.viewDir), 0).rgb;
681
+ }).$else(function() {
682
+ this.rgb = getSkyView(this, this.params, this.eyePos, this.viewDir, pb.float(-1), texTransmittanceLut, texMultiScatteringLut, true, true).rgb;
683
+ });
684
+ this.$l.groundDistance = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.eyePos, this.viewDir);
685
+ this.$l.sunTransmittance = transmittanceToSky(this, this.params, this.eyePos, this.params.lightDir, texTransmittanceLut);
471
686
  this.sunColor = pb.mul(this.params.lightColor, pb.vec4(this.sunTransmittance, 1));
472
- this.$if(pb.and(pb.notEqual(this.includeSunDisk, 0), pb.lessThan(this.groundDistance, 0)), function() {
687
+ this.$if(pb.and(pb.equal(this.includeSunDisk, 1), pb.lessThan(this.groundDistance, 0)), function() {
473
688
  this.rgb = pb.add(this.rgb, sunBloom(this, this.viewDir, this.params.lightDir, this.sunColor, this.sunSolidAngle));
474
689
  });
690
+ this.$if(pb.equal(this.includeSunDisk, 2), function() {
691
+ const halfApex = SUN_DISK_HALF_APEX_ANGLE;
692
+ const solidAngle = 2 * Math.PI * (1 - Math.cos(halfApex));
693
+ this.$l.theta = pb.distance(this.viewDir, this.params.lightDir);
694
+ this.$l.halfPixel = pb.mul(this.pixelAngle, 0.5);
695
+ this.$if(pb.lessThan(this.theta, pb.add(halfApex, this.halfPixel)), function() {
696
+ this.$l.transmittanceToLight = transmittanceToSky(this, this.params, this.eyePos, this.viewDir, texTransmittanceLut);
697
+ this.$l.edgeTheta = pb.div(pb.max(pb.sub(this.theta, this.halfPixel), 0), halfApex);
698
+ this.$l.softEdge = pb.clamp(pb.mul(pb.sub(1, pb.mul(this.edgeTheta, this.edgeTheta)), 2), 0, 1);
699
+ this.$l.coverage = pb.clamp(pb.add(pb.div(pb.sub(halfApex, this.theta), pb.max(this.pixelAngle, 1e-6)), 0.5), 0, 1);
700
+ this.$l.diskLuminance = pb.mul(this.transmittanceToLight, this.params.lightColor.rgb, pb.div(this.params.lightColor.a, solidAngle), this.softEdge);
701
+ this.rgb = pb.add(this.rgb, pb.mul(pb.min(this.diskLuminance, pb.vec3(this.sunDiskMaxLuminance)), this.coverage));
702
+ });
703
+ });
475
704
  this.$return(pb.vec4(this.rgb, 1));
476
705
  });
477
- return scope[funcName](stParams, f4SunColor, f3SkyBoxWorldPos, fSunSolidAngle, fIncludeSunDisk);
706
+ return scope[funcName](stParams, f4SunColor, f3LocalDir, fSunSolidAngle, fIncludeSunDisk, fPixelAngle, fSunDiskMaxLuminance);
478
707
  }
479
- /** @internal */ function aerialPerspective(scope, f2UV, stParams, f3CameraPos, f3WorldPos, f3Dim, texAerialPerspectiveLut) {
708
+ /** @internal */ const AP_LUT_SLICE_SIZE = 32;
709
+ /** @internal */ const AP_LUT_DEPTH_SLICES = 32;
710
+ /**
711
+ * Samples the aerial perspective LUT.
712
+ * @internal
713
+ */ function aerialPerspective(scope, f2UV, stParams, f3CameraPos, f3WorldPos, f3Dim, texAerialPerspectiveLut) {
480
714
  const pb = scope.$builder;
481
715
  const Params = getAtmosphereParamsStruct(pb);
482
716
  const funcName = 'z_aerialPerspective';
@@ -487,99 +721,82 @@ function sunBloom(scope, f3ViewDir, f3LightDir, f4LightColorAndIntensity, fSunSo
487
721
  pb.vec3('worldPos'),
488
722
  pb.vec3('dim')
489
723
  ], function() {
490
- this.$l.V = pb.sub(this.worldPos, this.cameraPos);
491
- this.$l.dis = pb.length(this.V);
492
- this.$l.viewDir = pb.normalize(this.V);
493
- this.$l.apDistance = pb.div(this.params.apDistance, this.params.cameraHeightScale);
494
- this.$l.d0 = pb.clamp(pb.div(this.dis, this.apDistance), 0, 1);
495
- this.$l.weight = pb.clamp(pb.mul(this.d0, 2), 0, 1);
496
- this.$l.dz = pb.mul(this.d0, pb.sub(this.dim.z, 1));
497
- this.$l.slice = pb.floor(this.dz);
498
- this.$l.nextSlice = pb.min(pb.add(this.slice, 1), pb.sub(this.dim.z, 1));
499
- this.$l.factor = pb.sub(this.dz, pb.floor(this.dz));
500
- this.t = pb.div(this.uv, pb.vec2(this.dim.x, 1));
501
- this.$l.uv1 = pb.add(this.t, pb.vec2(pb.div(this.slice, this.dim.z), 0));
502
- this.$l.uv2 = pb.add(this.t, pb.vec2(pb.div(this.nextSlice, this.dim.z), 0));
724
+ this.$l.tDepth = pb.max(pb.sub(pb.mul(pb.distance(this.worldPos, this.cameraPos), this.params.cameraHeightScale), this.params.apStartDepth), 0);
725
+ this.$l.linearW = pb.clamp(pb.div(this.tDepth, this.params.apDistance), 0, 1);
726
+ this.$l.nonLinSlice = pb.mul(pb.sqrt(this.linearW), this.dim.z);
727
+ this.$l.weight = pb.clamp(pb.mul(this.nonLinSlice, this.nonLinSlice, 2), 0, 1);
728
+ this.$l.sliceF = pb.clamp(pb.sub(this.nonLinSlice, 0.5), 0, pb.sub(this.dim.z, 1));
729
+ this.$l.slice0 = pb.floor(this.sliceF);
730
+ this.$l.slice1 = pb.min(pb.add(this.slice0, 1), pb.sub(this.dim.z, 1));
731
+ this.$l.factor = pb.sub(this.sliceF, this.slice0);
732
+ this.$l.halfTexel = pb.div(0.5, this.dim.x);
733
+ this.$l.u = pb.clamp(this.uv.x, this.halfTexel, pb.sub(1, this.halfTexel));
734
+ this.$l.uv1 = pb.vec2(pb.div(pb.add(this.slice0, this.u), this.dim.z), this.uv.y);
735
+ this.$l.uv2 = pb.vec2(pb.div(pb.add(this.slice1, this.u), this.dim.z), this.uv.y);
503
736
  this.$l.data1 = pb.textureSampleLevel(texAerialPerspectiveLut, this.uv1, 0);
504
737
  this.$l.data2 = pb.textureSampleLevel(texAerialPerspectiveLut, this.uv2, 0);
505
738
  this.$l.data = pb.mix(this.data1, this.data2, this.factor);
506
- this.$l.inscattering = pb.mul(this.data.rgb, this.weight);
507
- //this.$l.transmittance = pb.sub(1, pb.mul(this.weight, pb.sub(1, this.data.a)));
508
- this.$l.planetTranslate = pb.vec3(0, this.params.plantRadius, 0);
509
- this.$l.transmittance = pb.dot(transmittance(this, this.params, pb.add(this.cameraPos, this.planetTranslate), pb.add(this.worldPos, this.planetTranslate)), pb.vec3(1 / 3, 1 / 3, 1 / 3));
510
- this.$return(pb.vec4(this.inscattering, this.transmittance));
739
+ this.$return(pb.vec4(pb.mul(this.data.rgb, this.weight), pb.sub(1, pb.mul(this.weight, pb.sub(1, this.data.a)))));
511
740
  });
512
741
  return scope[funcName](stParams, f2UV, f3CameraPos, f3WorldPos, f3Dim);
513
742
  }
514
- /** @internal */ function aerialPerspectiveLut(scope, stParams, f2UV, f3VoxelDim, texTransmittanceLut, texMultiScatteringLut) {
743
+ /**
744
+ * @internal
745
+ *
746
+ * Renders one texel of the aerial perspective LUT atlas: rgb is the in-scattered luminance and a
747
+ * the mean transmittance from the observer to the froxel.
748
+ */ function aerialPerspectiveLut(scope, stParams, f2UV, f3VoxelDim, texTransmittanceLut, texMultiScatteringLut) {
515
749
  const pb = scope.$builder;
516
750
  const Params = getAtmosphereParamsStruct(pb);
517
- const funcNameFixVoxel = 'z_fixVoxel';
518
- pb.func(funcNameFixVoxel, [
519
- Params('params'),
520
- pb.vec3('eyePos'),
521
- pb.vec3('viewDir').inout(),
522
- pb.float('maxDis'),
523
- pb.float('adjustedMaxDis').inout()
524
- ], function() {
525
- this.$l.voxelPos = pb.add(this.eyePos, pb.mul(this.viewDir, this.maxDis));
526
- this.$l.voxelHeight = pb.length(this.voxelPos);
527
- this.$l.underGround = pb.lessThan(this.voxelHeight, this.params.plantRadius);
528
- this.$l.cameraToVoxel = pb.sub(this.voxelPos, this.eyePos);
529
- this.$l.cameraToVoxelLen = pb.length(this.cameraToVoxel);
530
- this.$l.cameraToVoxelDir = pb.div(this.cameraToVoxel, this.cameraToVoxelLen);
531
- this.$l.planetNearT = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.eyePos, this.cameraToVoxelDir);
532
- this.$l.belowHorizon = pb.and(pb.greaterThan(this.planetNearT, 0), pb.greaterThan(this.cameraToVoxelLen, this.planetNearT));
533
- this.$l.eyePos2 = this.eyePos;
534
- this.$if(pb.or(this.underGround, this.belowHorizon), function() {
535
- this.eyePos2 = pb.add(this.eyePos2, pb.mul(pb.normalize(this.eyePos2), 0.02));
536
- this.$if(this.belowHorizon, function() {
537
- this.$l.voxelWorldPosNorm = pb.normalize(this.voxelPos);
538
- this.$l.camProjOnGround = pb.mul(pb.normalize(this.eyePos2), this.params.plantRadius);
539
- this.$l.voxProjOnGround = pb.mul(this.voxelWorldPosNorm, this.params.plantRadius);
540
- this.$l.voxelGroundToRayStart = pb.sub(this.eyePos2, this.voxProjOnGround);
541
- this.$if(pb.lessThan(pb.dot(pb.normalize(this.voxelGroundToRayStart), this.voxelWorldPosNorm), 0.0001), function() {
542
- this.$l.middlePoint = pb.mul(pb.add(this.camProjOnGround, this.voxProjOnGround), 0.5);
543
- this.$l.middlePointOnGround = pb.mul(pb.normalize(this.middlePoint), this.params.plantRadius);
544
- this.voxelPos = pb.add(this.eyePos2, pb.mul(pb.sub(this.middlePointOnGround, this.eyePos2), 2));
545
- });
546
- }).$else(function() {
547
- this.voxelPos = pb.mul(pb.normalize(this.voxelPos), this.params.plantRadius);
548
- });
549
- this.$l.V = pb.sub(this.voxelPos, this.eyePos2);
550
- this.adjustedMaxDis = pb.length(this.V);
551
- this.viewDir = pb.div(this.V, this.adjustedMaxDis);
552
- });
553
- this.$return(this.eyePos2);
554
- });
555
751
  const funcName = 'z_aerialPerspectiveLut';
556
752
  pb.func(funcName, [
557
753
  Params('params'),
558
754
  pb.vec2('uv'),
559
- pb.vec3('dim'),
560
- pb.float('cameraPosY')
755
+ pb.vec3('dim')
561
756
  ], function() {
562
- this.$l.uvw = pb.vec3(this.uv, 0);
563
- this.uvw.x = pb.mul(this.uvw.x, this.dim.x, this.dim.z);
564
- this.uvw.z = pb.div(pb.floor(pb.div(this.uvw.x, this.dim.z)), this.dim.x);
565
- this.uvw.x = pb.div(pb.mod(this.uvw.x, this.dim.z), this.dim.x);
566
- this.uvw = pb.add(this.uvw, pb.div(pb.vec3(0.5), this.dim));
567
- this.$l.slice = this.uvw.z; //pb.mul(this.uvw.z, this.uvw.z);
568
- this.$l.viewDir = pb.normalize(pb.mul(this.params.cameraWorldMatrix, pb.vec4(pb.sub(pb.mul(this.uvw.x, 2), 1), pb.div(pb.sub(pb.mul(this.uvw.y, 2), 1), this.params.cameraAspect), -1, 0)).xyz);
569
- this.$l.eyePos = pb.vec3(0, pb.add(pb.mul(this.cameraPosY, this.params.cameraHeightScale), this.params.plantRadius), 0);
570
- this.$l.maxDis = pb.mul(this.slice, this.params.apDistance);
757
+ // uv arrives at the texel center of the dim.x * dim.z wide atlas.
758
+ this.$l.px = pb.floor(pb.mul(this.uv.x, this.dim.x, this.dim.z));
759
+ this.$l.slice = pb.floor(pb.div(this.px, this.dim.x));
760
+ this.$l.screenUV = pb.vec2(pb.div(pb.add(pb.sub(this.px, pb.mul(this.slice, this.dim.x)), 0.5), this.dim.x), this.uv.y);
761
+ this.$l.w = pb.div(pb.add(this.slice, 0.5), this.dim.z);
762
+ this.$l.ndc = pb.sub(pb.mul(this.screenUV, 2), pb.vec2(1));
763
+ this.$l.viewDir = pb.normalize(pb.mul(this.params.cameraWorldMatrix, pb.vec4(pb.mul(this.ndc.x, this.params.cameraTanHalfFovy, this.params.cameraAspect), pb.mul(this.ndc.y, this.params.cameraTanHalfFovy), -1, 0)).xyz);
764
+ this.$l.eyePos = pb.vec3(0, pb.add(this.params.observerAltitude, this.params.plantRadius), 0);
765
+ // Slices start at the start depth (RayStartWorldPos = CamPos + StartDepth * WorldDir).
766
+ this.$l.maxDis = pb.add(this.params.apStartDepth, pb.mul(this.w, this.w, this.params.apDistance));
571
767
  this.$l.voxelPos = pb.add(this.eyePos, pb.mul(this.viewDir, this.maxDis));
572
- this.$if(pb.lessThan(pb.length(this.voxelPos), this.params.plantRadius), function() {
573
- this.voxelPos = pb.mul(pb.normalize(this.voxelPos), this.params.plantRadius);
574
- this.maxDis = pb.length(pb.sub(this.eyePos, this.voxelPos));
768
+ this.$l.underGround = pb.lessThan(pb.length(this.voxelPos), this.params.plantRadius);
769
+ this.$l.planetNearT = rayIntersectSphere(this, pb.vec3(0), this.params.plantRadius, this.eyePos, this.viewDir);
770
+ this.$l.belowHorizon = pb.and(pb.greaterThan(this.planetNearT, 0), pb.greaterThan(this.maxDis, this.planetNearT));
771
+ // A froxel behind the ground would only integrate up to the ground hit, leaving surfaces seen
772
+ // from above (the observer sits just above the planet) without any aerial perspective. Instead
773
+ // integrate towards the ground point below the froxel.
774
+ this.$if(pb.or(this.underGround, this.belowHorizon), function() {
775
+ this.$l.voxelPosNorm = pb.normalize(this.voxelPos);
776
+ this.$l.camProjOnGround = pb.mul(pb.normalize(this.eyePos), this.params.plantRadius);
777
+ this.$l.voxProjOnGround = pb.mul(this.voxelPosNorm, this.params.plantRadius);
778
+ this.$l.voxelGroundToRayStart = pb.sub(this.eyePos, this.voxProjOnGround);
779
+ this.$if(pb.and(this.belowHorizon, pb.lessThan(pb.dot(pb.normalize(this.voxelGroundToRayStart), this.voxelPosNorm), 0.0001)), function() {
780
+ // Behind the planet: evaluate the point mirrored through the horizon point.
781
+ this.$l.middlePoint = pb.mul(pb.add(this.camProjOnGround, this.voxProjOnGround), 0.5);
782
+ this.$l.middlePointOnGround = pb.mul(pb.normalize(this.middlePoint), this.params.plantRadius);
783
+ this.voxelPos = pb.add(this.eyePos, pb.mul(pb.sub(this.middlePointOnGround, this.eyePos), 2));
784
+ }).$elseif(this.underGround, function() {
785
+ this.voxelPos = this.voxProjOnGround;
786
+ });
787
+ this.$l.V = pb.sub(this.voxelPos, this.eyePos);
788
+ this.maxDis = pb.length(this.V);
789
+ this.viewDir = pb.div(this.V, this.maxDis);
575
790
  });
576
- this.$l.color = getSkyView(this, this.params, this.eyePos, this.viewDir, this.maxDis, texTransmittanceLut, texMultiScatteringLut);
577
- this.$l.t1 = transmittanceToSky(this, this.params, this.eyePos, this.viewDir, texTransmittanceLut);
578
- this.$l.t2 = transmittanceToSky(this, this.params, this.voxelPos, this.viewDir, texTransmittanceLut);
579
- this.$l.t = pb.clamp(pb.div(this.t1, pb.max(this.t2, pb.vec3(0.0001))), pb.vec3(0), pb.vec3(1));
580
- this.$return(pb.vec4(this.color, pb.dot(this.t, pb.vec3(1 / 3, 1 / 3, 1 / 3))));
791
+ // Integrate from the start depth along the (possibly redirected) ray up to the froxel.
792
+ this.$l.rayStart = pb.add(this.eyePos, pb.mul(this.viewDir, this.params.apStartDepth));
793
+ this.$l.segment = pb.sub(this.maxDis, this.params.apStartDepth);
794
+ this.$if(pb.lessThanEqual(this.segment, 0), function() {
795
+ this.$return(pb.vec4(0, 0, 0, 1));
796
+ });
797
+ this.$return(getSkyView(this, this.params, this.rayStart, this.viewDir, this.segment, texTransmittanceLut, texMultiScatteringLut, true, false, true));
581
798
  });
582
- return scope[funcName](stParams, f2UV, f3VoxelDim, CAMERA_POS_Y);
799
+ return scope[funcName](stParams, f2UV, f3VoxelDim);
583
800
  }
584
801
  /** @internal */ function skyViewLut(scope, stParams, f2UV, texTransmittanceLut, texMultiScatteringLut) {
585
802
  const pb = scope.$builder;
@@ -587,16 +804,15 @@ function sunBloom(scope, f3ViewDir, f3LightDir, f4LightColorAndIntensity, fSunSo
587
804
  const funcName = 'v_skyViewLut';
588
805
  pb.func(funcName, [
589
806
  Params('params'),
590
- pb.vec2('uv'),
591
- pb.float('cameraPosY')
807
+ pb.vec2('uv')
592
808
  ], function() {
593
- this.$l.viewDir = uvToViewDir(this, this.uv);
594
- this.$l.h = pb.add(this.params.plantRadius, pb.mul(this.cameraPosY, this.params.cameraHeightScale));
809
+ this.$l.viewDir = uvToViewDir(this, this.params, this.uv);
810
+ this.$l.h = pb.add(this.params.plantRadius, this.params.observerAltitude);
595
811
  this.$l.eyePos = pb.vec3(0, this.h, 0);
596
- this.$l.rgb = getSkyView(this, this.params, this.eyePos, this.viewDir, pb.float(-1), texTransmittanceLut, texMultiScatteringLut);
812
+ this.$l.rgb = getSkyView(this, this.params, this.eyePos, this.viewDir, pb.float(-1), texTransmittanceLut, texMultiScatteringLut, true, true).rgb;
597
813
  this.$return(pb.vec4(this.rgb, 1));
598
814
  });
599
- return scope[funcName](stParams, f2UV, CAMERA_POS_Y);
815
+ return scope[funcName](stParams, f2UV);
600
816
  }
601
817
  /** @internal */ function multiScatteringLut(scope, stParams, f2UV, texTransmittanceLut) {
602
818
  const pb = scope.$builder;
@@ -693,6 +909,8 @@ let APFramebuffer;
693
909
  pb.vec4('lightColor'),
694
910
  pb.vec3('lightDir'),
695
911
  pb.float('cameraAspect'),
912
+ pb.vec3('groundAlbedo'),
913
+ pb.float('cameraTanHalfFovy'),
696
914
  pb.float('plantRadius'),
697
915
  pb.float('atmosphereHeight'),
698
916
  pb.float('rayleighScatteringHeight'),
@@ -701,7 +919,11 @@ let APFramebuffer;
701
919
  pb.float('ozoneCenter'),
702
920
  pb.float('ozoneWidth'),
703
921
  pb.float('apDistance'),
704
- pb.float('cameraHeightScale')
922
+ pb.float('apViewDistanceScale'),
923
+ pb.float('apStartDepth'),
924
+ pb.float('cameraHeightScale'),
925
+ pb.float('observerAltitude'),
926
+ pb.mat4('skyViewReferential')
705
927
  ]);
706
928
  }
707
929
  /** @internal */ function createTransmittanceLutProgram(device) {
@@ -859,7 +1081,7 @@ let APFramebuffer;
859
1081
  try {
860
1082
  skyViewLutProgram = createSkyViewLutProgram(device);
861
1083
  skyViewLutBindGroup = device.createBindGroup(skyViewLutProgram.bindGroupLayouts[0]);
862
- skyViewLUT = device.createTexture2D('rgba16f', 256, 128, {
1084
+ skyViewLUT = device.createTexture2D('rgba16f', SKY_VIEW_LUT_WIDTH, SKY_VIEW_LUT_HEIGHT, {
863
1085
  mipmapping: false
864
1086
  });
865
1087
  skyViewLUT.name = 'DebugSkyViewLut';
@@ -904,7 +1126,7 @@ let APFramebuffer;
904
1126
  this.multiScatteringLut = pb.tex2D().uniform(0);
905
1127
  this.$outputs.outColor = pb.vec4();
906
1128
  pb.main(function() {
907
- this.$outputs.outColor = aerialPerspectiveLut(this, this.params, this.$inputs.uv, pb.vec3(32, 32, 32), this.transmittanceLut, this.multiScatteringLut);
1129
+ this.$outputs.outColor = aerialPerspectiveLut(this, this.params, this.$inputs.uv, pb.vec3(AP_LUT_SLICE_SIZE, AP_LUT_SLICE_SIZE, AP_LUT_DEPTH_SLICES), this.transmittanceLut, this.multiScatteringLut);
908
1130
  });
909
1131
  }
910
1132
  });
@@ -917,7 +1139,7 @@ let APFramebuffer;
917
1139
  try {
918
1140
  APLutProgram = createAPLutProgram(device);
919
1141
  APLutBindGroup = device.createBindGroup(APLutProgram.bindGroupLayouts[0]);
920
- ApLut = device.createTexture2D('rgba16f', 32 * 32, 32, {
1142
+ ApLut = device.createTexture2D('rgba16f', AP_LUT_SLICE_SIZE * AP_LUT_DEPTH_SLICES, AP_LUT_SLICE_SIZE, {
921
1143
  mipmapping: false
922
1144
  });
923
1145
  ApLut.name = 'DebugAPLut';
@@ -942,5 +1164,5 @@ let APFramebuffer;
942
1164
  }
943
1165
  }
944
1166
 
945
- export { CAMERA_POS_Y, aerialPerspective, aerialPerspectiveLut, atmosphereLUTRendered, createAPLutProgram, createMultiScatteringLutProgram, createSkyViewLutProgram, createTransmittanceLutProgram, getAerialPerspectiveLut, getAtmosphereParamsStruct, getDefaultAtmosphereParams, getMultiScattering, getMultiScatteringLut, getSkyView, getSkyViewLut, getTransmittanceLut, integralMultiScattering, mieAbsorption, mieCoefficient, miePhase, multiScatteringLut, ozoneAbsorption, rayIntersectSphere, rayleighCoefficient, rayleighPhase, renderAPLut, renderAtmosphereLUTs, renderMultiScatteringLut, renderSkyViewLut, renderTransmittanceLut, scattering, skyBox, skyViewLut, transmittance, transmittanceLut, transmittanceLutToUV, transmittanceToSky, uvToTransmittanceLut, uvToViewDir, viewDirToUV };
1167
+ export { AP_LUT_DEPTH_SLICES, AP_LUT_SLICE_SIZE, MIN_OBSERVER_ALTITUDE, SKY_VIEW_LUT_HEIGHT, SKY_VIEW_LUT_WIDTH, SUN_DISK_HALF_APEX_ANGLE, aerialPerspective, aerialPerspectiveLut, atmosphereLUTRendered, createAPLutProgram, createMultiScatteringLutProgram, createSkyViewLutProgram, createTransmittanceLutProgram, getAerialPerspectiveLut, getAtmosphereParamsStruct, getDefaultAtmosphereParams, getMultiScattering, getMultiScatteringLut, getSkyView, getSkyViewLut, getTransmittanceLut, groundBounce, integralMultiScattering, mieAbsorption, mieCoefficient, miePhase, multiScatteringLut, ozoneAbsorption, rayIntersectSphere, rayIntersectSphereFar, rayleighCoefficient, rayleighPhase, renderAPLut, renderAtmosphereLUTs, renderMultiScatteringLut, renderSkyViewLut, renderTransmittanceLut, scattering, skyBox, skyViewLut, transmittance, transmittanceLut, transmittanceLutToUV, transmittanceToSky, uvToTransmittanceLut, uvToViewDir, viewDirToUV };
946
1168
  //# sourceMappingURL=atmosphere.js.map