@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
|
@@ -39,6 +39,11 @@ export class VolumetricsParticleSpec {
|
|
|
39
39
|
radius: any;
|
|
40
40
|
g?: number;
|
|
41
41
|
}): void;
|
|
42
|
+
/**
|
|
43
|
+
* @param {VolumetricsParticleSpec} other
|
|
44
|
+
* @returns {boolean}
|
|
45
|
+
*/
|
|
46
|
+
equals(other: VolumetricsParticleSpec): boolean;
|
|
42
47
|
}
|
|
43
48
|
export const VOLUMETRIC_PARTICLE_SPEC_FOG: Readonly<VolumetricsParticleSpec>;
|
|
44
49
|
export class ParticipatingMediaVolume {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParticipatingMediaVolume.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/ParticipatingMediaVolume.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ParticipatingMediaVolume.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/ParticipatingMediaVolume.js"],"names":[],"mappings":"AAKA;IA6EI;;;;OAIG;IACH,+BAHW;QAAC,wBAAwB,CAAC;QAAC,wBAAwB,CAAC;QAAC,MAAM,CAAC;QAAC,CAAC,CAAA;KAAC,GAC9D,uBAAuB,CAalC;IAED,oDAIC;IAlGD;;;OAGG;IACH,YAFU,MAAM,EAAE,CAEK;IAEvB;;;OAGG;IACH,YAFU,MAAM,EAAE,CAEK;IAEvB;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX,UAAQ;IAER,iCAIC;IAED;;;OAGG;IACH,YAFW,uBAAuB,QAOjC;IAED;;;;;aA0BC;IAED;;;OAGG;IACH,cAHW,uBAAuB,GACrB,OAAO,CAOnB;CAyBJ;AAED,6EAKI;AAIJ;IAII,iBAEC;IAED;;;OAGG;IACH,aAFU,MAAM,EAAE,CAEM;IACxB,0BAA4B;IAC5B,uBAAyB;IAEzB;;;OAGG;IACH,gBAFU,MAAM,EAAE,CAES;IAE3B;;;OAGG;IACH,uBAFU,MAAM,EAAE,CAEgB;IAElC;;;OAGG;IACH,MAFU,MAAM,CAEP;IAET;;;OAGG;IACH,gBAAc;IAEd;;;;;;;;;OASG;IACH,mCAEC;IAED,uCAA+E;IAE/E;;;;;;OAMG;IACH,eAFU,MAAM,CAEI;IAEpB;;;;OAIG;IACH,WAFU,SAAS,CAES;;CAE/B;0BAzLyB,4CAA4C"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import { isArrayEqualStrict } from "../../../core/collection/array/isArrayEqualStrict.js";
|
|
2
3
|
import { rgb_to_luminance } from "../../../core/color/rgb_to_luminance.js";
|
|
3
4
|
import { Transform } from "../../../engine/ecs/transform/Transform.js";
|
|
4
5
|
|
|
@@ -55,12 +56,30 @@ export class VolumetricsParticleSpec {
|
|
|
55
56
|
assert.isNumber(g, 'g');
|
|
56
57
|
assert.isFinite(g, 'g must be finite');
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
/*
|
|
60
|
+
Copied rather than referenced: the sources these arrive from are shared constants —
|
|
61
|
+
`VOLUMETRIC_PARTICLE_SPEC_FOG` and the generated `MIE_PARTICLES_STANDARD_PRECOMPUTED`
|
|
62
|
+
table — and `Object.freeze` on the object around them does not freeze the arrays inside.
|
|
63
|
+
Holding onto them would make every spec built from the same entry the same spec, so
|
|
64
|
+
tuning one volume would retune every other volume sharing its particle.
|
|
65
|
+
*/
|
|
66
|
+
this.extinction = extinction.slice();
|
|
67
|
+
this.scattering = scattering.slice();
|
|
60
68
|
this.radius = radius;
|
|
61
69
|
this.g = g;
|
|
62
70
|
}
|
|
63
71
|
|
|
72
|
+
/**
|
|
73
|
+
* @param {VolumetricsParticleSpec} other
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
equals(other) {
|
|
77
|
+
return this.radius === other.radius
|
|
78
|
+
&& this.g === other.g
|
|
79
|
+
&& isArrayEqualStrict(this.extinction, other.extinction)
|
|
80
|
+
&& isArrayEqualStrict(this.scattering, other.scattering);
|
|
81
|
+
}
|
|
82
|
+
|
|
64
83
|
/**
|
|
65
84
|
*
|
|
66
85
|
* @param {{cross_section_extinction, cross_section_scattering, radius, g}} particle_spec
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every participating medium in a scene, and a counter saying whether the GPU's copy is stale.
|
|
3
|
+
*
|
|
4
|
+
* **The version is the whole synchronisation protocol.** {@link GPUSceneVolumetrics} repacks the
|
|
5
|
+
* entire table whenever the number moves and does nothing at all when it does not, so a volume
|
|
6
|
+
* changed without moving the counter renders with the values it was last uploaded with — the CPU
|
|
7
|
+
* object holds the new density, reads back correctly, and only the picture is stale. Anything that
|
|
8
|
+
* writes into a volume in place therefore has to say so; see {@link invalidate}.
|
|
9
|
+
*
|
|
10
|
+
* **Volumes are packed by array index**, so removing one renumbers the rest. That is free here
|
|
11
|
+
* because the upload is all-or-nothing, and it is the reason no volume carries a slot number.
|
|
12
|
+
*/
|
|
1
13
|
export class SceneVolumetrics {
|
|
2
14
|
/**
|
|
3
15
|
*
|
|
@@ -10,5 +22,19 @@ export class SceneVolumetrics {
|
|
|
10
22
|
* @param {ParticipatingMediaVolume} volume
|
|
11
23
|
*/
|
|
12
24
|
add(volume: ParticipatingMediaVolume): void;
|
|
25
|
+
/**
|
|
26
|
+
* Take a volume back out.
|
|
27
|
+
*
|
|
28
|
+
* @param {ParticipatingMediaVolume} volume
|
|
29
|
+
* @returns {boolean} true if it was there to be removed
|
|
30
|
+
*/
|
|
31
|
+
remove(volume: ParticipatingMediaVolume): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Say that a volume already in the scene has been written into.
|
|
34
|
+
*
|
|
35
|
+
* Adding and removing move the version by themselves; changing a volume in place is invisible
|
|
36
|
+
* from here, and this is how such a change reaches the GPU.
|
|
37
|
+
*/
|
|
38
|
+
invalidate(): void;
|
|
13
39
|
}
|
|
14
40
|
//# sourceMappingURL=SceneVolumetrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/SceneVolumetrics.js"],"names":[],"mappings":"AAAA;IACI;;;OAGG;IACH,SAFU,0BAA0B,CAEvB;IAEb,gBAAY;IAEZ;;;OAGG;IACH,4CAMC;CACJ"}
|
|
1
|
+
{"version":3,"file":"SceneVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/SceneVolumetrics.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH;IACI;;;OAGG;IACH,SAFU,0BAA0B,CAEvB;IAEb,gBAAY;IAEZ;;;OAGG;IACH,4CAMC;IAED;;;;;OAKG;IACH,0CAFa,OAAO,CAenB;IAED;;;;;OAKG;IACH,mBAEC;CACJ"}
|
|
@@ -1,21 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Every participating medium in a scene, and a counter saying whether the GPU's copy is stale.
|
|
3
|
+
*
|
|
4
|
+
* **The version is the whole synchronisation protocol.** {@link GPUSceneVolumetrics} repacks the
|
|
5
|
+
* entire table whenever the number moves and does nothing at all when it does not, so a volume
|
|
6
|
+
* changed without moving the counter renders with the values it was last uploaded with — the CPU
|
|
7
|
+
* object holds the new density, reads back correctly, and only the picture is stale. Anything that
|
|
8
|
+
* writes into a volume in place therefore has to say so; see {@link invalidate}.
|
|
9
|
+
*
|
|
10
|
+
* **Volumes are packed by array index**, so removing one renumbers the rest. That is free here
|
|
11
|
+
* because the upload is all-or-nothing, and it is the reason no volume carries a slot number.
|
|
12
|
+
*/
|
|
13
|
+
export class SceneVolumetrics {
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {ParticipatingMediaVolume[]}
|
|
17
|
+
*/
|
|
18
|
+
volumes = [];
|
|
19
|
+
|
|
20
|
+
version = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param {ParticipatingMediaVolume} volume
|
|
25
|
+
*/
|
|
26
|
+
add(volume) {
|
|
27
|
+
|
|
28
|
+
this.volumes.push(volume);
|
|
29
|
+
|
|
30
|
+
this.version++;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Take a volume back out.
|
|
36
|
+
*
|
|
37
|
+
* @param {ParticipatingMediaVolume} volume
|
|
38
|
+
* @returns {boolean} true if it was there to be removed
|
|
39
|
+
*/
|
|
40
|
+
remove(volume) {
|
|
41
|
+
|
|
42
|
+
const index = this.volumes.indexOf(volume);
|
|
43
|
+
|
|
44
|
+
if (index === -1) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.volumes.splice(index, 1);
|
|
49
|
+
|
|
50
|
+
this.version++;
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Say that a volume already in the scene has been written into.
|
|
57
|
+
*
|
|
58
|
+
* Adding and removing move the version by themselves; changing a volume in place is invisible
|
|
59
|
+
* from here, and this is how such a change reaches the GPU.
|
|
60
|
+
*/
|
|
61
|
+
invalidate() {
|
|
62
|
+
this.version++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VOLUMETRICS_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VOLUMETRICS_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js"],"names":[],"mappings":"AAKA,uDA+EG;6BAlF0B,gCAAgC"}
|
|
@@ -1,29 +1,85 @@
|
|
|
1
|
-
import { f32, u32, vec3f, vec3u, vec4f } from "../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
-
import { WebGPUArray } from "../shader/type/WebGPUArray.js";
|
|
3
|
-
import { WebGPUStruct } from "../shader/type/WebGPUStruct.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// depth
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import { f32, mat4x4f, u32, vec3f, vec3u, vec4f } from "../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../shader/type/WebGPUArray.js";
|
|
3
|
+
import { WebGPUStruct } from "../shader/type/WebGPUStruct.js";
|
|
4
|
+
import { VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT } from "./VOLUMETRICS_SUN_SHADOW_RESOLUTION.js";
|
|
5
|
+
|
|
6
|
+
export const VOLUMETRICS_METADATA_STRUCT = WebGPUStruct.from({
|
|
7
|
+
resolution: vec3u,
|
|
8
|
+
// LUT / composite depth curve — covers the full logical range up to camera.far.
|
|
9
|
+
cluster_parameters: vec3f,
|
|
10
|
+
// Froxel-grid depth curve — covers [near, froxel_far]. Equals cluster_parameters when the grid
|
|
11
|
+
// spans the whole range (the no-op default). PM/lighting/TAA build the grid on THIS curve; the
|
|
12
|
+
// aerial pass uses it to map a LUT depth back to the grid slice it should sample.
|
|
13
|
+
froxel_cluster_parameters: vec3f,
|
|
14
|
+
volume_count: u32,
|
|
15
|
+
// World-space frustum planes with a FINITE far plane. The camera's own projection is
|
|
16
|
+
// infinite-far reverse-Z (its frustum far plane is zeroed), which frustum_slice can't slice;
|
|
17
|
+
// this is rebuilt at the logical far for the participating-media coverage test.
|
|
18
|
+
frustum: WebGPUArray.from(vec4f, 6),
|
|
19
|
+
// 1 when temporal-reprojection history is invalid (first frame, resolution change, camera
|
|
20
|
+
// teleport): the volumetric TAA then outputs the fresh sample instead of blending stale history.
|
|
21
|
+
history_reset: u32,
|
|
22
|
+
// View-space depth at which the froxel grid ends. The aerial pass samples the grid where
|
|
23
|
+
// depth <= froxel_far and ray-marches the scene volumes directly beyond it (RDR2-style far
|
|
24
|
+
// field, growing log steps). Defaults to camera.far -> the whole range is grid-sampled (no-op).
|
|
25
|
+
froxel_far: f32,
|
|
26
|
+
// Multiscatter tuning (calculate_multiscattering). Fewer octaves / higher decay -> less
|
|
27
|
+
// shadow fill -> stronger lit-rim-vs-core contrast (silver lining). Engine defaults: 6 / 0.5.
|
|
28
|
+
ms_octave_count: u32,
|
|
29
|
+
ms_extinction_decay: f32,
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Q-04. World position -> [0,1]^3 inside one cascade of the sun's optical-depth volume, and its
|
|
33
|
+
* inverse, innermost cascade first.
|
|
34
|
+
*
|
|
35
|
+
* Each volume's third axis is the direction light travels, so a column of voxels is one sun ray
|
|
36
|
+
* and the value stored along it is the running integral of extinction — read back in a single
|
|
37
|
+
* fetch by `chunk_volumetrics_sun_optical_depth`, where the shipping path marches 16 steps per
|
|
38
|
+
* froxel. `build_volumetrics_sun_shadow_transform` places each box and explains why it is
|
|
39
|
+
* placed that way; the inverse is what `shader_volumetrics_build_sun_shadow_volume` walks.
|
|
40
|
+
*/
|
|
41
|
+
sun_shadow_ws_to_uvw: WebGPUArray.from(mat4x4f, VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT),
|
|
42
|
+
sun_shadow_uvw_to_ws: WebGPUArray.from(mat4x4f, VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT),
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* World-space length of one voxel along the sun axis, per cascade — the scan's `dt`. Constant
|
|
46
|
+
* for the frame, because each box's extent comes from the projection rather than from where the
|
|
47
|
+
* camera happens to be pointing.
|
|
48
|
+
*
|
|
49
|
+
* A `vec4f` rather than an array because WGSL's uniform address space rounds an `array<f32, N>`
|
|
50
|
+
* element up to 16 bytes, so the packed vector is the same four values in a quarter of the
|
|
51
|
+
* space and with no stride to get wrong. It is also the reason the cascade count is capped at
|
|
52
|
+
* four.
|
|
53
|
+
*/
|
|
54
|
+
sun_shadow_step_ws: vec4f,
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* View depth each cascade's box covers out to, innermost first — what the read side selects on.
|
|
58
|
+
*
|
|
59
|
+
* Selection is by depth rather than by testing containment in each box because the two agree
|
|
60
|
+
* (every box contains the sub-frustum out to this depth, by construction) and only the first
|
|
61
|
+
* gives a scalar to blend across. Unused lanes hold the outermost cascade's far, so a read that
|
|
62
|
+
* runs off the end of the ladder still lands on a real cascade.
|
|
63
|
+
*/
|
|
64
|
+
sun_shadow_cascade_far: vec4f,
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Q-04. Which slot of the `light_directional` table the cascades were built for, or
|
|
68
|
+
* `VOLUMETRICS_SUN_SHADOW_LIGHT_NONE` when they were not built at all.
|
|
69
|
+
*
|
|
70
|
+
* The lighting pass tests its loop index against this rather than assuming zero, so a second
|
|
71
|
+
* directional light degrades to the march instead of being shadowed by the first one's
|
|
72
|
+
* cascades — there is one ladder and it is aligned to one direction. The sentinel matches no
|
|
73
|
+
* index, so it degrades *every* directional light the same way, which is what the two cases
|
|
74
|
+
* that cannot place a box need: a scene with no directional light, and a camera with no field
|
|
75
|
+
* of view to derive a bounding sphere from.
|
|
76
|
+
*
|
|
77
|
+
* This carried a `sun_shadow_mode` word beside it while Q-04 was an A/B. That word is gone: the
|
|
78
|
+
* cascades are the only path for the sun now, and "not built this frame" is a property of the
|
|
79
|
+
* light rather than a mode to select.
|
|
80
|
+
*
|
|
81
|
+
* Point and spot lights always march. Their `tmax` is the distance to the light, so those rays
|
|
82
|
+
* are short and local and there is far less to amortize.
|
|
83
|
+
*/
|
|
84
|
+
sun_shadow_light_index: u32,
|
|
29
85
|
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-steps the build pass takes across one voxel of cascade `index`, along the sun.
|
|
3
|
+
*
|
|
4
|
+
* A voxel has to hold the medium's integral across its slab, and the rate that integral is sampled
|
|
5
|
+
* at is a separate knob from the rate it is stored at — only the first has to beat the medium's
|
|
6
|
+
* features. The outermost cascade has the largest voxel and needs the most; each cascade in from it
|
|
7
|
+
* has a voxel `RATIO` times smaller, so the same world-space sample spacing costs `RATIO` times
|
|
8
|
+
* fewer sub-steps. Holding the spacing constant across cascades rather than the count is what keeps
|
|
9
|
+
* the innermost cascade from spending its budget resolving a millimetre.
|
|
10
|
+
*
|
|
11
|
+
* **Always even, and never fewer than two.** The build stores its running integral when it reaches
|
|
12
|
+
* sub-step `count / 2`, which is the voxel's centre only when the halves are equal; an odd count
|
|
13
|
+
* stores the integral to `floor(count/2)/count` of the slab, and one sub-step stores it to the near
|
|
14
|
+
* face — a half-slab bias in the direction that makes the medium shadow too little, on the cascade
|
|
15
|
+
* that matters most.
|
|
16
|
+
*
|
|
17
|
+
* @param {number} index
|
|
18
|
+
* @returns {number}
|
|
19
|
+
*/
|
|
20
|
+
export function volumetrics_sun_shadow_sub_steps(index: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Voxel counts of one cascade of the sun optical-depth volume, `[x, y, z]`, with `z` along the sun.
|
|
23
|
+
*
|
|
24
|
+
* Cubic, and that is a measured decision rather than a default. It is tempting to make the grid
|
|
25
|
+
* lateral-heavy: at the playground's 60 degree field of view the medium there is a horizontal slab
|
|
26
|
+
* three units thick crossed by a low sun, so its structure perpendicular to the sun is far finer
|
|
27
|
+
* than its structure along it, and as a single box `[256, 256, 32]` beats `[128, 128, 128]` by an
|
|
28
|
+
* order of magnitude at identical memory. That advantage belongs to *that* fog and *that* sun
|
|
29
|
+
* elevation. Against a converged reference at one viewpoint, as a single box:
|
|
30
|
+
*
|
|
31
|
+
* | field of view | `[128,128,128]` | `[256,256,32]` |
|
|
32
|
+
* |---|---|---|
|
|
33
|
+
* | 40 deg | +6.4 | +28.1 |
|
|
34
|
+
* | 60 deg | +37.7 | +2.5 |
|
|
35
|
+
* | 90 deg | +1.4 | +39.0 |
|
|
36
|
+
* | 110 deg | +2.1 | +39.5 |
|
|
37
|
+
*
|
|
38
|
+
* Two axes, two Nyquist limits, and which one is starved depends on the camera. Cubic is the shape
|
|
39
|
+
* that does not assume. 96 puts one cascade at 7.1 MB, three at 21.2 MB.
|
|
40
|
+
*
|
|
41
|
+
* @type {number[]}
|
|
42
|
+
*/
|
|
43
|
+
export const VOLUMETRICS_SUN_SHADOW_RESOLUTION: number[];
|
|
44
|
+
/**
|
|
45
|
+
* How many cascades the structure carries.
|
|
46
|
+
*
|
|
47
|
+
* A single world-uniform box cannot be sized correctly, and that is arithmetic rather than tuning.
|
|
48
|
+
* The box has to contain the camera frustum under any rotation, so its side is proportional to
|
|
49
|
+
* `far` and to `tan(fov/2)`; the medium's features — a three-unit fog slab — are absolute. So the
|
|
50
|
+
* ratio between what the structure can resolve and what it has to resolve is a free parameter of
|
|
51
|
+
* the *camera*, and the table above is what that looks like: every single-box configuration
|
|
52
|
+
* measured has a field of view at which it is 28 to 50 mean luminance from the truth, and which
|
|
53
|
+
* one moves with the resolution. Three cascades of 96 are within 1.8 across the same range.
|
|
54
|
+
*
|
|
55
|
+
* Buying the near field's resolution uniformly instead is not an option: 0.28 unit voxels over a
|
|
56
|
+
* 283 unit box is 1024 per axis, i.e. 268 MB. Cascades buy it where the froxels are, which on a
|
|
57
|
+
* log-distributed grid over [0.1, 120] is two thirds of the slices inside 15 units — the innermost
|
|
58
|
+
* box here is 33 units across, so its voxel is 0.34 units for 7.1 MB.
|
|
59
|
+
*
|
|
60
|
+
* Three is what Frostbite ships for its extinction clipmap and what Enshrouded ships for this exact
|
|
61
|
+
* structure. Four is a constant away; the read side, the metadata and the build shaders are all
|
|
62
|
+
* generated from this.
|
|
63
|
+
*
|
|
64
|
+
* @type {number}
|
|
65
|
+
*/
|
|
66
|
+
export const VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT: number;
|
|
67
|
+
/**
|
|
68
|
+
* Ratio between one cascade's far distance and the next one in.
|
|
69
|
+
*
|
|
70
|
+
* `far_i = far / RATIO^(count - 1 - i)`, the logarithmic split, so every cascade has the same
|
|
71
|
+
* voxel-size ratio to its neighbour and the *worst* case within a cascade — its near end — is a
|
|
72
|
+
* fixed factor. Three cascades at ratio 3 cover a 120 unit far plane as 13.3 / 40 / 120, giving
|
|
73
|
+
* 0.34 / 1.02 / 3.07 unit voxels at 96 per axis.
|
|
74
|
+
*
|
|
75
|
+
* Bounded by the metadata: the per-cascade scalars are packed into `vec4f`, so no more than four.
|
|
76
|
+
*
|
|
77
|
+
* @type {number}
|
|
78
|
+
*/
|
|
79
|
+
export const VOLUMETRICS_SUN_SHADOW_CASCADE_RATIO: number;
|
|
80
|
+
/**
|
|
81
|
+
* `sun_shadow_light_index` when no cascades were placed this frame, so no directional light matches
|
|
82
|
+
* it and every one of them falls back to the per-froxel march.
|
|
83
|
+
*
|
|
84
|
+
* Two situations reach it and neither is a switch: a scene with no directional light, and a camera
|
|
85
|
+
* with no field of view for {@link frustum_bounding_sphere} to work from. The build passes still
|
|
86
|
+
* run — collapsed to one voxel — because the lighting pass binds their outputs unconditionally and
|
|
87
|
+
* WebGPU has no optional bindings.
|
|
88
|
+
*
|
|
89
|
+
* @type {number}
|
|
90
|
+
*/
|
|
91
|
+
export const VOLUMETRICS_SUN_SHADOW_LIGHT_NONE: number;
|
|
92
|
+
/**
|
|
93
|
+
* Workgroup shape of the build pass. One invocation owns a whole column along the sun axis, so
|
|
94
|
+
* this is 2D and covers the volume's x/y.
|
|
95
|
+
* @type {number[]}
|
|
96
|
+
*/
|
|
97
|
+
export const VOLUMETRICS_SUN_SHADOW_WORKGROUP_RESOLUTION: number[];
|
|
98
|
+
//# sourceMappingURL=VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.js"],"names":[],"mappings":"AA8DA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wDAHW,MAAM,GACJ,MAAM,CAWlB;AA1FD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,gDAFU,MAAM,EAAE,CAE4C;AAE9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,mDAFU,MAAM,CAEsC;AAEtD;;;;;;;;;;;GAWG;AACH,mDAFU,MAAM,CAEsC;AAgCtD;;;;;;;;;;GAUG;AACH,gDAFU,MAAM,CAE4C;AAE5D;;;;GAIG;AACH,0DAFU,MAAM,EAAE,CAEgD"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voxel counts of one cascade of the sun optical-depth volume, `[x, y, z]`, with `z` along the sun.
|
|
3
|
+
*
|
|
4
|
+
* Cubic, and that is a measured decision rather than a default. It is tempting to make the grid
|
|
5
|
+
* lateral-heavy: at the playground's 60 degree field of view the medium there is a horizontal slab
|
|
6
|
+
* three units thick crossed by a low sun, so its structure perpendicular to the sun is far finer
|
|
7
|
+
* than its structure along it, and as a single box `[256, 256, 32]` beats `[128, 128, 128]` by an
|
|
8
|
+
* order of magnitude at identical memory. That advantage belongs to *that* fog and *that* sun
|
|
9
|
+
* elevation. Against a converged reference at one viewpoint, as a single box:
|
|
10
|
+
*
|
|
11
|
+
* | field of view | `[128,128,128]` | `[256,256,32]` |
|
|
12
|
+
* |---|---|---|
|
|
13
|
+
* | 40 deg | +6.4 | +28.1 |
|
|
14
|
+
* | 60 deg | +37.7 | +2.5 |
|
|
15
|
+
* | 90 deg | +1.4 | +39.0 |
|
|
16
|
+
* | 110 deg | +2.1 | +39.5 |
|
|
17
|
+
*
|
|
18
|
+
* Two axes, two Nyquist limits, and which one is starved depends on the camera. Cubic is the shape
|
|
19
|
+
* that does not assume. 96 puts one cascade at 7.1 MB, three at 21.2 MB.
|
|
20
|
+
*
|
|
21
|
+
* @type {number[]}
|
|
22
|
+
*/
|
|
23
|
+
export const VOLUMETRICS_SUN_SHADOW_RESOLUTION = [96, 96, 96];
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* How many cascades the structure carries.
|
|
27
|
+
*
|
|
28
|
+
* A single world-uniform box cannot be sized correctly, and that is arithmetic rather than tuning.
|
|
29
|
+
* The box has to contain the camera frustum under any rotation, so its side is proportional to
|
|
30
|
+
* `far` and to `tan(fov/2)`; the medium's features — a three-unit fog slab — are absolute. So the
|
|
31
|
+
* ratio between what the structure can resolve and what it has to resolve is a free parameter of
|
|
32
|
+
* the *camera*, and the table above is what that looks like: every single-box configuration
|
|
33
|
+
* measured has a field of view at which it is 28 to 50 mean luminance from the truth, and which
|
|
34
|
+
* one moves with the resolution. Three cascades of 96 are within 1.8 across the same range.
|
|
35
|
+
*
|
|
36
|
+
* Buying the near field's resolution uniformly instead is not an option: 0.28 unit voxels over a
|
|
37
|
+
* 283 unit box is 1024 per axis, i.e. 268 MB. Cascades buy it where the froxels are, which on a
|
|
38
|
+
* log-distributed grid over [0.1, 120] is two thirds of the slices inside 15 units — the innermost
|
|
39
|
+
* box here is 33 units across, so its voxel is 0.34 units for 7.1 MB.
|
|
40
|
+
*
|
|
41
|
+
* Three is what Frostbite ships for its extinction clipmap and what Enshrouded ships for this exact
|
|
42
|
+
* structure. Four is a constant away; the read side, the metadata and the build shaders are all
|
|
43
|
+
* generated from this.
|
|
44
|
+
*
|
|
45
|
+
* @type {number}
|
|
46
|
+
*/
|
|
47
|
+
export const VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT = 3;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Ratio between one cascade's far distance and the next one in.
|
|
51
|
+
*
|
|
52
|
+
* `far_i = far / RATIO^(count - 1 - i)`, the logarithmic split, so every cascade has the same
|
|
53
|
+
* voxel-size ratio to its neighbour and the *worst* case within a cascade — its near end — is a
|
|
54
|
+
* fixed factor. Three cascades at ratio 3 cover a 120 unit far plane as 13.3 / 40 / 120, giving
|
|
55
|
+
* 0.34 / 1.02 / 3.07 unit voxels at 96 per axis.
|
|
56
|
+
*
|
|
57
|
+
* Bounded by the metadata: the per-cascade scalars are packed into `vec4f`, so no more than four.
|
|
58
|
+
*
|
|
59
|
+
* @type {number}
|
|
60
|
+
*/
|
|
61
|
+
export const VOLUMETRICS_SUN_SHADOW_CASCADE_RATIO = 3;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Sub-steps the build pass takes across one voxel of cascade `index`, along the sun.
|
|
65
|
+
*
|
|
66
|
+
* A voxel has to hold the medium's integral across its slab, and the rate that integral is sampled
|
|
67
|
+
* at is a separate knob from the rate it is stored at — only the first has to beat the medium's
|
|
68
|
+
* features. The outermost cascade has the largest voxel and needs the most; each cascade in from it
|
|
69
|
+
* has a voxel `RATIO` times smaller, so the same world-space sample spacing costs `RATIO` times
|
|
70
|
+
* fewer sub-steps. Holding the spacing constant across cascades rather than the count is what keeps
|
|
71
|
+
* the innermost cascade from spending its budget resolving a millimetre.
|
|
72
|
+
*
|
|
73
|
+
* **Always even, and never fewer than two.** The build stores its running integral when it reaches
|
|
74
|
+
* sub-step `count / 2`, which is the voxel's centre only when the halves are equal; an odd count
|
|
75
|
+
* stores the integral to `floor(count/2)/count` of the slab, and one sub-step stores it to the near
|
|
76
|
+
* face — a half-slab bias in the direction that makes the medium shadow too little, on the cascade
|
|
77
|
+
* that matters most.
|
|
78
|
+
*
|
|
79
|
+
* @param {number} index
|
|
80
|
+
* @returns {number}
|
|
81
|
+
*/
|
|
82
|
+
export function volumetrics_sun_shadow_sub_steps(index) {
|
|
83
|
+
const outermost = 4;
|
|
84
|
+
|
|
85
|
+
const halves = Math.max(
|
|
86
|
+
1,
|
|
87
|
+
Math.ceil(outermost / (2 * Math.pow(VOLUMETRICS_SUN_SHADOW_CASCADE_RATIO, VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT - 1 - index)))
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return 2 * halves;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* `sun_shadow_light_index` when no cascades were placed this frame, so no directional light matches
|
|
95
|
+
* it and every one of them falls back to the per-froxel march.
|
|
96
|
+
*
|
|
97
|
+
* Two situations reach it and neither is a switch: a scene with no directional light, and a camera
|
|
98
|
+
* with no field of view for {@link frustum_bounding_sphere} to work from. The build passes still
|
|
99
|
+
* run — collapsed to one voxel — because the lighting pass binds their outputs unconditionally and
|
|
100
|
+
* WebGPU has no optional bindings.
|
|
101
|
+
*
|
|
102
|
+
* @type {number}
|
|
103
|
+
*/
|
|
104
|
+
export const VOLUMETRICS_SUN_SHADOW_LIGHT_NONE = 0xFFFFFFFF;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Workgroup shape of the build pass. One invocation owns a whole column along the sun axis, so
|
|
108
|
+
* this is 2D and covers the volume's x/y.
|
|
109
|
+
* @type {number[]}
|
|
110
|
+
*/
|
|
111
|
+
export const VOLUMETRICS_SUN_SHADOW_WORKGROUP_RESOLUTION = [8, 8];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Far distance of cascade `index`, i.e. the view depth its box has to cover.
|
|
3
|
+
*
|
|
4
|
+
* A logarithmic split, `far / ratio^(count - 1 - index)`. The choice is forced by what the cascades
|
|
5
|
+
* are for: every box is sized from the bounding sphere of the sub-frustum it covers, so its voxel is
|
|
6
|
+
* proportional to its far distance, and a constant ratio between far distances is a constant ratio
|
|
7
|
+
* between voxel sizes. Any other split leaves one cascade carrying a resolution jump the others do
|
|
8
|
+
* not.
|
|
9
|
+
*
|
|
10
|
+
* The innermost cascade still starts at the camera rather than at the previous cascade's far plane —
|
|
11
|
+
* cascades here nest rather than tile, because the box is sized from a *frustum's* bounding sphere
|
|
12
|
+
* and a shell would need a sphere around the shell, which is the outer sphere again.
|
|
13
|
+
*
|
|
14
|
+
* @param {number} far the full range the structure must cover
|
|
15
|
+
* @param {number} index
|
|
16
|
+
* @param {number} count
|
|
17
|
+
* @param {number} ratio
|
|
18
|
+
* @returns {number}
|
|
19
|
+
*/
|
|
20
|
+
export function volumetrics_sun_shadow_cascade_far(far: number, index: number, count: number, ratio: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Radius of the smallest sphere containing a symmetric perspective frustum, and where its centre
|
|
23
|
+
* sits along the view axis.
|
|
24
|
+
*
|
|
25
|
+
* This is the quantity that makes the structure temporally stable, and the reason it is a sphere
|
|
26
|
+
* rather than a tight fit: it depends only on `fov`, `aspect`, `near` and `far`, so it does not
|
|
27
|
+
* change when the camera turns. A box sized from it therefore has a fixed extent, hence a fixed
|
|
28
|
+
* voxel size, hence a world-space voxel lattice that only ever translates.
|
|
29
|
+
*
|
|
30
|
+
* Both frustum corner rings are equidistant from the centre when
|
|
31
|
+
* `z = (far + near)(k^2 + 1) / 2` with `k^2 = tan^2(theta_x) + tan^2(theta_y)`. Past `z = far` that
|
|
32
|
+
* solution leaves the sphere behind the far plane, and the far ring alone bounds it.
|
|
33
|
+
*
|
|
34
|
+
* @param {number[]} out `[center_view_z, radius]`
|
|
35
|
+
* @param {number} fov_y vertical field of view, radians
|
|
36
|
+
* @param {number} aspect width / height
|
|
37
|
+
* @param {number} near
|
|
38
|
+
* @param {number} far
|
|
39
|
+
* @returns {number[]} out
|
|
40
|
+
*/
|
|
41
|
+
export function frustum_bounding_sphere(out: number[], fov_y: number, aspect: number, near: number, far: number): number[];
|
|
42
|
+
/**
|
|
43
|
+
* Place the sun's optical-depth volume for this frame.
|
|
44
|
+
*
|
|
45
|
+
* The volume is a box aligned to the sun: its third axis is the direction light travels, so a
|
|
46
|
+
* column of voxels along that axis is a light ray, and the optical depth of every voxel in the
|
|
47
|
+
* column is one running sum away from its neighbour's. That is what
|
|
48
|
+
* `shader_volumetrics_build_sun_shadow_volume` computes and what
|
|
49
|
+
* `chunk_volumetrics_sun_optical_depth` reads back in a single fetch.
|
|
50
|
+
*
|
|
51
|
+
* Two properties matter and both are about time rather than space, because the froxel lighting this
|
|
52
|
+
* feeds goes through a 0.95-blend temporal filter that turns any instability into either ghosting
|
|
53
|
+
* or flicker:
|
|
54
|
+
*
|
|
55
|
+
* - **The extent never changes with camera orientation.** It comes from the frustum's bounding
|
|
56
|
+
* sphere, which is a function of the projection only. A tight fit of the frustum corners in sun
|
|
57
|
+
* space — the obvious thing, and what this engine's CSM deliberately does for its cascades —
|
|
58
|
+
* would breathe as the camera turned, moving every voxel centre continuously and making the
|
|
59
|
+
* whole structure swim. The CSM can afford the tight fit because it is two orders of magnitude
|
|
60
|
+
* denser and its consumer is a filtered depth comparison; this is neither.
|
|
61
|
+
*
|
|
62
|
+
* - **The origin is snapped to a whole voxel.** With a fixed extent that makes the world-space
|
|
63
|
+
* voxel lattice identical from frame to frame no matter how the camera moves: voxel centres land
|
|
64
|
+
* on the same world positions, so the sampled medium is the same and the reconstruction is the
|
|
65
|
+
* same function of world position. Only the indexing changes. The box shifts by whole voxels,
|
|
66
|
+
* and the slab it gains or loses lies outside the frustum where the medium is zero, so even the
|
|
67
|
+
* scan's starting value is unaffected.
|
|
68
|
+
*
|
|
69
|
+
* @param {Float32Array} ws_to_uvw 16 floats, column-major. World position -> [0,1]^3 volume coords.
|
|
70
|
+
* @param {Float32Array} uvw_to_ws 16 floats, column-major. Its inverse, for the build pass.
|
|
71
|
+
* @param {ArrayLike<number>} light_direction unit vector along which light TRAVELS (the
|
|
72
|
+
* `light_directional` table's `direction`, i.e. NOT the direction toward the light).
|
|
73
|
+
* @param {ArrayLike<number>} camera_position world space
|
|
74
|
+
* @param {ArrayLike<number>} camera_forward unit, world space
|
|
75
|
+
* @param {number} fov_y vertical field of view, radians
|
|
76
|
+
* @param {number} aspect width / height
|
|
77
|
+
* @param {number} near
|
|
78
|
+
* @param {number} far the depth the medium actually extends to — `min(froxel_far, camera.far)`,
|
|
79
|
+
* since the froxel grid is where the extinction is read from and it ends there.
|
|
80
|
+
* @param {ArrayLike<number>} resolution `[x, y, z]` voxel counts
|
|
81
|
+
* @returns {number} world-space length of one voxel along the sun axis, i.e. the scan's `dz`
|
|
82
|
+
*/
|
|
83
|
+
export function build_volumetrics_sun_shadow_transform({ ws_to_uvw, uvw_to_ws, light_direction, camera_position, camera_forward, fov_y, aspect, near, far, resolution, }: Float32Array): number;
|
|
84
|
+
//# sourceMappingURL=build_volumetrics_sun_shadow_transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build_volumetrics_sun_shadow_transform.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wDANW,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,GACJ,MAAM,CAOlB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,6CAPW,MAAM,EAAE,SACR,MAAM,UACN,MAAM,QACN,MAAM,OACN,MAAM,GACJ,MAAM,EAAE,CAoBpB;AAyDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,0KAdW,YAAY,GAYV,MAAM,CA4ElB"}
|