@zephyr3d/scene 0.9.27 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -27
- package/dist/animation/animation_bank.js +634 -0
- package/dist/animation/animation_bank.js.map +1 -0
- package/dist/animation/animation_bank_gpu.js +256 -0
- package/dist/animation/animation_bank_gpu.js.map +1 -0
- package/dist/animation/animationset.js +54 -0
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/cloth/gpu_cloth_component.js +406 -0
- package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
- package/dist/animation/cloth/gpu_cloth_system.js +332 -202
- package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
- package/dist/animation/gpu_animation_driver.js +289 -0
- package/dist/animation/gpu_animation_driver.js.map +1 -0
- package/dist/animation/joint_dynamics/collision.js +112 -1
- package/dist/animation/joint_dynamics/collision.js.map +1 -1
- package/dist/animation/joint_dynamics/controller.js +6 -0
- package/dist/animation/joint_dynamics/controller.js.map +1 -1
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
- package/dist/animation/joint_dynamics/solver.js +50 -12
- package/dist/animation/joint_dynamics/solver.js.map +1 -1
- package/dist/animation/joint_dynamics/types.js.map +1 -1
- package/dist/animation/skeleton.js +279 -55
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skin_palette_atlas.js +252 -0
- package/dist/animation/skin_palette_atlas.js.map +1 -0
- package/dist/animation/spring/multi_chain_spring_system.js +298 -38
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
- package/dist/animation/spring/spring_chain.js +2 -0
- package/dist/animation/spring/spring_chain.js.map +1 -1
- package/dist/animation/spring/spring_collider.js +159 -21
- package/dist/animation/spring/spring_collider.js.map +1 -1
- package/dist/animation/spring/spring_particle.js +1 -0
- package/dist/animation/spring/spring_particle.js.map +1 -1
- package/dist/animation/spring/spring_solver.js +173 -0
- package/dist/animation/spring/spring_solver.js.map +1 -0
- package/dist/animation/spring/spring_system.js +249 -24
- package/dist/animation/spring/spring_system.js.map +1 -1
- package/dist/animation/spring_modifier.js +32 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/app/app.js +26 -0
- package/dist/app/app.js.map +1 -1
- package/dist/app/engine.js +86 -15
- package/dist/app/engine.js.map +1 -1
- package/dist/app/gamepad.js +191 -0
- package/dist/app/gamepad.js.map +1 -0
- package/dist/app/inputactions.js +271 -0
- package/dist/app/inputactions.js.map +1 -0
- package/dist/app/inputmgr.js +331 -22
- package/dist/app/inputmgr.js.map +1 -1
- package/dist/app/loading.js +138 -0
- package/dist/app/loading.js.map +1 -0
- package/dist/app/pipelinecache.js +209 -0
- package/dist/app/pipelinecache.js.map +1 -0
- package/dist/app/runtimescript.js +25 -0
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/scriptingsystem.js +54 -0
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +7 -2
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/asset_manifest.js +59 -0
- package/dist/asset/asset_manifest.js.map +1 -0
- package/dist/asset/asset_preload.js +258 -0
- package/dist/asset/asset_preload.js.map +1 -0
- package/dist/asset/assetmanager.js +117 -65
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/dist/asset/loaders/ktx2/basis_location.js +17 -0
- package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
- package/dist/asset/mesh_lod_builder.js +104 -0
- package/dist/asset/mesh_lod_builder.js.map +1 -0
- package/dist/asset/mesh_settings.js +111 -0
- package/dist/asset/mesh_settings.js.map +1 -0
- package/dist/asset/meshopt_decoder.js +18 -0
- package/dist/asset/meshopt_decoder.js.map +1 -0
- package/dist/asset/meshopt_simplifier.js +26 -0
- package/dist/asset/meshopt_simplifier.js.map +1 -0
- package/dist/asset/model.js +171 -1
- package/dist/asset/model.js.map +1 -1
- package/dist/asset/texture_settings.js +231 -0
- package/dist/asset/texture_settings.js.map +1 -0
- package/dist/asset/zmsh_binary.js +131 -0
- package/dist/asset/zmsh_binary.js.map +1 -0
- package/dist/asset/zsdf_binary.js +111 -0
- package/dist/asset/zsdf_binary.js.map +1 -0
- package/dist/blitter/bilateralblur.js +1 -2
- package/dist/blitter/bilateralblur.js.map +1 -1
- package/dist/blitter/gaussianblur.js +1 -6
- package/dist/blitter/gaussianblur.js.map +1 -1
- package/dist/camera/base.js +31 -10
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +104 -178
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/follow.js +342 -0
- package/dist/camera/follow.js.map +1 -0
- package/dist/camera/fps.js +9 -7
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +46 -19
- package/dist/camera/orbit.js.map +1 -1
- package/dist/index.d.ts +25436 -15990
- package/dist/index.js +65 -11
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js +3 -0
- package/dist/material/blinn.js.map +1 -1
- package/dist/material/eye.js +1 -1
- package/dist/material/eye.js.map +1 -1
- package/dist/material/hair.js +2 -3
- package/dist/material/hair.js.map +1 -1
- package/dist/material/lambert.js +4 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +66 -4
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +118 -45
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js +1 -1
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +191 -83
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +31 -206
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mtoon.js +1 -1
- package/dist/material/mtoon.js.map +1 -1
- package/dist/material/pbrmr.js +3 -0
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/pbrsg.js +3 -0
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/sdf_debug.js +78 -0
- package/dist/material/sdf_debug.js.map +1 -0
- package/dist/material/shader/helper.js +333 -191
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/shader/terrain_blend.js +204 -43
- package/dist/material/shader/terrain_blend.js.map +1 -1
- package/dist/material/skin.js +331 -297
- package/dist/material/skin.js.map +1 -1
- package/dist/material/skinprofile.js +1058 -0
- package/dist/material/skinprofile.js.map +1 -0
- package/dist/material/sss.js +353 -0
- package/dist/material/sss.js.map +1 -0
- package/dist/material/sss_kernel.js +265 -0
- package/dist/material/sss_kernel.js.map +1 -0
- package/dist/material/sssprofile.js +879 -0
- package/dist/material/sssprofile.js.map +1 -0
- package/dist/material/subsurfaceprofile.js +4 -8
- package/dist/material/subsurfaceprofile.js.map +1 -1
- package/dist/material/terrain-cm.js +464 -188
- package/dist/material/terrain-cm.js.map +1 -1
- package/dist/material/unlit.js +3 -0
- package/dist/material/unlit.js.map +1 -1
- package/dist/material/water.js +1261 -1438
- package/dist/material/water.js.map +1 -1
- package/dist/node_modules/meshoptimizer/LICENSE +21 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
- package/dist/physics/character.js +226 -0
- package/dist/physics/character.js.map +1 -0
- package/dist/physics/collider.js +209 -0
- package/dist/physics/collider.js.map +1 -0
- package/dist/physics/events.js +79 -0
- package/dist/physics/events.js.map +1 -0
- package/dist/physics/joint.js +272 -0
- package/dist/physics/joint.js.map +1 -0
- package/dist/physics/node_physics.js +234 -0
- package/dist/physics/node_physics.js.map +1 -0
- package/dist/physics/part.js +91 -0
- package/dist/physics/part.js.map +1 -0
- package/dist/physics/rigid_body.js +379 -0
- package/dist/physics/rigid_body.js.map +1 -0
- package/dist/physics/vehicle.js +335 -0
- package/dist/physics/vehicle.js.map +1 -0
- package/dist/physics/world.js +25 -0
- package/dist/physics/world.js.map +1 -0
- package/dist/posteffect/bloom.js +49 -14
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/motionblur.js +106 -106
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/postsss.js +572 -0
- package/dist/posteffect/postsss.js.map +1 -0
- package/dist/posteffect/sao.js +2 -6
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/skinsss.js +605 -355
- package/dist/posteffect/skinsss.js.map +1 -1
- package/dist/posteffect/ssgi.js +91 -162
- package/dist/posteffect/ssgi.js.map +1 -1
- package/dist/posteffect/ssr.js +3 -11
- package/dist/posteffect/ssr.js.map +1 -1
- package/dist/posteffect/sss.js +4 -13
- package/dist/posteffect/sss.js.map +1 -1
- package/dist/posteffect/taa.js +1 -0
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/render/abuffer_oit.js +3 -2
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +179 -64
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cluster_light.js +958 -224
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/cull_visitor.js +25 -5
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/debug_views.js +37 -0
- package/dist/render/debug_views.js.map +1 -0
- package/dist/render/depthpass.js +5 -1
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable_mixin.js +53 -6
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/dualdepthpeeling_oit.js +5 -5
- package/dist/render/dualdepthpeeling_oit.js.map +1 -1
- package/dist/render/envlight.js +196 -113
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +5 -10
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +247 -157
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +16 -38
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/gi/probe_volume.js +1334 -0
- package/dist/render/gi/probe_volume.js.map +1 -0
- package/dist/render/gi/scene_gi.js +282 -0
- package/dist/render/gi/scene_gi.js.map +1 -0
- package/dist/render/gi/voxel_atlas.js +198 -0
- package/dist/render/gi/voxel_atlas.js.map +1 -0
- package/dist/render/gi/voxel_lighting.js +652 -0
- package/dist/render/gi/voxel_lighting.js.map +1 -0
- package/dist/render/gi/voxel_scene.js +642 -0
- package/dist/render/gi/voxel_scene.js.map +1 -0
- package/dist/render/gi/voxelize_pass.js +223 -0
- package/dist/render/gi/voxelize_pass.js.map +1 -0
- package/dist/render/globalbindgroup_allocator.js +3 -2
- package/dist/render/globalbindgroup_allocator.js.map +1 -1
- package/dist/render/gpu_picking.js +9 -36
- package/dist/render/gpu_picking.js.map +1 -1
- package/dist/render/instance_culling.js +499 -0
- package/dist/render/instance_culling.js.map +1 -0
- package/dist/render/lightpass.js +19 -8
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/lod.js +46 -0
- package/dist/render/lod.js.map +1 -0
- package/dist/render/primitive.js +301 -9
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/primitive_readback.js +209 -0
- package/dist/render/primitive_readback.js.map +1 -0
- package/dist/render/render_queue.js +162 -11
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +10 -7
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +14 -1
- package/dist/render/rendergraph/blackboard.js.map +1 -1
- package/dist/render/rendergraph/executor.js +136 -0
- package/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +272 -55
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_graph_context.js +41 -0
- package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
- package/dist/render/rendergraph/scene_render_context.js +31 -2
- package/dist/render/rendergraph/scene_render_context.js.map +1 -1
- package/dist/render/rendergraph/types.js.map +1 -1
- package/dist/render/renderpass.js +28 -5
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/sdf/box_allocator.js +98 -0
- package/dist/render/sdf/box_allocator.js.map +1 -0
- package/dist/render/sdf/global_sdf.js +865 -0
- package/dist/render/sdf/global_sdf.js.map +1 -0
- package/dist/render/sdf/scene_sdf.js +562 -0
- package/dist/render/sdf/scene_sdf.js.map +1 -0
- package/dist/render/sdf/sdf_atlas.js +227 -0
- package/dist/render/sdf/sdf_atlas.js.map +1 -0
- package/dist/render/sdf/sdf_programs.js +42 -0
- package/dist/render/sdf/sdf_programs.js.map +1 -0
- package/dist/render/sdf/sdf_view.js +199 -0
- package/dist/render/sdf/sdf_view.js.map +1 -0
- package/dist/render/sdf/waterline.js +610 -0
- package/dist/render/sdf/waterline.js.map +1 -0
- package/dist/render/shadow_mask_pass.js +142 -25
- package/dist/render/shadow_mask_pass.js.map +1 -1
- package/dist/render/shore_wave_generator.js +1193 -0
- package/dist/render/shore_wave_generator.js.map +1 -0
- package/dist/render/sky.js +516 -86
- package/dist/render/sky.js.map +1 -1
- package/dist/render/transmission_thickness_pass.js +477 -0
- package/dist/render/transmission_thickness_pass.js.map +1 -0
- package/dist/render/underwater.js +58 -158
- package/dist/render/underwater.js.map +1 -1
- package/dist/render/virtualtexture/virtual_texture.js +1214 -0
- package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_common.js +472 -0
- package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
- package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
- package/dist/render/volumetric_cloud/debug_view.js +131 -0
- package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
- package/dist/render/volumetric_cloud/resources.js +380 -0
- package/dist/render/volumetric_cloud/resources.js.map +1 -0
- package/dist/render/volumetric_cloud/sky_cache.js +380 -0
- package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
- package/dist/render/water_caustics.js +134 -319
- package/dist/render/water_caustics.js.map +1 -1
- package/dist/render/water_foam.js +627 -0
- package/dist/render/water_foam.js.map +1 -0
- package/dist/render/water_interaction.js +1795 -0
- package/dist/render/water_interaction.js.map +1 -0
- package/dist/render/weightedblended_oit.js +3 -3
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/basesprite.js +9 -4
- package/dist/scene/basesprite.js.map +1 -1
- package/dist/scene/batchgroup.js +108 -12
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +28 -7
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/foliage.js +1020 -0
- package/dist/scene/foliage.js.map +1 -0
- package/dist/scene/foliage_buckets.js +147 -0
- package/dist/scene/foliage_buckets.js.map +1 -0
- package/dist/scene/foliage_mask.js +358 -0
- package/dist/scene/foliage_mask.js.map +1 -0
- package/dist/scene/hair.js +15 -4
- package/dist/scene/hair.js.map +1 -1
- package/dist/scene/light.js +179 -13
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +327 -45
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/meshdrawable.js +6 -0
- package/dist/scene/meshdrawable.js.map +1 -1
- package/dist/scene/msdftext.js +9 -3
- package/dist/scene/msdftext.js.map +1 -1
- package/dist/scene/msdftextsprite.js +9 -3
- package/dist/scene/msdftextsprite.js.map +1 -1
- package/dist/scene/particlesys.js +8 -2
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/physics_settings.js +157 -0
- package/dist/scene/physics_settings.js.map +1 -0
- package/dist/scene/scene.js +190 -44
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +147 -6
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
- package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +881 -42
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/grass_gpu.js +929 -0
- package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
- package/dist/scene/terrain-cm/grassmaterial.js +180 -9
- package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +465 -36
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
- package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
- package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
- package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
- package/dist/scene/update_queue.js +54 -0
- package/dist/scene/update_queue.js.map +1 -0
- package/dist/scene/water.js +633 -268
- package/dist/scene/water.js.map +1 -1
- package/dist/scene/water_surface_sampler.js +324 -0
- package/dist/scene/water_surface_sampler.js.map +1 -0
- package/dist/scene/wind.js +317 -0
- package/dist/scene/wind.js.map +1 -0
- package/dist/shaders/atmosphere.js +388 -166
- package/dist/shaders/atmosphere.js.map +1 -1
- package/dist/shaders/fog.js +100 -32
- package/dist/shaders/fog.js.map +1 -1
- package/dist/shaders/gi.js +365 -0
- package/dist/shaders/gi.js.map +1 -0
- package/dist/shaders/ltc_rect.js +202 -0
- package/dist/shaders/ltc_rect.js.map +1 -0
- package/dist/shaders/misc.js +1 -10
- package/dist/shaders/misc.js.map +1 -1
- package/dist/shaders/noise.js +5 -1
- package/dist/shaders/noise.js.map +1 -1
- package/dist/shaders/probes.js +309 -0
- package/dist/shaders/probes.js.map +1 -0
- package/dist/shaders/sdf.js +537 -0
- package/dist/shaders/sdf.js.map +1 -0
- package/dist/shaders/shadow.js +104 -70
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shaders/skin_brdf.js +243 -0
- package/dist/shaders/skin_brdf.js.map +1 -0
- package/dist/shaders/ssgi.js +63 -0
- package/dist/shaders/ssgi.js.map +1 -0
- package/dist/shaders/ssgi_reprojection.js +118 -0
- package/dist/shaders/ssgi_reprojection.js.map +1 -0
- package/dist/shaders/ssr.js +6 -159
- package/dist/shaders/ssr.js.map +1 -1
- package/dist/shaders/temporal.js +38 -27
- package/dist/shaders/temporal.js.map +1 -1
- package/dist/shaders/water.js +32 -82
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +7 -21
- package/dist/shaders/water_medium.js.map +1 -1
- package/dist/shadow/dom.js +110 -19
- package/dist/shadow/dom.js.map +1 -1
- package/dist/shadow/esm.js +3 -3
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/pcf_opt.js +15 -48
- package/dist/shadow/pcf_opt.js.map +1 -1
- package/dist/shadow/pcf_pd.js +15 -53
- package/dist/shadow/pcf_pd.js.map +1 -1
- package/dist/shadow/pcss.js +34 -9
- package/dist/shadow/pcss.js.map +1 -1
- package/dist/shadow/shadow_impl.js +3 -8
- package/dist/shadow/shadow_impl.js.map +1 -1
- package/dist/shadow/shadow_region.js +40 -2
- package/dist/shadow/shadow_region.js.map +1 -1
- package/dist/shadow/shadowmapper.js +93 -53
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/ssm.js +18 -72
- package/dist/shadow/ssm.js.map +1 -1
- package/dist/shadow/vsm.js +3 -3
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/shape.js +44 -1
- package/dist/shapes/shape.js.map +1 -1
- package/dist/utility/buoyancy.js +287 -0
- package/dist/utility/buoyancy.js.map +1 -0
- package/dist/utility/physical.js +10 -1
- package/dist/utility/physical.js.map +1 -1
- package/dist/utility/pmrem.js +17 -43
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/sdf/bake.js +435 -0
- package/dist/utility/sdf/bake.js.map +1 -0
- package/dist/utility/sdf/bvh.js +576 -0
- package/dist/utility/sdf/bvh.js.map +1 -0
- package/dist/utility/serialization/manager.js +34 -6
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +46 -5
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +11 -4
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +87 -254
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/cloth.js +25 -0
- package/dist/utility/serialization/scene/cloth.js.map +1 -0
- package/dist/utility/serialization/scene/common.js +14 -6
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/foliage.js +821 -0
- package/dist/utility/serialization/scene/foliage.js.map +1 -0
- package/dist/utility/serialization/scene/hair.js +11 -4
- package/dist/utility/serialization/scene/hair.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +115 -7
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +388 -220
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +69 -4
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +140 -5
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/node_physics.js +1318 -0
- package/dist/utility/serialization/scene/node_physics.js.map +1 -0
- package/dist/utility/serialization/scene/particle.js +11 -4
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/physics.js +120 -0
- package/dist/utility/serialization/scene/physics.js.map +1 -0
- package/dist/utility/serialization/scene/primitive.js +124 -10
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +1687 -51
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/sprite.js +11 -4
- package/dist/utility/serialization/scene/sprite.js.map +1 -1
- package/dist/utility/serialization/scene/terrain.js +163 -33
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/text.js +11 -4
- package/dist/utility/serialization/scene/text.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +1543 -264
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/shprojector.js +10 -22
- package/dist/utility/shprojector.js.map +1 -1
- package/dist/utility/textures/foam.js +170 -0
- package/dist/utility/textures/foam.js.map +1 -0
- package/dist/utility/textures/ggxlut.js +17 -43
- package/dist/utility/textures/ggxlut.js.map +1 -1
- package/dist/utility/textures/ltcdata.js +4 -4
- package/dist/utility/textures/ltcdata.js.map +1 -1
- package/dist/utility/textures/ltclut.js +16 -6
- package/dist/utility/textures/ltclut.js.map +1 -1
- package/dist/utility/unsupported.js +24 -0
- package/dist/utility/unsupported.js.map +1 -0
- package/dist/values.js +13 -1
- package/dist/values.js.map +1 -1
- package/package.json +25 -12
- package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/src/asset/meshoptimizer/LICENSE +21 -0
- package/dist/animation/joint_dynamics/convex_collider.js +0 -320
- package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { Vector3 } from '@zephyr3d/base';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Taps stored per profile in the kernel LUT, per side of the kernel centre.
|
|
5
|
+
*
|
|
6
|
+
* The full separable kernel is `2 * SSS_KERNEL_TAPS_PER_SIDE + 1` wide. Unreal's
|
|
7
|
+
* separable path uses 13 + 9 + 6 taps across its three kernels; this is the same
|
|
8
|
+
* order of magnitude, and the quality presets stride across it rather than
|
|
9
|
+
* baking a different table per preset.
|
|
10
|
+
*/ const SSS_KERNEL_TAPS_PER_SIDE = 15;
|
|
11
|
+
/**
|
|
12
|
+
* Entries in a baked kernel row: the centre tap plus one side.
|
|
13
|
+
*
|
|
14
|
+
* Only half the kernel is stored because it is symmetric about its centre and
|
|
15
|
+
* the shader mirrors each tap as it walks outwards. The weights are normalized
|
|
16
|
+
* for the *full* mirrored kernel, so a consumer that does not mirror would come
|
|
17
|
+
* out half as bright.
|
|
18
|
+
*/ const SSS_KERNEL_TAPS = SSS_KERNEL_TAPS_PER_SIDE + 1;
|
|
19
|
+
/**
|
|
20
|
+
* Entries in a baked transmission table.
|
|
21
|
+
*
|
|
22
|
+
* Unreal's own is 32 wide, which its capture shows holding a per-channel
|
|
23
|
+
* Beer-Lambert falloff sampled across thickness. Matching the width is not the
|
|
24
|
+
* point - it is simply enough resolution for a curve this smooth.
|
|
25
|
+
*/ const SSS_TRANSMISSION_SAMPLES = 32;
|
|
26
|
+
/**
|
|
27
|
+
* Columns of the kernel LUT that precede the baked taps.
|
|
28
|
+
*
|
|
29
|
+
* One, holding `(diffusionWorldRadius, transmissionMaxThickness, 0, 0)` - the
|
|
30
|
+
* two scales the rest of the row is measured against. Named because the baker
|
|
31
|
+
* writes it and the shader reads it, and an off-by-one between them silently
|
|
32
|
+
* reads a weight as a radius.
|
|
33
|
+
*/ const SSS_KERNEL_LUT_HEADER_COLUMNS = 1;
|
|
34
|
+
/**
|
|
35
|
+
* Christensen-Burley shaping parameter.
|
|
36
|
+
*
|
|
37
|
+
* The "diffusion" fit rather than the "searchlight" one, matching what Unreal
|
|
38
|
+
* uses: searchlight is the better match to ground truth for a pencil beam, but
|
|
39
|
+
* diffusion is what a screen-space pass actually approximates, and mixing the
|
|
40
|
+
* two is how a profile ends up looking right in isolation and wrong in a scene.
|
|
41
|
+
*/ function burleyScaling(albedo) {
|
|
42
|
+
const a = Math.min(Math.max(albedo, 0), 1);
|
|
43
|
+
return 1.9 - a + 3.5 * (a - 0.8) * (a - 0.8);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Radially symmetric Burley reflectance profile, without the `1/r` Jacobian.
|
|
47
|
+
*
|
|
48
|
+
* `R(r) = (e^(-r/d) + e^(-r/(3d))) / (8*pi*d*r)`
|
|
49
|
+
*
|
|
50
|
+
* The `1/r` term converts the 1D profile into a 2D disc density. A separable
|
|
51
|
+
* screen-space blur integrates along a line rather than over a disc, so it is
|
|
52
|
+
* dropped and the weights are renormalized by their own sum instead - the same
|
|
53
|
+
* approximation `burleyDiffusionWeight` in `shaders/diffusion.ts` documents, and
|
|
54
|
+
* it has to be the same one or the two paths would disagree about what a profile
|
|
55
|
+
* means. The constant factor goes with it, since normalization removes it.
|
|
56
|
+
*/ function burleyProfile(r, d) {
|
|
57
|
+
const safeD = Math.max(d, 1e-6);
|
|
58
|
+
const x = Math.abs(r) / safeD;
|
|
59
|
+
return (Math.exp(-Math.min(x, 40)) + Math.exp(-Math.min(x / 3, 40))) / safeD;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Inverse of the Burley CDF, `F(r) = 1 - e^(-r/d)/4 - 3*e^(-r/(3d))/4`.
|
|
63
|
+
*
|
|
64
|
+
* Solved by bisection rather than Newton: the derivative is well behaved but the
|
|
65
|
+
* CDF flattens hard in the tail, and a Newton step from a poor bracket there
|
|
66
|
+
* overshoots into negative radii. This runs once per profile change, so twenty
|
|
67
|
+
* bisection steps cost nothing worth optimizing.
|
|
68
|
+
*/ function invertBurleyCdf(u, d) {
|
|
69
|
+
const target = Math.min(Math.max(u, 0), 0.999);
|
|
70
|
+
const cdf = (r)=>1 - 0.25 * Math.exp(-r / d) - 0.75 * Math.exp(-r / (3 * d));
|
|
71
|
+
let lo = 0;
|
|
72
|
+
// The profile has unbounded support; 24d carries >99.9% of the energy.
|
|
73
|
+
let hi = d * 24;
|
|
74
|
+
for(let i = 0; i < 40; i++){
|
|
75
|
+
const mid = (lo + hi) * 0.5;
|
|
76
|
+
if (cdf(mid) < target) {
|
|
77
|
+
lo = mid;
|
|
78
|
+
} else {
|
|
79
|
+
hi = mid;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return (lo + hi) * 0.5;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Pre-integrates a profile into the separable kernel the SSS blur passes sample.
|
|
86
|
+
*
|
|
87
|
+
* Why this runs on the CPU at all: the kernel is a function of the profile and
|
|
88
|
+
* nothing else, profiles change when someone drags a slider, and the alternative
|
|
89
|
+
* is two `exp` calls per tap per channel per pixel per pass. It is also how
|
|
90
|
+
* Unreal does it - the `SSProfiles` texture in a UE capture holds baked weights,
|
|
91
|
+
* not profile parameters - and matching that is the point of the exercise.
|
|
92
|
+
*
|
|
93
|
+
* Sample placement is importance-sampled against the profile's own CDF, so taps
|
|
94
|
+
* cluster where the energy is and thin out in the tail. A uniform placement
|
|
95
|
+
* spends most of its taps on the tail, which is both where the profile is
|
|
96
|
+
* flattest and where the depth-aware rejection is most likely to throw the tap
|
|
97
|
+
* away.
|
|
98
|
+
*
|
|
99
|
+
* @param profile - Profile to bake.
|
|
100
|
+
* @param tapsPerSide - Taps per side; the returned kernel has `n+1` entries.
|
|
101
|
+
* @returns Half the kernel: entry 0 is the centre, entries 1..n walk outwards
|
|
102
|
+
* with increasing positive offsets. Offsets are normalized against the widest
|
|
103
|
+
* channel radius, so the shader scales them by one screen-space radius and
|
|
104
|
+
* mirrors each one.
|
|
105
|
+
*
|
|
106
|
+
* @internal
|
|
107
|
+
*/ function bakeSubsurfaceKernel(profile, tapsPerSide = SSS_KERNEL_TAPS_PER_SIDE) {
|
|
108
|
+
const albedo = profile.surfaceAlbedo;
|
|
109
|
+
const mfpColor = profile.meanFreePathColor;
|
|
110
|
+
const mfpDistance = Math.max(profile.meanFreePathDistance, 0);
|
|
111
|
+
// Per-channel shaping distance. Kept in millimetres throughout: the offsets
|
|
112
|
+
// come out normalized, so the only thing that matters here is the ratio
|
|
113
|
+
// between channels and the ratio of each to the widest.
|
|
114
|
+
const d = [
|
|
115
|
+
Math.max(mfpColor.x, 0) * mfpDistance / burleyScaling(albedo.x),
|
|
116
|
+
Math.max(mfpColor.y, 0) * mfpDistance / burleyScaling(albedo.y),
|
|
117
|
+
Math.max(mfpColor.z, 0) * mfpDistance / burleyScaling(albedo.z)
|
|
118
|
+
];
|
|
119
|
+
const maxD = Math.max(d[0], d[1], d[2]);
|
|
120
|
+
const taps = [];
|
|
121
|
+
if (maxD <= 1e-6) {
|
|
122
|
+
// Degenerate profile: a single centre tap is an exact identity kernel, which
|
|
123
|
+
// is the right answer for "no scattering" and keeps the LUT well-formed.
|
|
124
|
+
taps.push({
|
|
125
|
+
offset: 0,
|
|
126
|
+
weight: [
|
|
127
|
+
1,
|
|
128
|
+
1,
|
|
129
|
+
1
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
for(let i = 0; i < tapsPerSide; i++){
|
|
133
|
+
taps.push({
|
|
134
|
+
offset: 0,
|
|
135
|
+
weight: [
|
|
136
|
+
0,
|
|
137
|
+
0,
|
|
138
|
+
0
|
|
139
|
+
]
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
taps,
|
|
144
|
+
worldRadius: 0
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Importance-sample the widest channel: it is the one that sets the extent, so
|
|
148
|
+
// its CDF is what places taps where any channel still has energy. Sampling
|
|
149
|
+
// each channel's own CDF would need a different offset per channel, which a
|
|
150
|
+
// single texture fetch per tap cannot express.
|
|
151
|
+
const offsets = [
|
|
152
|
+
0
|
|
153
|
+
];
|
|
154
|
+
for(let i = 1; i <= tapsPerSide; i++){
|
|
155
|
+
// Stratified midpoints over the half-profile. The last stratum stops short
|
|
156
|
+
// of 1 because the CDF's inverse diverges there.
|
|
157
|
+
const u = (i - 0.5) / tapsPerSide;
|
|
158
|
+
offsets.push(invertBurleyCdf(u * 0.97, maxD));
|
|
159
|
+
}
|
|
160
|
+
const scale = 1 / offsets[offsets.length - 1];
|
|
161
|
+
const sum = [
|
|
162
|
+
0,
|
|
163
|
+
0,
|
|
164
|
+
0
|
|
165
|
+
];
|
|
166
|
+
const halfWeights = [];
|
|
167
|
+
for(let i = 0; i < offsets.length; i++){
|
|
168
|
+
// Each tap stands for the span between its neighbours' midpoints, so a
|
|
169
|
+
// sparse tail tap carries proportionally more energy than a dense centre
|
|
170
|
+
// one. Without this the tail is under-weighted by exactly the factor the
|
|
171
|
+
// importance sampling spread it by.
|
|
172
|
+
const prev = i > 0 ? offsets[i - 1] : -offsets[1];
|
|
173
|
+
const next = i < offsets.length - 1 ? offsets[i + 1] : offsets[i] + (offsets[i] - prev);
|
|
174
|
+
const span = (next - prev) * 0.5;
|
|
175
|
+
const w = [
|
|
176
|
+
burleyProfile(offsets[i], d[0]) * span,
|
|
177
|
+
burleyProfile(offsets[i], d[1]) * span,
|
|
178
|
+
burleyProfile(offsets[i], d[2]) * span
|
|
179
|
+
];
|
|
180
|
+
halfWeights.push(w);
|
|
181
|
+
// The centre tap appears once, every other tap is mirrored.
|
|
182
|
+
const multiplicity = i === 0 ? 1 : 2;
|
|
183
|
+
sum[0] += w[0] * multiplicity;
|
|
184
|
+
sum[1] += w[1] * multiplicity;
|
|
185
|
+
sum[2] += w[2] * multiplicity;
|
|
186
|
+
}
|
|
187
|
+
const norm = [
|
|
188
|
+
sum[0] > 1e-12 ? 1 / sum[0] : 0,
|
|
189
|
+
sum[1] > 1e-12 ? 1 / sum[1] : 0,
|
|
190
|
+
sum[2] > 1e-12 ? 1 / sum[2] : 0
|
|
191
|
+
];
|
|
192
|
+
for(let i = 0; i <= tapsPerSide; i++){
|
|
193
|
+
const w = halfWeights[i];
|
|
194
|
+
taps.push({
|
|
195
|
+
offset: offsets[i] * scale,
|
|
196
|
+
weight: [
|
|
197
|
+
w[0] * norm[0],
|
|
198
|
+
w[1] * norm[1],
|
|
199
|
+
w[2] * norm[2]
|
|
200
|
+
]
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Offsets were normalized against the outermost tap, so that tap's position -
|
|
204
|
+
// in millimetres - is what ±1 stands for. Converting it here is what keeps the
|
|
205
|
+
// definition of "one radius" in one place.
|
|
206
|
+
return {
|
|
207
|
+
taps,
|
|
208
|
+
worldRadius: offsets[offsets.length - 1] * profile.worldUnitsPerMillimetre
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const tmpExtinction = new Vector3();
|
|
212
|
+
/**
|
|
213
|
+
* Pre-integrates a profile's Beer-Lambert transmission falloff.
|
|
214
|
+
*
|
|
215
|
+
* `T_c(t) = exp(-sigma_c * t)`, where sigma comes from the profile's own mean
|
|
216
|
+
* free path. The channel spread is where the look comes from: for skin the red
|
|
217
|
+
* coefficient is several times smaller than blue's, so light that has crossed a
|
|
218
|
+
* finger or an earlobe arrives red no matter what colour it started as.
|
|
219
|
+
*
|
|
220
|
+
* Samples are spaced geometrically rather than uniformly. The curve is an
|
|
221
|
+
* exponential, so a uniform spacing would spend most of its entries on a tail
|
|
222
|
+
* that has already decayed to nothing while under-resolving the thin end - and
|
|
223
|
+
* the thin end is the only part that is bright enough to see.
|
|
224
|
+
*
|
|
225
|
+
* @param profile - Profile to bake.
|
|
226
|
+
* @param sampleCount - Entries in the returned table.
|
|
227
|
+
* @returns The table and the thickness its last entry stands for.
|
|
228
|
+
*
|
|
229
|
+
* @internal
|
|
230
|
+
*/ function bakeTransmissionLUT(profile, sampleCount = SSS_TRANSMISSION_SAMPLES) {
|
|
231
|
+
const sigma = profile.getExtinctionCoefficient(tmpExtinction);
|
|
232
|
+
// Range out to where even the least-absorbed channel has gone dark. exp(-8) is
|
|
233
|
+
// about 3e-4, which is below anything an 8-bit display resolves, so carrying
|
|
234
|
+
// the table further would only add entries that are all zero.
|
|
235
|
+
const minSigma = Math.max(Math.min(sigma.x, sigma.y, sigma.z), 1e-6);
|
|
236
|
+
const maxThickness = 8 / minSigma;
|
|
237
|
+
const samples = [];
|
|
238
|
+
for(let i = 0; i < sampleCount; i++){
|
|
239
|
+
// Geometric from a small fraction of the range up to all of it, with the
|
|
240
|
+
// first entry pinned at zero thickness so the table starts at full
|
|
241
|
+
// transmission exactly rather than nearly.
|
|
242
|
+
const t = i === 0 ? 0 : maxThickness * Math.pow(SSS_TRANSMISSION_MIN_RATIO, 1 - (i - 1) / Math.max(sampleCount - 2, 1));
|
|
243
|
+
samples.push([
|
|
244
|
+
Math.exp(-Math.min(sigma.x * t, 80)),
|
|
245
|
+
Math.exp(-Math.min(sigma.y * t, 80)),
|
|
246
|
+
Math.exp(-Math.min(sigma.z * t, 80))
|
|
247
|
+
]);
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
samples,
|
|
251
|
+
maxThickness
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Ratio of the thinnest non-zero entry in the transmission table to the thickest.
|
|
256
|
+
*
|
|
257
|
+
* Exported because the shader has to invert the baker's spacing to look the
|
|
258
|
+
* table up, and the two are one mapping written twice: a reader that assumed
|
|
259
|
+
* uniform spacing would find the right table at the wrong index.
|
|
260
|
+
*
|
|
261
|
+
* @internal
|
|
262
|
+
*/ const SSS_TRANSMISSION_MIN_RATIO = 1 / 512;
|
|
263
|
+
|
|
264
|
+
export { SSS_KERNEL_LUT_HEADER_COLUMNS, SSS_KERNEL_TAPS, SSS_KERNEL_TAPS_PER_SIDE, SSS_TRANSMISSION_MIN_RATIO, SSS_TRANSMISSION_SAMPLES, bakeSubsurfaceKernel, bakeTransmissionLUT };
|
|
265
|
+
//# sourceMappingURL=sss_kernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sss_kernel.js","sources":["../../src/material/sss_kernel.ts"],"sourcesContent":["import { Vector3 } from '@zephyr3d/base';\nimport type { SubsurfaceProfile } from './subsurfaceprofile';\n\n/**\n * Taps stored per profile in the kernel LUT, per side of the kernel centre.\n *\n * The full separable kernel is `2 * SSS_KERNEL_TAPS_PER_SIDE + 1` wide. Unreal's\n * separable path uses 13 + 9 + 6 taps across its three kernels; this is the same\n * order of magnitude, and the quality presets stride across it rather than\n * baking a different table per preset.\n */\nexport const SSS_KERNEL_TAPS_PER_SIDE = 15;\n\n/**\n * Entries in a baked kernel row: the centre tap plus one side.\n *\n * Only half the kernel is stored because it is symmetric about its centre and\n * the shader mirrors each tap as it walks outwards. The weights are normalized\n * for the *full* mirrored kernel, so a consumer that does not mirror would come\n * out half as bright.\n */\nexport const SSS_KERNEL_TAPS = SSS_KERNEL_TAPS_PER_SIDE + 1;\n\n/** One pre-integrated tap: where to sample, and how much of each channel to take. */\nexport interface SubsurfaceKernelTap {\n /** Offset from the kernel centre, normalized so 1 is the profile's widest channel radius. */\n offset: number;\n /** Per-channel weight, normalized so the full mirrored kernel sums to one per channel. */\n weight: [number, number, number];\n}\n\n/** A baked kernel and the world-space distance its normalized offsets are measured against. */\nexport interface SubsurfaceKernel {\n taps: SubsurfaceKernelTap[];\n /**\n * World-space distance corresponding to a normalized offset of 1 - the radius\n * the blur pass projects into screen space. Returned alongside the taps rather\n * than recomputed by the caller so the two cannot disagree about what ±1 means.\n */\n worldRadius: number;\n}\n\n/**\n * Entries in a baked transmission table.\n *\n * Unreal's own is 32 wide, which its capture shows holding a per-channel\n * Beer-Lambert falloff sampled across thickness. Matching the width is not the\n * point - it is simply enough resolution for a curve this smooth.\n */\nexport const SSS_TRANSMISSION_SAMPLES = 32;\n\n/**\n * Columns of the kernel LUT that precede the baked taps.\n *\n * One, holding `(diffusionWorldRadius, transmissionMaxThickness, 0, 0)` - the\n * two scales the rest of the row is measured against. Named because the baker\n * writes it and the shader reads it, and an off-by-one between them silently\n * reads a weight as a radius.\n */\nexport const SSS_KERNEL_LUT_HEADER_COLUMNS = 1;\n\n/** A baked transmission table and the thickness range it spans. */\nexport interface SubsurfaceTransmission {\n /** `exp(-sigma * t)` per channel, from `t = 0` out to `maxThickness`. */\n samples: Array<[number, number, number]>;\n /**\n * Thickness, in world units, at which the table ends. The shader normalizes\n * its measured thickness against this before looking up, so it is what the\n * last entry means.\n */\n maxThickness: number;\n}\n\n/**\n * Christensen-Burley shaping parameter.\n *\n * The \"diffusion\" fit rather than the \"searchlight\" one, matching what Unreal\n * uses: searchlight is the better match to ground truth for a pencil beam, but\n * diffusion is what a screen-space pass actually approximates, and mixing the\n * two is how a profile ends up looking right in isolation and wrong in a scene.\n */\nfunction burleyScaling(albedo: number): number {\n const a = Math.min(Math.max(albedo, 0), 1);\n return 1.9 - a + 3.5 * (a - 0.8) * (a - 0.8);\n}\n\n/**\n * Radially symmetric Burley reflectance profile, without the `1/r` Jacobian.\n *\n * `R(r) = (e^(-r/d) + e^(-r/(3d))) / (8*pi*d*r)`\n *\n * The `1/r` term converts the 1D profile into a 2D disc density. A separable\n * screen-space blur integrates along a line rather than over a disc, so it is\n * dropped and the weights are renormalized by their own sum instead - the same\n * approximation `burleyDiffusionWeight` in `shaders/diffusion.ts` documents, and\n * it has to be the same one or the two paths would disagree about what a profile\n * means. The constant factor goes with it, since normalization removes it.\n */\nfunction burleyProfile(r: number, d: number): number {\n const safeD = Math.max(d, 1e-6);\n const x = Math.abs(r) / safeD;\n return (Math.exp(-Math.min(x, 40)) + Math.exp(-Math.min(x / 3, 40))) / safeD;\n}\n\n/**\n * Inverse of the Burley CDF, `F(r) = 1 - e^(-r/d)/4 - 3*e^(-r/(3d))/4`.\n *\n * Solved by bisection rather than Newton: the derivative is well behaved but the\n * CDF flattens hard in the tail, and a Newton step from a poor bracket there\n * overshoots into negative radii. This runs once per profile change, so twenty\n * bisection steps cost nothing worth optimizing.\n */\nfunction invertBurleyCdf(u: number, d: number): number {\n const target = Math.min(Math.max(u, 0), 0.999);\n const cdf = (r: number) => 1 - 0.25 * Math.exp(-r / d) - 0.75 * Math.exp(-r / (3 * d));\n let lo = 0;\n // The profile has unbounded support; 24d carries >99.9% of the energy.\n let hi = d * 24;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) * 0.5;\n if (cdf(mid) < target) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n return (lo + hi) * 0.5;\n}\n\n/**\n * Pre-integrates a profile into the separable kernel the SSS blur passes sample.\n *\n * Why this runs on the CPU at all: the kernel is a function of the profile and\n * nothing else, profiles change when someone drags a slider, and the alternative\n * is two `exp` calls per tap per channel per pixel per pass. It is also how\n * Unreal does it - the `SSProfiles` texture in a UE capture holds baked weights,\n * not profile parameters - and matching that is the point of the exercise.\n *\n * Sample placement is importance-sampled against the profile's own CDF, so taps\n * cluster where the energy is and thin out in the tail. A uniform placement\n * spends most of its taps on the tail, which is both where the profile is\n * flattest and where the depth-aware rejection is most likely to throw the tap\n * away.\n *\n * @param profile - Profile to bake.\n * @param tapsPerSide - Taps per side; the returned kernel has `n+1` entries.\n * @returns Half the kernel: entry 0 is the centre, entries 1..n walk outwards\n * with increasing positive offsets. Offsets are normalized against the widest\n * channel radius, so the shader scales them by one screen-space radius and\n * mirrors each one.\n *\n * @internal\n */\nexport function bakeSubsurfaceKernel(\n profile: SubsurfaceProfile,\n tapsPerSide = SSS_KERNEL_TAPS_PER_SIDE\n): SubsurfaceKernel {\n const albedo = profile.surfaceAlbedo;\n const mfpColor = profile.meanFreePathColor;\n const mfpDistance = Math.max(profile.meanFreePathDistance, 0);\n\n // Per-channel shaping distance. Kept in millimetres throughout: the offsets\n // come out normalized, so the only thing that matters here is the ratio\n // between channels and the ratio of each to the widest.\n const d: [number, number, number] = [\n (Math.max(mfpColor.x, 0) * mfpDistance) / burleyScaling(albedo.x),\n (Math.max(mfpColor.y, 0) * mfpDistance) / burleyScaling(albedo.y),\n (Math.max(mfpColor.z, 0) * mfpDistance) / burleyScaling(albedo.z)\n ];\n const maxD = Math.max(d[0], d[1], d[2]);\n const taps: SubsurfaceKernelTap[] = [];\n\n if (maxD <= 1e-6) {\n // Degenerate profile: a single centre tap is an exact identity kernel, which\n // is the right answer for \"no scattering\" and keeps the LUT well-formed.\n taps.push({ offset: 0, weight: [1, 1, 1] });\n for (let i = 0; i < tapsPerSide; i++) {\n taps.push({ offset: 0, weight: [0, 0, 0] });\n }\n return { taps, worldRadius: 0 };\n }\n\n // Importance-sample the widest channel: it is the one that sets the extent, so\n // its CDF is what places taps where any channel still has energy. Sampling\n // each channel's own CDF would need a different offset per channel, which a\n // single texture fetch per tap cannot express.\n const offsets: number[] = [0];\n for (let i = 1; i <= tapsPerSide; i++) {\n // Stratified midpoints over the half-profile. The last stratum stops short\n // of 1 because the CDF's inverse diverges there.\n const u = (i - 0.5) / tapsPerSide;\n offsets.push(invertBurleyCdf(u * 0.97, maxD));\n }\n\n const scale = 1 / offsets[offsets.length - 1];\n const sum: [number, number, number] = [0, 0, 0];\n const halfWeights: Array<[number, number, number]> = [];\n\n for (let i = 0; i < offsets.length; i++) {\n // Each tap stands for the span between its neighbours' midpoints, so a\n // sparse tail tap carries proportionally more energy than a dense centre\n // one. Without this the tail is under-weighted by exactly the factor the\n // importance sampling spread it by.\n const prev = i > 0 ? offsets[i - 1] : -offsets[1];\n const next = i < offsets.length - 1 ? offsets[i + 1] : offsets[i] + (offsets[i] - prev);\n const span = (next - prev) * 0.5;\n const w: [number, number, number] = [\n burleyProfile(offsets[i], d[0]) * span,\n burleyProfile(offsets[i], d[1]) * span,\n burleyProfile(offsets[i], d[2]) * span\n ];\n halfWeights.push(w);\n // The centre tap appears once, every other tap is mirrored.\n const multiplicity = i === 0 ? 1 : 2;\n sum[0] += w[0] * multiplicity;\n sum[1] += w[1] * multiplicity;\n sum[2] += w[2] * multiplicity;\n }\n\n const norm: [number, number, number] = [\n sum[0] > 1e-12 ? 1 / sum[0] : 0,\n sum[1] > 1e-12 ? 1 / sum[1] : 0,\n sum[2] > 1e-12 ? 1 / sum[2] : 0\n ];\n\n for (let i = 0; i <= tapsPerSide; i++) {\n const w = halfWeights[i];\n taps.push({\n offset: offsets[i] * scale,\n weight: [w[0] * norm[0], w[1] * norm[1], w[2] * norm[2]]\n });\n }\n\n // Offsets were normalized against the outermost tap, so that tap's position -\n // in millimetres - is what ±1 stands for. Converting it here is what keeps the\n // definition of \"one radius\" in one place.\n return { taps, worldRadius: offsets[offsets.length - 1] * profile.worldUnitsPerMillimetre };\n}\n\nconst tmpExtinction = new Vector3();\n\n/**\n * Pre-integrates a profile's Beer-Lambert transmission falloff.\n *\n * `T_c(t) = exp(-sigma_c * t)`, where sigma comes from the profile's own mean\n * free path. The channel spread is where the look comes from: for skin the red\n * coefficient is several times smaller than blue's, so light that has crossed a\n * finger or an earlobe arrives red no matter what colour it started as.\n *\n * Samples are spaced geometrically rather than uniformly. The curve is an\n * exponential, so a uniform spacing would spend most of its entries on a tail\n * that has already decayed to nothing while under-resolving the thin end - and\n * the thin end is the only part that is bright enough to see.\n *\n * @param profile - Profile to bake.\n * @param sampleCount - Entries in the returned table.\n * @returns The table and the thickness its last entry stands for.\n *\n * @internal\n */\nexport function bakeTransmissionLUT(\n profile: SubsurfaceProfile,\n sampleCount = SSS_TRANSMISSION_SAMPLES\n): SubsurfaceTransmission {\n const sigma = profile.getExtinctionCoefficient(tmpExtinction);\n // Range out to where even the least-absorbed channel has gone dark. exp(-8) is\n // about 3e-4, which is below anything an 8-bit display resolves, so carrying\n // the table further would only add entries that are all zero.\n const minSigma = Math.max(Math.min(sigma.x, sigma.y, sigma.z), 1e-6);\n const maxThickness = 8 / minSigma;\n const samples: Array<[number, number, number]> = [];\n\n for (let i = 0; i < sampleCount; i++) {\n // Geometric from a small fraction of the range up to all of it, with the\n // first entry pinned at zero thickness so the table starts at full\n // transmission exactly rather than nearly.\n const t =\n i === 0\n ? 0\n : maxThickness * Math.pow(SSS_TRANSMISSION_MIN_RATIO, 1 - (i - 1) / Math.max(sampleCount - 2, 1));\n samples.push([\n Math.exp(-Math.min(sigma.x * t, 80)),\n Math.exp(-Math.min(sigma.y * t, 80)),\n Math.exp(-Math.min(sigma.z * t, 80))\n ]);\n }\n\n return { samples, maxThickness };\n}\n\n/**\n * Ratio of the thinnest non-zero entry in the transmission table to the thickest.\n *\n * Exported because the shader has to invert the baker's spacing to look the\n * table up, and the two are one mapping written twice: a reader that assumed\n * uniform spacing would find the right table at the wrong index.\n *\n * @internal\n */\nexport const SSS_TRANSMISSION_MIN_RATIO = 1 / 512;\n"],"names":["SSS_KERNEL_TAPS_PER_SIDE","SSS_KERNEL_TAPS","SSS_TRANSMISSION_SAMPLES","SSS_KERNEL_LUT_HEADER_COLUMNS","burleyScaling","albedo","a","Math","min","max","burleyProfile","r","d","safeD","x","abs","exp","invertBurleyCdf","u","target","cdf","lo","hi","i","mid","bakeSubsurfaceKernel","profile","tapsPerSide","surfaceAlbedo","mfpColor","meanFreePathColor","mfpDistance","meanFreePathDistance","y","z","maxD","taps","push","offset","weight","worldRadius","offsets","scale","length","sum","halfWeights","prev","next","span","w","multiplicity","norm","worldUnitsPerMillimetre","tmpExtinction","Vector3","bakeTransmissionLUT","sampleCount","sigma","getExtinctionCoefficient","minSigma","maxThickness","samples","t","pow","SSS_TRANSMISSION_MIN_RATIO"],"mappings":"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"}
|