@woosh/meep-engine 3.11.1 → 3.11.3
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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +294 -290
- package/src/engine/graphics3/ParticipatingMedia.d.ts +111 -0
- package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMedia.js +203 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +34 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +73 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +87 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.js +184 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts +16 -2
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +28 -4
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +5 -2
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +564 -451
- package/src/shade/device/ShadeGPUCommandContext.d.ts +18 -2
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +994 -940
- package/src/shade/device/immediate_data_supported.d.ts +33 -0
- package/src/shade/device/immediate_data_supported.d.ts.map +1 -0
- package/src/shade/device/immediate_data_supported.js +53 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts +18 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.js +24 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.js +49 -1
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +20 -2
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts +65 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts.map +1 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.js +160 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +50 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts +11 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts.map +1 -0
- package/src/shade/device/mock/pipeline_immediate_size.js +18 -0
- package/src/shade/device/pipeline/PipelineLayoutManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/PipelineLayoutManager.js +1 -0
- package/src/shade/playground/volumetrics_froxel/README.md +104 -1
- package/src/shade/playground/volumetrics_froxel/index.html +20 -1
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +298 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts +119 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -0
- package/src/shade/playground/volumetrics_froxel/measure.js +559 -0
- package/src/shade/renderer/GraphicsContext.d.ts +9 -2
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +13 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +22 -18
- package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/GPUSky.js +145 -142
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +34 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +36 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts +20 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.js +25 -0
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +14 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +163 -177
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts +20 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.js +46 -0
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts +11 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.js +57 -27
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts +19 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.js +69 -33
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.js +35 -35
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.js +38 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts +17 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.js +29 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts +21 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.js +42 -0
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts +2 -2
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +165 -84
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +215 -204
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +79 -67
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +6 -2
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +4 -0
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +341 -345
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +7 -3
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +77 -81
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +5 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +6 -2
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +4 -1
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/ShaderDescriptor.js +26 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.js +32 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts +7 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.js +17 -6
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.js +69 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.js +41 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.js +15 -19
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.js +44 -0
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.js +1 -4
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +7 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.js +37 -2
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.js +6 -0
- package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.js +1 -1
- package/src/shade/renderer/shader/graph/compute/graph_compute_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_image_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.js +7 -0
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts +3 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.js +12 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts +21 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts.map +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.js +21 -0
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts +59 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +195 -2
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts +14 -0
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts.map +1 -0
- package/src/shade/renderer/shader/type/type_has_arrays.js +33 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts +14 -13
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +133 -129
- package/src/shade/renderer/view/GPUViewSkyContext.d.ts.map +1 -1
- package/src/shade/renderer/view/GPUViewSkyContext.js +169 -173
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +480 -315
- package/src/shade/renderer/volumetrics/NOTES.md +887 -8
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +5 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +21 -2
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +26 -0
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/SceneVolumetrics.js +64 -21
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js +84 -28
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts +98 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.js +111 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts +84 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js +252 -0
- package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.js +75 -75
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts +43 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.js +145 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +20 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +48 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts +38 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.js +130 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +18 -3
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +193 -70
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +16 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +83 -15
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +29 -18
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +260 -260
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts +58 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +290 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +25 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/CPUBitmapData.js +33 -0
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +2228 -2215
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +210 -2
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts +69 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts.map +1 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.js +148 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts +16 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/cpu_texture_sample.js +176 -172
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts +0 -2
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts.map +0 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.js +0 -1
|
@@ -1,316 +1,481 @@
|
|
|
1
|
-
import { GPUTypedBuffer } from "../buffer/GPUTypedBuffer.js";
|
|
2
|
-
import { graph_compute_pass } from "../shader/graph/compute/graph_compute_pass.js";
|
|
3
|
-
import { graph_import_buffer } from "../shader/graph/graph_import_buffer.js";
|
|
4
|
-
import { graph_import_texture } from "../shader/graph/graph_import_texture.js";
|
|
5
|
-
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
6
|
-
import { update_frustum_far_plane } from "../shadow/map/update_frustum_far_plane.js";
|
|
7
|
-
import { slice_flat_array } from "../util/slice_flat_array.js";
|
|
8
|
-
import { build_light_cluster_parameters } from "../light/cluster/build_light_cluster_parameters.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.#taa_enabled
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
* @
|
|
102
|
-
* @
|
|
103
|
-
*/
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
1
|
+
import { GPUTypedBuffer } from "../buffer/GPUTypedBuffer.js";
|
|
2
|
+
import { graph_compute_pass } from "../shader/graph/compute/graph_compute_pass.js";
|
|
3
|
+
import { graph_import_buffer } from "../shader/graph/graph_import_buffer.js";
|
|
4
|
+
import { graph_import_texture } from "../shader/graph/graph_import_texture.js";
|
|
5
|
+
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
6
|
+
import { update_frustum_far_plane } from "../shadow/map/update_frustum_far_plane.js";
|
|
7
|
+
import { slice_flat_array } from "../util/slice_flat_array.js";
|
|
8
|
+
import { build_light_cluster_parameters } from "../light/cluster/build_light_cluster_parameters.js";
|
|
9
|
+
import {
|
|
10
|
+
build_volumetrics_sun_shadow_transform,
|
|
11
|
+
volumetrics_sun_shadow_cascade_far
|
|
12
|
+
} from "./build_volumetrics_sun_shadow_transform.js";
|
|
13
|
+
import { graph_build_volumetrics } from "./graph_build_volumetrics.js";
|
|
14
|
+
import {
|
|
15
|
+
VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT,
|
|
16
|
+
VOLUMETRICS_SUN_SHADOW_CASCADE_RATIO,
|
|
17
|
+
VOLUMETRICS_SUN_SHADOW_LIGHT_NONE,
|
|
18
|
+
VOLUMETRICS_SUN_SHADOW_RESOLUTION
|
|
19
|
+
} from "./VOLUMETRICS_SUN_SHADOW_RESOLUTION.js";
|
|
20
|
+
import { shader_volumetrics_taa } from "./taa/shader_volumetrics_taa.js";
|
|
21
|
+
import { VOLUMETRICS_METADATA_STRUCT } from "./VOLUMETRICS_METADATA_STRUCT.js";
|
|
22
|
+
import { VOLUMETRICS_RESOLUTION_Z } from "./VOLUMETRICS_RESOLUTION_Z.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* resolution of a single froxel in XY, in pixels
|
|
26
|
+
*/
|
|
27
|
+
const TILE_SIZE = 8;
|
|
28
|
+
|
|
29
|
+
export class GPUViewVolumetrics {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @type {GPUViewContext}
|
|
33
|
+
*/
|
|
34
|
+
#view
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* NOTE: Initialized in the constructor
|
|
38
|
+
* @type {GPUTextureContext[]}
|
|
39
|
+
*/
|
|
40
|
+
#volumetrics_textures = [];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Should we perform temporal integration, or not?
|
|
44
|
+
* If set to true - the next update will discard history.
|
|
45
|
+
* Useful for significant scene transitions and screen resizing.
|
|
46
|
+
* @type {boolean}
|
|
47
|
+
*/
|
|
48
|
+
#reset_history = true;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether to run the 3D temporal reprojection (volumetric TAA) over the per-froxel scattering
|
|
52
|
+
* volume. When disabled, the aerial pass integrates the raw (noisier) scattering LUT directly —
|
|
53
|
+
* a safe fallback if temporal artifacts appear.
|
|
54
|
+
* @type {boolean}
|
|
55
|
+
*/
|
|
56
|
+
#taa_enabled = true;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @returns {boolean}
|
|
60
|
+
*/
|
|
61
|
+
get taa_enabled() {
|
|
62
|
+
return this.#taa_enabled;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {boolean} v
|
|
67
|
+
*/
|
|
68
|
+
set taa_enabled(v) {
|
|
69
|
+
if (v === this.#taa_enabled) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.#taa_enabled = v;
|
|
73
|
+
// re-enabling must not blend against a stale / never-written history texture
|
|
74
|
+
this.#reset_history = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* View-space distance at which the froxel grid ends and the aerial pass switches to a direct
|
|
79
|
+
* RDR2-style volume ray-march. Clamped to camera.far at upload, so the default (Infinity) means
|
|
80
|
+
* "grid covers the whole range" and the far march is a no-op.
|
|
81
|
+
* @type {number}
|
|
82
|
+
*/
|
|
83
|
+
#froxel_far = Infinity;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @returns {number}
|
|
87
|
+
*/
|
|
88
|
+
get froxel_far() {
|
|
89
|
+
return this.#froxel_far;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {number} v
|
|
94
|
+
*/
|
|
95
|
+
set froxel_far(v) {
|
|
96
|
+
this.#froxel_far = v;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Q-04. World -> volume and back for each cascade, innermost first, rebuilt every frame by
|
|
101
|
+
* {@link build_volumetrics_sun_shadow_transform} and uploaded in the metadata.
|
|
102
|
+
* @type {Float32Array[]}
|
|
103
|
+
*/
|
|
104
|
+
#sun_shadow_ws_to_uvw = Array.from({ length: VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT }, () => new Float32Array(16));
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @type {Float32Array[]}
|
|
108
|
+
*/
|
|
109
|
+
#sun_shadow_uvw_to_ws = Array.from({ length: VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT }, () => new Float32Array(16));
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Voxel counts one sun optical-depth cascade is dispatched at this frame. Collapses to
|
|
113
|
+
* `[1, 1, 1]` when the froxels are marching instead, so the passes stay in the frame graph and
|
|
114
|
+
* cost nothing — see `graph_build_sun_shadow_volume` for why they stay rather than going.
|
|
115
|
+
* @type {number[]}
|
|
116
|
+
*/
|
|
117
|
+
#sun_shadow_resolution = [1, 1, 1];
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* World-space size of one voxel along the sun axis per cascade, i.e. each scan's step, packed
|
|
121
|
+
* for the `vec4f` the metadata carries.
|
|
122
|
+
* @type {Float32Array}
|
|
123
|
+
*/
|
|
124
|
+
#sun_shadow_step_ws = new Float32Array(4);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Which directional light this frame's cascades were built for, or
|
|
128
|
+
* {@link VOLUMETRICS_SUN_SHADOW_LIGHT_NONE} when there was nothing to build for.
|
|
129
|
+
* @type {number}
|
|
130
|
+
*/
|
|
131
|
+
#sun_shadow_light_index = VOLUMETRICS_SUN_SHADOW_LIGHT_NONE;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* View depth each cascade covers out to, packed the same way. Trailing lanes repeat the
|
|
135
|
+
* outermost so a read past the end of the ladder still lands on a real cascade.
|
|
136
|
+
* @type {Float32Array}
|
|
137
|
+
*/
|
|
138
|
+
#sun_shadow_cascade_far = new Float32Array(4);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @type {GPUTypedBuffer}
|
|
142
|
+
*/
|
|
143
|
+
#metadata;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @type {GPUDevice}
|
|
147
|
+
*/
|
|
148
|
+
#device
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
*
|
|
152
|
+
* @param {GPUViewContext} view
|
|
153
|
+
* @param {GPUDevice} device
|
|
154
|
+
*/
|
|
155
|
+
constructor(view, device) {
|
|
156
|
+
this.#device = device;
|
|
157
|
+
this.#view = view;
|
|
158
|
+
|
|
159
|
+
// initialize textures
|
|
160
|
+
for (let i = 0; i < 2; i++) {
|
|
161
|
+
const texture = new GPUTextureContext(device);
|
|
162
|
+
|
|
163
|
+
texture.descriptor.format = "rgba16float";
|
|
164
|
+
texture.descriptor.dimension = "3d";
|
|
165
|
+
texture.descriptor.usage = GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING;
|
|
166
|
+
|
|
167
|
+
this.#volumetrics_textures[i] = texture;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.#metadata = GPUTypedBuffer.create({
|
|
171
|
+
type: VOLUMETRICS_METADATA_STRUCT,
|
|
172
|
+
device,
|
|
173
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
destroy() {
|
|
179
|
+
|
|
180
|
+
const textures = this.#volumetrics_textures;
|
|
181
|
+
|
|
182
|
+
for (let i = 0; i < 2; i++) {
|
|
183
|
+
|
|
184
|
+
textures[i].destroy();
|
|
185
|
+
|
|
186
|
+
textures[i] = null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
#update_resolution() {
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
const screen_resolution = this.#view.resolution;
|
|
195
|
+
|
|
196
|
+
const output_resolution_x = Math.ceil(screen_resolution[0] / TILE_SIZE);
|
|
197
|
+
const output_resolution_y = Math.ceil(screen_resolution[1] / TILE_SIZE);
|
|
198
|
+
|
|
199
|
+
const t_first = this.#volumetrics_textures[0];
|
|
200
|
+
|
|
201
|
+
if (t_first.width === output_resolution_x
|
|
202
|
+
&& t_first.height === output_resolution_y
|
|
203
|
+
) {
|
|
204
|
+
// already at the right resolution
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
for (let i = 0; i < 2; i++) {
|
|
209
|
+
|
|
210
|
+
this.#volumetrics_textures[i].resize(
|
|
211
|
+
output_resolution_x,
|
|
212
|
+
output_resolution_y,
|
|
213
|
+
VOLUMETRICS_RESOLUTION_Z
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// drop history
|
|
219
|
+
this.#reset_history = true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Place this frame's sun optical-depth cascades, and say which light they cover.
|
|
224
|
+
*
|
|
225
|
+
* This is how the sun's media self-shadowing is computed — there is no second path to select
|
|
226
|
+
* between. The march in `chunk_integrate_optical_depth` remains for the lights the cascades do
|
|
227
|
+
* not cover: every point and spot light, whose rays are short enough that there is little to
|
|
228
|
+
* amortize, and any directional light past the first, since there is one ladder of boxes and it
|
|
229
|
+
* is aligned to one direction. Two situations leave the cascades covering nothing at all, and
|
|
230
|
+
* `VOLUMETRICS_SUN_SHADOW_LIGHT_NONE` is how they say so.
|
|
231
|
+
*
|
|
232
|
+
* The light is the first entry of the `light_directional` table, which is the first
|
|
233
|
+
* `DirectionalLight` in scene order — `GPULightCollection.#build` packs them in that order, so
|
|
234
|
+
* walking the same list here recovers the same index. In practice a scene has one sun.
|
|
235
|
+
*
|
|
236
|
+
* Every cascade is placed by the same call with a different `far`, which is what makes the
|
|
237
|
+
* stability argument transfer: each box is sized from the bounding sphere of the sub-frustum it
|
|
238
|
+
* covers, that sphere is a function of the projection alone, and the origin is snapped to whole
|
|
239
|
+
* voxels — so each cascade's world-space lattice is the same set of points from frame to frame
|
|
240
|
+
* no matter how the camera moves.
|
|
241
|
+
*
|
|
242
|
+
* @returns {number} the light index the cascades cover, or the sentinel
|
|
243
|
+
*/
|
|
244
|
+
#update_sun_shadow() {
|
|
245
|
+
const camera = this.#view.camera.camera;
|
|
246
|
+
|
|
247
|
+
// One voxel per cascade rather than no pass at all: the lighting pass binds these textures
|
|
248
|
+
// unconditionally and WebGPU has no optional bindings. Nothing samples them, because the
|
|
249
|
+
// sentinel below matches no light index.
|
|
250
|
+
this.#sun_shadow_resolution = [1, 1, 1];
|
|
251
|
+
|
|
252
|
+
// an orthographic view has no fov to derive a bounding sphere from, and no volumetrics
|
|
253
|
+
// camera path that reaches here today — bail rather than invent one
|
|
254
|
+
if (typeof camera.fov !== "number") {
|
|
255
|
+
return VOLUMETRICS_SUN_SHADOW_LIGHT_NONE;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const lights = this.#view.scene.lights.source.elements;
|
|
259
|
+
|
|
260
|
+
let sun = null;
|
|
261
|
+
|
|
262
|
+
for (let i = 0; i < lights.length; i++) {
|
|
263
|
+
if (lights[i].isDirectionalLight === true) {
|
|
264
|
+
sun = lights[i];
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (sun === null) {
|
|
270
|
+
return VOLUMETRICS_SUN_SHADOW_LIGHT_NONE;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const resolution = VOLUMETRICS_SUN_SHADOW_RESOLUTION;
|
|
274
|
+
|
|
275
|
+
// `forward` is the direction light TRAVELS — the same vector light_record_directional
|
|
276
|
+
// writes into the table, which the shader then negates to point at the light.
|
|
277
|
+
const direction = sun.forward;
|
|
278
|
+
|
|
279
|
+
const view_matrix = camera.view_matrix;
|
|
280
|
+
const position = camera.transform.position;
|
|
281
|
+
|
|
282
|
+
// the medium lives in the froxel grid and the grid stops here, so there is nothing to
|
|
283
|
+
// integrate past it
|
|
284
|
+
const far = Math.min(this.#froxel_far, camera.far);
|
|
285
|
+
|
|
286
|
+
const cascade_count = VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT;
|
|
287
|
+
const cascade_ratio = VOLUMETRICS_SUN_SHADOW_CASCADE_RATIO;
|
|
288
|
+
|
|
289
|
+
// the view matrix's z row, negated: view space looks down -Z, and the row is unit length
|
|
290
|
+
// because the linear part is a rotation
|
|
291
|
+
const camera_forward = [-view_matrix[2], -view_matrix[6], -view_matrix[10]];
|
|
292
|
+
|
|
293
|
+
for (let cascade = 0; cascade < cascade_count; cascade++) {
|
|
294
|
+
|
|
295
|
+
const cascade_far = volumetrics_sun_shadow_cascade_far(far, cascade, cascade_count, cascade_ratio);
|
|
296
|
+
|
|
297
|
+
this.#sun_shadow_step_ws[cascade] = build_volumetrics_sun_shadow_transform({
|
|
298
|
+
ws_to_uvw: this.#sun_shadow_ws_to_uvw[cascade],
|
|
299
|
+
uvw_to_ws: this.#sun_shadow_uvw_to_ws[cascade],
|
|
300
|
+
light_direction: [direction.x, direction.y, direction.z],
|
|
301
|
+
camera_position: [position.x, position.y, position.z],
|
|
302
|
+
camera_forward,
|
|
303
|
+
fov_y: camera.fov,
|
|
304
|
+
aspect: camera.aspect,
|
|
305
|
+
near: camera.near,
|
|
306
|
+
far: cascade_far,
|
|
307
|
+
resolution,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
this.#sun_shadow_cascade_far[cascade] = cascade_far;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Trailing lanes repeat the outermost cascade rather than holding zero: the read side walks
|
|
314
|
+
// the ladder comparing view depth against these, and a zero would read as a cascade that
|
|
315
|
+
// ends at the camera.
|
|
316
|
+
for (let lane = cascade_count; lane < 4; lane++) {
|
|
317
|
+
this.#sun_shadow_cascade_far[lane] = far;
|
|
318
|
+
this.#sun_shadow_step_ws[lane] = this.#sun_shadow_step_ws[cascade_count - 1];
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
this.#sun_shadow_resolution = resolution;
|
|
322
|
+
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
#update_metadata() {
|
|
327
|
+
const view = this.#view;
|
|
328
|
+
const camera = view.camera;
|
|
329
|
+
|
|
330
|
+
const resolution = this.#volumetrics_textures[0].size;
|
|
331
|
+
|
|
332
|
+
this.#sun_shadow_light_index = this.#update_sun_shadow();
|
|
333
|
+
|
|
334
|
+
const volumetrics_cluster_parameters = new Float32Array(3);
|
|
335
|
+
|
|
336
|
+
// The depth-curve `scale` must grow with the slice count. The hard-coded 4.06 was tuned for
|
|
337
|
+
// the light-cluster grid (24 slices); reusing it with 64 froxel slices collapses the log
|
|
338
|
+
// curve so ~half the slices bunch into the first fraction of a unit of depth, leaving almost
|
|
339
|
+
// none for the actual scene. Derive scale for a log-uniform distribution over
|
|
340
|
+
// [near + near_offset, far] instead (gives O ~= 0, i.e. depth ~ offset * (far/offset)^(s/(N-1))).
|
|
341
|
+
const NEAR_OFFSET = 0.1;
|
|
342
|
+
const depth_offset = camera.camera.near + NEAR_OFFSET;
|
|
343
|
+
const depth_scale = (VOLUMETRICS_RESOLUTION_Z - 1) / Math.log2(camera.camera.far / depth_offset);
|
|
344
|
+
|
|
345
|
+
build_light_cluster_parameters(
|
|
346
|
+
volumetrics_cluster_parameters,
|
|
347
|
+
0,
|
|
348
|
+
VOLUMETRICS_RESOLUTION_Z,
|
|
349
|
+
camera.camera.near,
|
|
350
|
+
camera.camera.far,
|
|
351
|
+
NEAR_OFFSET,
|
|
352
|
+
depth_scale
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
// Froxel-grid curve: same construction but ending at froxel_far (<= camera.far). The grid's
|
|
356
|
+
// slices pack into [near, froxel_far] for extra near detail; beyond froxel_far the aerial
|
|
357
|
+
// pass ray-marches the volumes. froxel_far == camera.far -> identical to the LUT curve (no-op).
|
|
358
|
+
const froxel_far = Math.min(this.#froxel_far, camera.camera.far);
|
|
359
|
+
const froxel_depth_scale = (VOLUMETRICS_RESOLUTION_Z - 1) / Math.log2(froxel_far / depth_offset);
|
|
360
|
+
const volumetrics_froxel_cluster_parameters = new Float32Array(3);
|
|
361
|
+
build_light_cluster_parameters(
|
|
362
|
+
volumetrics_froxel_cluster_parameters,
|
|
363
|
+
0,
|
|
364
|
+
VOLUMETRICS_RESOLUTION_Z,
|
|
365
|
+
camera.camera.near,
|
|
366
|
+
froxel_far,
|
|
367
|
+
NEAR_OFFSET,
|
|
368
|
+
froxel_depth_scale
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
// The projection is infinite-far reverse-Z, so the camera frustum's far plane is zeroed and
|
|
372
|
+
// can't be sliced into froxel slabs. Rebuild a finite far plane at the logical far for the
|
|
373
|
+
// participating-media coverage test — exactly as the light-cluster assignment does.
|
|
374
|
+
const clipped_frustum = new Float32Array(24);
|
|
375
|
+
clipped_frustum.set(camera.camera.frustum);
|
|
376
|
+
update_frustum_far_plane(clipped_frustum, camera.camera.view_matrix, camera.camera.far);
|
|
377
|
+
|
|
378
|
+
this.#metadata.upload({
|
|
379
|
+
cluster_parameters: volumetrics_cluster_parameters,
|
|
380
|
+
froxel_cluster_parameters: volumetrics_froxel_cluster_parameters,
|
|
381
|
+
resolution,
|
|
382
|
+
frustum: slice_flat_array(clipped_frustum, 0, 4, 6),
|
|
383
|
+
history_reset: this.#reset_history ? 1 : 0,
|
|
384
|
+
froxel_far,
|
|
385
|
+
// multiscatter knobs (GUI-tunable via globals); engine defaults 6 / 0.5
|
|
386
|
+
ms_octave_count: globalThis.__VOL_MS_OCTAVES ?? 6,
|
|
387
|
+
ms_extinction_decay: globalThis.__VOL_MS_EXT_DECAY ?? 0.5,
|
|
388
|
+
// Q-04. The sun's media self-shadowing, out of a 16-step per-froxel march and into one
|
|
389
|
+
// fetch of the cascades built earlier this frame — see #update_sun_shadow.
|
|
390
|
+
sun_shadow_ws_to_uvw: this.#sun_shadow_ws_to_uvw,
|
|
391
|
+
sun_shadow_uvw_to_ws: this.#sun_shadow_uvw_to_ws,
|
|
392
|
+
sun_shadow_step_ws: this.#sun_shadow_step_ws,
|
|
393
|
+
sun_shadow_cascade_far: this.#sun_shadow_cascade_far,
|
|
394
|
+
sun_shadow_light_index: this.#sun_shadow_light_index,
|
|
395
|
+
}, this.#device.queue);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
*
|
|
400
|
+
* @param {FrameGraph} graph
|
|
401
|
+
* @param {number} light_cluster_data
|
|
402
|
+
* @param {number} light_cluster_lookup
|
|
403
|
+
* @param {number} light_cluster_parameters
|
|
404
|
+
* @param {number} shadowmap_atlas
|
|
405
|
+
*/
|
|
406
|
+
graph_update({
|
|
407
|
+
graph,
|
|
408
|
+
light_cluster_data,
|
|
409
|
+
light_cluster_lookup,
|
|
410
|
+
light_cluster_parameters,
|
|
411
|
+
shadowmap_atlas,
|
|
412
|
+
}) {
|
|
413
|
+
|
|
414
|
+
const view = this.#view;
|
|
415
|
+
const lights = view.scene.lights;
|
|
416
|
+
const camera = view.camera;
|
|
417
|
+
|
|
418
|
+
// Optional runtime A/B toggle (e.g. a GUI checkbox) without per-view plumbing. The setter
|
|
419
|
+
// forces a history reset on change, so flipping it back on never blends against stale data.
|
|
420
|
+
const taa_requested = globalThis.__VOL_TAA_ENABLED ?? true;
|
|
421
|
+
if (taa_requested !== this.#taa_enabled) {
|
|
422
|
+
this.taa_enabled = taa_requested;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// runtime froxel-grid far override (GUI); Infinity -> grid covers the whole range (no far march)
|
|
426
|
+
const froxel_far_requested = globalThis.__VOL_FROXEL_FAR ?? Infinity;
|
|
427
|
+
if (froxel_far_requested !== this.#froxel_far) {
|
|
428
|
+
this.#froxel_far = froxel_far_requested;
|
|
429
|
+
// the froxel grid's depth curve just changed; the TAA history is on the old curve, reset it
|
|
430
|
+
this.#reset_history = true;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
this.#update_resolution();
|
|
434
|
+
this.#update_metadata();
|
|
435
|
+
|
|
436
|
+
const gr_metadata = graph_import_buffer(graph, this.#metadata.buffer, "volumetrics metadata");
|
|
437
|
+
|
|
438
|
+
const resolution = this.#volumetrics_textures[0].size;
|
|
439
|
+
|
|
440
|
+
// Ping-pong the two persistent froxel textures: this frame writes [parity] and reads the
|
|
441
|
+
// previous frame's accumulation from [parity ^ 1]. On the first frame / after a resize the
|
|
442
|
+
// history is invalid, which #update_metadata signals via history_reset (the TAA then emits
|
|
443
|
+
// the fresh sample). graph_build_volumetrics inserts the reprojection pass only when both
|
|
444
|
+
// history/output handles are supplied — so leaving them undefined disables it.
|
|
445
|
+
let taa_history;
|
|
446
|
+
let taa_output;
|
|
447
|
+
|
|
448
|
+
if (this.#taa_enabled) {
|
|
449
|
+
const parity = view.frame_index & 1;
|
|
450
|
+
taa_history = graph_import_texture(graph, this.#volumetrics_textures[parity ^ 1], "volumetrics taa history");
|
|
451
|
+
taa_output = graph_import_texture(graph, this.#volumetrics_textures[parity], "volumetrics taa output");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const { lut_aerial } = graph_build_volumetrics({
|
|
455
|
+
graph,
|
|
456
|
+
camera,
|
|
457
|
+
lights,
|
|
458
|
+
view,
|
|
459
|
+
light_cluster_data,
|
|
460
|
+
light_cluster_lookup,
|
|
461
|
+
light_cluster_parameters,
|
|
462
|
+
shadowmap_atlas,
|
|
463
|
+
|
|
464
|
+
volumetrics_metadata: gr_metadata,
|
|
465
|
+
volumetric_resolution: resolution,
|
|
466
|
+
sun_shadow_resolution: this.#sun_shadow_resolution,
|
|
467
|
+
|
|
468
|
+
taa_history,
|
|
469
|
+
taa_output,
|
|
470
|
+
camera_previous: view.gpu_previous_camera_state,
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
this.#reset_history = false;
|
|
474
|
+
|
|
475
|
+
return {
|
|
476
|
+
resolved: lut_aerial,
|
|
477
|
+
metadata: gr_metadata,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
316
481
|
}
|