@woosh/meep-engine 3.34.0 → 3.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/engine/Engine.d.ts +2 -0
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +5 -1
- package/src/engine/input/devices/XRInputDevice.d.ts +63 -0
- package/src/engine/input/devices/XRInputDevice.d.ts.map +1 -0
- package/src/engine/input/devices/XRInputDevice.js +386 -0
- package/src/engine/input/devices/xr/XRInputAction.d.ts +37 -0
- package/src/engine/input/devices/xr/XRInputAction.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputAction.js +85 -0
- package/src/engine/input/devices/xr/XRInputButton.d.ts +28 -0
- package/src/engine/input/devices/xr/XRInputButton.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputButton.js +43 -0
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts +15 -0
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputCoordinates.js +21 -0
- package/src/engine/input/devices/xr/XRInputHandle.d.ts +63 -0
- package/src/engine/input/devices/xr/XRInputHandle.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputHandle.js +171 -0
- package/src/engine/input/devices/xr/XRInputPose.d.ts +23 -0
- package/src/engine/input/devices/xr/XRInputPose.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputPose.js +36 -0
- package/src/engine/input/devices/xr/XRInputTypes.d.ts +76 -0
- package/src/engine/input/devices/xr/XRInputTypes.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputTypes.js +31 -0
- package/src/engine/input/devices/xr/XRInputValueSource.d.ts +11 -0
- package/src/engine/input/devices/xr/XRInputValueSource.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRInputValueSource.js +11 -0
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.d.ts +15 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +9 -0
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts +15 -4
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +22 -0
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.d.ts +17 -2
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.d.ts +5 -0
- package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/InputDeviceAdapter.d.ts +2 -0
- package/src/engine/input/ecs/ism/device/InputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +2 -0
- package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.d.ts +7 -0
- package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.d.ts +5 -0
- package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.d.ts +5 -0
- package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts +16 -0
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts.map +1 -0
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.js +54 -0
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts +9 -0
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts.map +1 -0
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.js +12 -0
- package/src/engine/input/ecs/ism/trigger/InputTrigger.d.ts +11 -1
- package/src/engine/input/ecs/ism/trigger/InputTrigger.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTrigger.js +7 -0
- package/src/engine/input/ecs/ism/trigger/InputTriggerChord.d.ts +16 -2
- package/src/engine/input/ecs/ism/trigger/InputTriggerChord.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerHold.d.ts +22 -2
- package/src/engine/input/ecs/ism/trigger/InputTriggerHold.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.d.ts +16 -2
- package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.d.ts +24 -4
- package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.d.ts +6 -8
- package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +5 -0
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts +7 -0
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts.map +1 -0
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.js +15 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/device/timing/profile/GPUProfileSession.d.ts +25 -11
- package/src/shade/device/timing/profile/GPUProfileSession.d.ts.map +1 -1
- package/src/shade/device/timing/profile/GPUProfileSession.js +553 -474
- package/src/shade/playground/avboit/main.d.ts.map +1 -1
- package/src/shade/playground/avboit/main.js +888 -916
- package/src/shade/playground/particle_ecs/README.md +13 -7
- package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +5 -5
- package/src/shade/playground/particle_ecs/bonfire_effects.js +5 -5
- package/src/shade/playground/particle_ecs/effects/smoke.json +1859 -1859
- package/src/shade/playground/particle_ecs/effects/soot.json +1605 -1605
- package/src/shade/playground/particle_system/README.md +1 -2
- package/src/shade/playground/profile_hotkey.d.ts.map +1 -1
- package/src/shade/playground/profile_hotkey.js +4 -40
- package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/main.js +4 -39
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +4 -39
- package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/measure.js +2 -4
- package/src/shade/renderer/Renderer.d.ts +1 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +3 -1
- package/src/shade/renderer/light/GPULightCollection.d.ts +9 -1
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +41 -0
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts +37 -0
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_project_environment_sh.js +105 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/particles/DESIGN.md +65 -8
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts +7 -1
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +1247 -1244
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts +7 -1
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +9 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +4 -2
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +15 -9
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +29 -11
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.d.ts +24 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.js +45 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +3 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +38 -0
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +190 -185
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +8 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +5 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +8 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +9 -0
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +13 -3
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +9 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts +39 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js +107 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.d.ts +15 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.js +44 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts +19 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +48 -0
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts +29 -0
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +90 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.d.ts +10 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.js +55 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.d.ts +10 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.js +47 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.d.ts +10 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.js +63 -0
- package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.d.ts +17 -0
- package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.js +26 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +8 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +50 -2
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +488 -436
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +254 -63
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The froxel irradiance volume: the light a transparent surface standing in a froxel receives, for
|
|
3
|
+
* surfaces the lighting pass cannot see — the particles. The froxel GI stage (`gi/`) starts it with
|
|
4
|
+
* whatever the renderer's indirect lighting mode says a point there receives — the environment,
|
|
5
|
+
* Brick4, the light probe volume — and `shader_volumetrics_build_lighting` adds, in the same loop
|
|
6
|
+
* that lights the fog, every directional, point and spot light, their shadows, and the fog's own
|
|
7
|
+
* attenuation toward each light. idTech 8 builds the same thing in the same pass ("Froxels
|
|
8
|
+
* Irradiance Volume", Sousa, SIGGRAPH 2025, p.29).
|
|
9
|
+
*
|
|
10
|
+
* Stored in the Metro Exodus L1 encoding (`l1i/`): luma as SH2 — four coefficients — and chroma as
|
|
11
|
+
* its constant band only. Two lights of different colours from opposite sides therefore light both
|
|
12
|
+
* sides in their luminance-weighted mix, not one colour each; that is the price of 6 coefficients
|
|
13
|
+
* instead of 12.
|
|
14
|
+
*
|
|
15
|
+
* Every light is added as a delta — all of its irradiance from one direction — and scaled by
|
|
16
|
+
* `1/(2 pi)`, which is the scale under which `resolve_irradiance_sh_to_diffuse(Y, CoCg, n)` returns
|
|
17
|
+
* `E(n) / pi`: the Lambertian radiance of a unit-albedo surface facing `n`. With SH2 that is
|
|
18
|
+
* `E * max(0, 1/4 + cos(theta)/2)` per light, over `pi` — the band-limited clamped cosine, a quarter
|
|
19
|
+
* dim at the peak and a quarter lit a right angle past the terminator.
|
|
20
|
+
*
|
|
21
|
+
* - `volumetrics_irradiance_sh_add(sh, irradiance, direction_to_light)` — one light's contribution,
|
|
22
|
+
* `irradiance` being what reaches the point at normal incidence and `direction_to_light` a unit
|
|
23
|
+
* vector pointing toward the light.
|
|
24
|
+
* - `volumetrics_irradiance_sh_add_radiance(sh, radiance)` — a whole radiance field arriving at the
|
|
25
|
+
* point, as RGB SH2: coefficients of radiance, not cosine-convolved, ordered `[DC, y, z, x]` in
|
|
26
|
+
* the project's all-positive basis (`sh2_basis_at`). The form every GI source hands over — the
|
|
27
|
+
* probes of Brick4 and of the light probe volume, and `GPULightCollection.environment_sh`. A light
|
|
28
|
+
* is the delta field `E sh2_basis_at(l)`, and adding it this way adds exactly what
|
|
29
|
+
* `volumetrics_irradiance_sh_add` does.
|
|
30
|
+
* - `volumetrics_irradiance_sh_storable(sh)` — what an `rgba16float` volume can hold. A clustered
|
|
31
|
+
* light close to a froxel exceeds half precision on its own and stores as +Inf, and an infinite
|
|
32
|
+
* luma times a zero band-1 basis is a NaN; either would reach every particle sampling that froxel.
|
|
33
|
+
* Non-finite coefficients become 0 and the rest are clamped to the half range.
|
|
34
|
+
*
|
|
35
|
+
* @type {CodeChunk}
|
|
36
|
+
*/
|
|
37
|
+
export const chunk_volumetrics_irradiance_sh: CodeChunk;
|
|
38
|
+
import { CodeChunk } from "../shader/compiler/CodeChunk.js";
|
|
39
|
+
//# sourceMappingURL=chunk_volumetrics_irradiance_sh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_volumetrics_irradiance_sh.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,8CAFU,SAAS,CA+DjB;0BAnGwB,iCAAiC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { F16_MAX_DEFINITION } from "../shader/chunk/math/F16_MAX_DEFINITION.js";
|
|
2
|
+
import { F32_MAX_DEFINITION } from "../shader/chunk/math/F32_MAX_DEFINITION.js";
|
|
3
|
+
import {
|
|
4
|
+
chunk_convert_to_irradiance_sh,
|
|
5
|
+
METRO_L1_IRRADIANCE_STRUCT
|
|
6
|
+
} from "../shader/chunk/spherical_harmonics/l1i/chunk_convert_to_irradiance_sh.js";
|
|
7
|
+
import { chunk_rgb_to_YCoCg } from "../shader/chunk/color/YCoCg/chunk_rgb_to_YCoCg.js";
|
|
8
|
+
import { CodeChunk } from "../shader/compiler/CodeChunk.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The froxel irradiance volume: the light a transparent surface standing in a froxel receives, for
|
|
12
|
+
* surfaces the lighting pass cannot see — the particles. The froxel GI stage (`gi/`) starts it with
|
|
13
|
+
* whatever the renderer's indirect lighting mode says a point there receives — the environment,
|
|
14
|
+
* Brick4, the light probe volume — and `shader_volumetrics_build_lighting` adds, in the same loop
|
|
15
|
+
* that lights the fog, every directional, point and spot light, their shadows, and the fog's own
|
|
16
|
+
* attenuation toward each light. idTech 8 builds the same thing in the same pass ("Froxels
|
|
17
|
+
* Irradiance Volume", Sousa, SIGGRAPH 2025, p.29).
|
|
18
|
+
*
|
|
19
|
+
* Stored in the Metro Exodus L1 encoding (`l1i/`): luma as SH2 — four coefficients — and chroma as
|
|
20
|
+
* its constant band only. Two lights of different colours from opposite sides therefore light both
|
|
21
|
+
* sides in their luminance-weighted mix, not one colour each; that is the price of 6 coefficients
|
|
22
|
+
* instead of 12.
|
|
23
|
+
*
|
|
24
|
+
* Every light is added as a delta — all of its irradiance from one direction — and scaled by
|
|
25
|
+
* `1/(2 pi)`, which is the scale under which `resolve_irradiance_sh_to_diffuse(Y, CoCg, n)` returns
|
|
26
|
+
* `E(n) / pi`: the Lambertian radiance of a unit-albedo surface facing `n`. With SH2 that is
|
|
27
|
+
* `E * max(0, 1/4 + cos(theta)/2)` per light, over `pi` — the band-limited clamped cosine, a quarter
|
|
28
|
+
* dim at the peak and a quarter lit a right angle past the terminator.
|
|
29
|
+
*
|
|
30
|
+
* - `volumetrics_irradiance_sh_add(sh, irradiance, direction_to_light)` — one light's contribution,
|
|
31
|
+
* `irradiance` being what reaches the point at normal incidence and `direction_to_light` a unit
|
|
32
|
+
* vector pointing toward the light.
|
|
33
|
+
* - `volumetrics_irradiance_sh_add_radiance(sh, radiance)` — a whole radiance field arriving at the
|
|
34
|
+
* point, as RGB SH2: coefficients of radiance, not cosine-convolved, ordered `[DC, y, z, x]` in
|
|
35
|
+
* the project's all-positive basis (`sh2_basis_at`). The form every GI source hands over — the
|
|
36
|
+
* probes of Brick4 and of the light probe volume, and `GPULightCollection.environment_sh`. A light
|
|
37
|
+
* is the delta field `E sh2_basis_at(l)`, and adding it this way adds exactly what
|
|
38
|
+
* `volumetrics_irradiance_sh_add` does.
|
|
39
|
+
* - `volumetrics_irradiance_sh_storable(sh)` — what an `rgba16float` volume can hold. A clustered
|
|
40
|
+
* light close to a froxel exceeds half precision on its own and stores as +Inf, and an infinite
|
|
41
|
+
* luma times a zero band-1 basis is a NaN; either would reach every particle sampling that froxel.
|
|
42
|
+
* Non-finite coefficients become 0 and the rest are clamped to the half range.
|
|
43
|
+
*
|
|
44
|
+
* @type {CodeChunk}
|
|
45
|
+
*/
|
|
46
|
+
export const chunk_volumetrics_irradiance_sh = CodeChunk.from(
|
|
47
|
+
//language=WGSL
|
|
48
|
+
`
|
|
49
|
+
const VOLUMETRICS_IRRADIANCE_SH_SCALE : f32 = 0.15915494309189535; // 1 / (2 pi)
|
|
50
|
+
|
|
51
|
+
fn volumetrics_irradiance_sh_add(
|
|
52
|
+
sh: ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref},
|
|
53
|
+
irradiance: vec3<f32>,
|
|
54
|
+
direction_to_light: vec3<f32>,
|
|
55
|
+
) -> ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref} {
|
|
56
|
+
let light = convert_to_irradiance_sh(irradiance * VOLUMETRICS_IRRADIANCE_SH_SCALE, direction_to_light);
|
|
57
|
+
|
|
58
|
+
return ${METRO_L1_IRRADIANCE_STRUCT.make({
|
|
59
|
+
CoCg: "sh.CoCg + light.CoCg",
|
|
60
|
+
Y: "sh.Y + light.Y",
|
|
61
|
+
})};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fn volumetrics_irradiance_sh_add_radiance(
|
|
65
|
+
sh: ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref},
|
|
66
|
+
radiance: array<vec3<f32>, 4>,
|
|
67
|
+
) -> ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref} {
|
|
68
|
+
// luma carries all four coefficients, chroma the constant band only; YCoCg is linear, so the
|
|
69
|
+
// transform goes through the coefficients as it would through the colours
|
|
70
|
+
let c0 = rgb_to_YCoCg(radiance[0]);
|
|
71
|
+
|
|
72
|
+
// the Metro layout is (x, y, z, constant); the basis order is (constant, y, z, x)
|
|
73
|
+
let Y = vec4<f32>(
|
|
74
|
+
rgb_to_YCoCg(radiance[3]).x,
|
|
75
|
+
rgb_to_YCoCg(radiance[1]).x,
|
|
76
|
+
rgb_to_YCoCg(radiance[2]).x,
|
|
77
|
+
c0.x,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// the chroma a light adds is its irradiance's own, not times the band-0 basis constant
|
|
81
|
+
const BAND_0_BASIS : f32 = 0.28209479177387814;
|
|
82
|
+
|
|
83
|
+
return ${METRO_L1_IRRADIANCE_STRUCT.make({
|
|
84
|
+
CoCg: "sh.CoCg + c0.yz * (VOLUMETRICS_IRRADIANCE_SH_SCALE / BAND_0_BASIS)",
|
|
85
|
+
Y: "sh.Y + Y * VOLUMETRICS_IRRADIANCE_SH_SCALE",
|
|
86
|
+
})};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fn volumetrics_irradiance_sh_storable(sh: ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref}) -> ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref} {
|
|
90
|
+
// the comparison is what WGSL defines for a NaN; clamp is not
|
|
91
|
+
let Y_finite = (sh.Y == sh.Y) & (abs(sh.Y) < vec4<f32>(F32_MAX));
|
|
92
|
+
let CoCg_finite = (sh.CoCg == sh.CoCg) & (abs(sh.CoCg) < vec2<f32>(F32_MAX));
|
|
93
|
+
|
|
94
|
+
return ${METRO_L1_IRRADIANCE_STRUCT.make({
|
|
95
|
+
CoCg: "select(vec2<f32>(0.0), clamp(sh.CoCg, vec2<f32>(-F16_MAX), vec2<f32>(F16_MAX)), CoCg_finite)",
|
|
96
|
+
Y: "select(vec4<f32>(0.0), clamp(sh.Y, vec4<f32>(-F16_MAX), vec4<f32>(F16_MAX)), Y_finite)",
|
|
97
|
+
})};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
`, [
|
|
101
|
+
chunk_convert_to_irradiance_sh,
|
|
102
|
+
chunk_rgb_to_YCoCg,
|
|
103
|
+
METRO_L1_IRRADIANCE_STRUCT.declaration_chunk,
|
|
104
|
+
F16_MAX_DEFINITION,
|
|
105
|
+
F32_MAX_DEFINITION,
|
|
106
|
+
]
|
|
107
|
+
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `volumetrics_froxel_centre_ws(voxel, resolution)` — the world position a froxel's value stands for:
|
|
3
|
+
* its column's centre, at the depth its slab's content sits at (`volumetrics_froxel_content_offset`),
|
|
4
|
+
* which is where the lighting pass's jittered samples average to and where
|
|
5
|
+
* `volumetrics_position_world_to_froxel_uvw` puts the froxel's texel centre. A froxel GI module
|
|
6
|
+
* whose answer depends on position asks it there; GI is smooth enough across a froxel that one
|
|
7
|
+
* sample is all of it.
|
|
8
|
+
*
|
|
9
|
+
* The enclosing shader binds `camera` and `volumetrics_metadata` under those names.
|
|
10
|
+
*
|
|
11
|
+
* @type {CodeChunk}
|
|
12
|
+
*/
|
|
13
|
+
export const chunk_volumetrics_froxel_centre_ws: CodeChunk;
|
|
14
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
15
|
+
//# sourceMappingURL=chunk_volumetrics_froxel_centre_ws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_volumetrics_froxel_centre_ws.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;GAWG;AACH,iDAFU,SAAS,CAyBjB;0BAvCwB,oCAAoC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { chunk_cluster_depth_from_z_slice } from "../../light/cluster/chunk_cluster_depth_from_z_slice.js";
|
|
2
|
+
import { chunk_camera_ray_from_uv } from "../../shader/chunk/geometry/ray/chunk_camera_ray_from_uv.js";
|
|
3
|
+
import { RAY_STRUCT } from "../../shader/chunk/geometry/ray/RAY_STRUCT.js";
|
|
4
|
+
import { chunk_texel_coordinate_to_uv } from "../../shader/chunk/texture/chunk_texel_coordinate_to_uv.js";
|
|
5
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
6
|
+
import { chunk_camera_ray_planar_depth_scale } from "../chunk_camera_ray_planar_depth_scale.js";
|
|
7
|
+
import { chunk_volumetrics_froxel_content_offset } from "../chunk_volumetrics_froxel_content_offset.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `volumetrics_froxel_centre_ws(voxel, resolution)` — the world position a froxel's value stands for:
|
|
11
|
+
* its column's centre, at the depth its slab's content sits at (`volumetrics_froxel_content_offset`),
|
|
12
|
+
* which is where the lighting pass's jittered samples average to and where
|
|
13
|
+
* `volumetrics_position_world_to_froxel_uvw` puts the froxel's texel centre. A froxel GI module
|
|
14
|
+
* whose answer depends on position asks it there; GI is smooth enough across a froxel that one
|
|
15
|
+
* sample is all of it.
|
|
16
|
+
*
|
|
17
|
+
* The enclosing shader binds `camera` and `volumetrics_metadata` under those names.
|
|
18
|
+
*
|
|
19
|
+
* @type {CodeChunk}
|
|
20
|
+
*/
|
|
21
|
+
export const chunk_volumetrics_froxel_centre_ws = CodeChunk.from(
|
|
22
|
+
//language=WGSL
|
|
23
|
+
`
|
|
24
|
+
fn volumetrics_froxel_centre_ws(voxel: vec3<u32>, resolution: vec3<u32>) -> vec3<f32> {
|
|
25
|
+
let curve = volumetrics_metadata.froxel_cluster_parameters;
|
|
26
|
+
let near_far = camera.clip_near_far;
|
|
27
|
+
|
|
28
|
+
let slice = f32(voxel.z) + volumetrics_froxel_content_offset(curve.z);
|
|
29
|
+
let view_depth = clamp(cluster_depth_from_z_slice(slice, curve, f32(resolution.z)), near_far.x, near_far.y);
|
|
30
|
+
|
|
31
|
+
let ray = camera_ray_from_uv(texel_coordinate_to_uv(vec2<f32>(voxel.xy), resolution.xy), camera);
|
|
32
|
+
|
|
33
|
+
// planar depth to a distance along the ray, as the lighting pass does
|
|
34
|
+
return ray.origin + ray.direction * (view_depth * camera_ray_planar_depth_scale(ray.direction, camera));
|
|
35
|
+
}
|
|
36
|
+
`, [
|
|
37
|
+
RAY_STRUCT.declaration_chunk,
|
|
38
|
+
chunk_volumetrics_froxel_content_offset,
|
|
39
|
+
chunk_cluster_depth_from_z_slice,
|
|
40
|
+
chunk_camera_ray_from_uv,
|
|
41
|
+
chunk_texel_coordinate_to_uv,
|
|
42
|
+
chunk_camera_ray_planar_depth_scale,
|
|
43
|
+
]
|
|
44
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every froxel GI module shares. A module is one concrete compute shader per indirect lighting
|
|
3
|
+
* mode (`shader_volumetrics_gi_ibl`, `_brick4`, `_lpv`), one thread per froxel: it asks its mode what
|
|
4
|
+
* radiance arrives at the froxel, as RGB SH2, and hands the answer to `volumetrics_gi_store`. That
|
|
5
|
+
* starts the froxel irradiance volume, and `shader_volumetrics_build_lighting` adds the lights to it.
|
|
6
|
+
* A new mode is one more module: nothing downstream knows which mode wrote the volume.
|
|
7
|
+
*
|
|
8
|
+
* `volumetrics_froxel_centre_ws` (`chunk_volumetrics_froxel_centre_ws`) says where a froxel is, for a
|
|
9
|
+
* mode whose answer depends on position; `volumetrics_gi_store(voxel, radiance)` — scales the field by `INDIRECT_LIGHT_INTENSITY`, as the
|
|
10
|
+
* deferred and forward paths scale their indirect light, encodes it as the volume stores light
|
|
11
|
+
* (`volumetrics_irradiance_sh_add_radiance`) and writes it to `tGIY` / `tGICoCg`.
|
|
12
|
+
*
|
|
13
|
+
* The enclosing shader binds `tGIY` and `tGICoCg` under those names.
|
|
14
|
+
*
|
|
15
|
+
* @type {CodeChunk}
|
|
16
|
+
*/
|
|
17
|
+
export const chunk_volumetrics_gi: CodeChunk;
|
|
18
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
19
|
+
//# sourceMappingURL=chunk_volumetrics_gi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_volumetrics_gi.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;GAeG;AACH,mCAFU,SAAS,CA0BjB;0BA5CwB,oCAAoC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
METRO_L1_IRRADIANCE_STRUCT
|
|
3
|
+
} from "../../shader/chunk/spherical_harmonics/l1i/chunk_convert_to_irradiance_sh.js";
|
|
4
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
5
|
+
import { INDIRECT_LIGHT_INTENSITY } from "../../deferred/INDIRECT_LIGHT_INTENSITY.js";
|
|
6
|
+
import { chunk_volumetrics_irradiance_sh } from "../chunk_volumetrics_irradiance_sh.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What every froxel GI module shares. A module is one concrete compute shader per indirect lighting
|
|
10
|
+
* mode (`shader_volumetrics_gi_ibl`, `_brick4`, `_lpv`), one thread per froxel: it asks its mode what
|
|
11
|
+
* radiance arrives at the froxel, as RGB SH2, and hands the answer to `volumetrics_gi_store`. That
|
|
12
|
+
* starts the froxel irradiance volume, and `shader_volumetrics_build_lighting` adds the lights to it.
|
|
13
|
+
* A new mode is one more module: nothing downstream knows which mode wrote the volume.
|
|
14
|
+
*
|
|
15
|
+
* `volumetrics_froxel_centre_ws` (`chunk_volumetrics_froxel_centre_ws`) says where a froxel is, for a
|
|
16
|
+
* mode whose answer depends on position; `volumetrics_gi_store(voxel, radiance)` — scales the field by `INDIRECT_LIGHT_INTENSITY`, as the
|
|
17
|
+
* deferred and forward paths scale their indirect light, encodes it as the volume stores light
|
|
18
|
+
* (`volumetrics_irradiance_sh_add_radiance`) and writes it to `tGIY` / `tGICoCg`.
|
|
19
|
+
*
|
|
20
|
+
* The enclosing shader binds `tGIY` and `tGICoCg` under those names.
|
|
21
|
+
*
|
|
22
|
+
* @type {CodeChunk}
|
|
23
|
+
*/
|
|
24
|
+
export const chunk_volumetrics_gi = CodeChunk.from(
|
|
25
|
+
//language=WGSL
|
|
26
|
+
`
|
|
27
|
+
fn volumetrics_gi_store(voxel: vec3<u32>, radiance: array<vec3<f32>, 4>) {
|
|
28
|
+
const INDIRECT_INTENSITY : f32 = ${INDIRECT_LIGHT_INTENSITY};
|
|
29
|
+
|
|
30
|
+
let scaled = array<vec3<f32>, 4>(
|
|
31
|
+
radiance[0] * INDIRECT_INTENSITY,
|
|
32
|
+
radiance[1] * INDIRECT_INTENSITY,
|
|
33
|
+
radiance[2] * INDIRECT_INTENSITY,
|
|
34
|
+
radiance[3] * INDIRECT_INTENSITY,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
var sh: ${METRO_L1_IRRADIANCE_STRUCT.wgsl_ref};
|
|
38
|
+
|
|
39
|
+
let stored = volumetrics_irradiance_sh_storable(volumetrics_irradiance_sh_add_radiance(sh, scaled));
|
|
40
|
+
|
|
41
|
+
textureStore(tGIY, voxel, stored.Y);
|
|
42
|
+
textureStore(tGICoCg, voxel, vec4<f32>(stored.CoCg, 0.0, 0.0));
|
|
43
|
+
}
|
|
44
|
+
`, [
|
|
45
|
+
METRO_L1_IRRADIANCE_STRUCT.declaration_chunk,
|
|
46
|
+
chunk_volumetrics_irradiance_sh,
|
|
47
|
+
]
|
|
48
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The froxel GI stage: the renderer's indirect lighting at every froxel, as the froxel irradiance
|
|
3
|
+
* volume encodes light, for `shader_volumetrics_build_lighting` to add the lights to. One module per
|
|
4
|
+
* mode (see `chunk_volumetrics_gi`); this picks the one `indirect_lighting_mode` names and binds its
|
|
5
|
+
* source from the scene.
|
|
6
|
+
*
|
|
7
|
+
* @param {object} options
|
|
8
|
+
* @param {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} options.graph
|
|
9
|
+
* @param {ShadeIndirectLightingMode} options.indirect_lighting_mode
|
|
10
|
+
* @param {import("../../scene/GPUSceneContext.js").GPUSceneContext} options.scene_ctx the GI sources:
|
|
11
|
+
* `lights.environment_sh`, `volumetric_light_map`, `light_probe_volume`
|
|
12
|
+
* @param {import("../../camera/GPUCameraContext.js").GPUCameraContext} options.camera
|
|
13
|
+
* @param {number} options.volumetrics_metadata graph handle
|
|
14
|
+
* @param {number[]} options.resolution the froxel grid
|
|
15
|
+
* @returns {{Y: number, CoCg: number}} handles of the GI volume, in the froxel irradiance encoding
|
|
16
|
+
*/
|
|
17
|
+
export function graph_build_froxel_gi({ graph, indirect_lighting_mode, scene_ctx, camera, volumetrics_metadata, resolution, }: {
|
|
18
|
+
graph: import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
19
|
+
indirect_lighting_mode: ShadeIndirectLightingMode;
|
|
20
|
+
scene_ctx: import("../../scene/GPUSceneContext.js").GPUSceneContext;
|
|
21
|
+
camera: import("../../camera/GPUCameraContext.js").GPUCameraContext;
|
|
22
|
+
volumetrics_metadata: number;
|
|
23
|
+
resolution: number[];
|
|
24
|
+
}): {
|
|
25
|
+
Y: number;
|
|
26
|
+
CoCg: number;
|
|
27
|
+
};
|
|
28
|
+
import { ShadeIndirectLightingMode } from "../../ShadeIndirectLightingMode.js";
|
|
29
|
+
//# sourceMappingURL=graph_build_froxel_gi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph_build_froxel_gi.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;GAeG;AACH;IATsG,KAAK,EAAhG,OAAO,8DAA8D,EAAE,UAAU;IAC9C,sBAAsB,EAAzD,yBAAyB;IACyC,SAAS,EAA3E,OAAO,gCAAgC,EAAE,eAAe;IAEa,MAAM,EAA3E,OAAO,kCAAkC,EAAE,gBAAgB;IAC3C,oBAAoB,EAApC,MAAM;IACY,UAAU,EAA5B,MAAM,EAAE;IACN;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAkErC;0CAtFyC,oCAAoC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { TextureResourceDescriptor } from "../../../device/graph/TextureResourceDescriptor.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 { ShadeIndirectLightingMode } from "../../ShadeIndirectLightingMode.js";
|
|
5
|
+
import { shader_volumetrics_gi_brick4 } from "./shader_volumetrics_gi_brick4.js";
|
|
6
|
+
import { shader_volumetrics_gi_ibl } from "./shader_volumetrics_gi_ibl.js";
|
|
7
|
+
import { shader_volumetrics_gi_lpv } from "./shader_volumetrics_gi_lpv.js";
|
|
8
|
+
import { VOLUMETRICS_GI_WORKGROUP_RESOLUTION } from "./volumetrics_gi_resources.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The froxel GI stage: the renderer's indirect lighting at every froxel, as the froxel irradiance
|
|
12
|
+
* volume encodes light, for `shader_volumetrics_build_lighting` to add the lights to. One module per
|
|
13
|
+
* mode (see `chunk_volumetrics_gi`); this picks the one `indirect_lighting_mode` names and binds its
|
|
14
|
+
* source from the scene.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} options
|
|
17
|
+
* @param {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} options.graph
|
|
18
|
+
* @param {ShadeIndirectLightingMode} options.indirect_lighting_mode
|
|
19
|
+
* @param {import("../../scene/GPUSceneContext.js").GPUSceneContext} options.scene_ctx the GI sources:
|
|
20
|
+
* `lights.environment_sh`, `volumetric_light_map`, `light_probe_volume`
|
|
21
|
+
* @param {import("../../camera/GPUCameraContext.js").GPUCameraContext} options.camera
|
|
22
|
+
* @param {number} options.volumetrics_metadata graph handle
|
|
23
|
+
* @param {number[]} options.resolution the froxel grid
|
|
24
|
+
* @returns {{Y: number, CoCg: number}} handles of the GI volume, in the froxel irradiance encoding
|
|
25
|
+
*/
|
|
26
|
+
export function graph_build_froxel_gi({
|
|
27
|
+
graph,
|
|
28
|
+
indirect_lighting_mode,
|
|
29
|
+
scene_ctx,
|
|
30
|
+
camera,
|
|
31
|
+
volumetrics_metadata,
|
|
32
|
+
resolution,
|
|
33
|
+
}) {
|
|
34
|
+
const volume = () => TextureResourceDescriptor.from({
|
|
35
|
+
resolution,
|
|
36
|
+
dimension: "3d",
|
|
37
|
+
format: "rgba16float",
|
|
38
|
+
usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const bindings = {
|
|
42
|
+
volumetrics_metadata,
|
|
43
|
+
camera: graph_import_buffer(graph, camera.buffer.buffer, "froxel gi camera"),
|
|
44
|
+
tGIY: volume(),
|
|
45
|
+
tGICoCg: volume(),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
let shader;
|
|
49
|
+
|
|
50
|
+
switch (indirect_lighting_mode) {
|
|
51
|
+
case ShadeIndirectLightingMode.IBL:
|
|
52
|
+
shader = shader_volumetrics_gi_ibl;
|
|
53
|
+
bindings.environment_sh = scene_ctx.lights.environment_sh;
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
case ShadeIndirectLightingMode.Brick4:
|
|
57
|
+
shader = shader_volumetrics_gi_brick4;
|
|
58
|
+
bindings.brick4 = scene_ctx.volumetric_light_map.buffer;
|
|
59
|
+
break;
|
|
60
|
+
|
|
61
|
+
case ShadeIndirectLightingMode.LPV: {
|
|
62
|
+
shader = shader_volumetrics_gi_lpv;
|
|
63
|
+
const lpv = scene_ctx.light_probe_volume;
|
|
64
|
+
bindings.lpv_lookup = lpv.buffer_mesh_bvh;
|
|
65
|
+
bindings.lpv_metadata = lpv.buffer_metadata;
|
|
66
|
+
bindings.lpv_mesh = lpv.buffer_mesh;
|
|
67
|
+
bindings.lpv_probes = lpv.buffer_probes;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Unsupported indirect lighting mode: ${indirect_lighting_mode}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const outputs = graph_compute_pass({
|
|
76
|
+
graph,
|
|
77
|
+
shader,
|
|
78
|
+
group_count: [
|
|
79
|
+
Math.ceil(resolution[0] / VOLUMETRICS_GI_WORKGROUP_RESOLUTION[0]),
|
|
80
|
+
Math.ceil(resolution[1] / VOLUMETRICS_GI_WORKGROUP_RESOLUTION[1]),
|
|
81
|
+
Math.ceil(resolution[2] / VOLUMETRICS_GI_WORKGROUP_RESOLUTION[2]),
|
|
82
|
+
],
|
|
83
|
+
bindings,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
Y: outputs.tGIY,
|
|
88
|
+
CoCg: outputs.tGICoCg,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Froxel GI under `ShadeIndirectLightingMode.Brick4`: the sparse volumetric lightmap's probes,
|
|
3
|
+
* interpolated at each froxel's centre and truncated from SH3 to SH2. See `chunk_volumetrics_gi` for
|
|
4
|
+
* what a GI module is.
|
|
5
|
+
*
|
|
6
|
+
* @type {ComputeShader}
|
|
7
|
+
*/
|
|
8
|
+
export const shader_volumetrics_gi_brick4: ComputeShader;
|
|
9
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
10
|
+
//# sourceMappingURL=shader_volumetrics_gi_brick4.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_volumetrics_gi_brick4.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.js"],"names":[],"mappings":"AA2CA;;;;;;GAMG;AACH,2CAFU,aAAa,CAMpB;8BAnD2B,+BAA+B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BRICK4_DATA_STRUCT } from "../../global_illumination/brick4/gpu/BRICK4_DATA_STRUCT.js";
|
|
2
|
+
import { chunk_brick4_sample_sh } from "../../global_illumination/brick4/gpu/draw/chunk_brick4_sample_sh.js";
|
|
3
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
4
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
5
|
+
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
6
|
+
import { chunk_volumetrics_gi } from "./chunk_volumetrics_gi.js";
|
|
7
|
+
import { chunk_volumetrics_froxel_centre_ws } from "./chunk_volumetrics_froxel_centre_ws.js";
|
|
8
|
+
import { VOLUMETRICS_GI_WORKGROUP_RESOLUTION, volumetrics_gi_resource_group } from "./volumetrics_gi_resources.js";
|
|
9
|
+
|
|
10
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
11
|
+
|
|
12
|
+
resources.addGroup(
|
|
13
|
+
volumetrics_gi_resource_group()
|
|
14
|
+
.addStorageBuffer("brick4", BRICK4_DATA_STRUCT)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const body = CodeChunk.from(
|
|
18
|
+
//language=WGSL
|
|
19
|
+
`
|
|
20
|
+
@compute @workgroup_size(${VOLUMETRICS_GI_WORKGROUP_RESOLUTION.join(", ")})
|
|
21
|
+
fn main(@builtin(global_invocation_id) voxel: vec3<u32>) {
|
|
22
|
+
let resolution = textureDimensions(tGIY);
|
|
23
|
+
|
|
24
|
+
if (any(voxel >= resolution)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let position = volumetrics_froxel_centre_ws(voxel, resolution);
|
|
29
|
+
|
|
30
|
+
// A froxel has no surface. The normal only masks probes behind one, and a zero normal weighs
|
|
31
|
+
// every probe of the brick the same (brick4_probe_compute_weight_by_normal), which is the
|
|
32
|
+
// interpolation a point in open space wants.
|
|
33
|
+
let sh = brick4_sample_sh(position, vec3<f32>(0.0));
|
|
34
|
+
|
|
35
|
+
// SH3 to SH2: the first four coefficients are the same two bands, in the same order
|
|
36
|
+
volumetrics_gi_store(voxel, array<vec3<f32>, 4>(sh[0], sh[1], sh[2], sh[3]));
|
|
37
|
+
}
|
|
38
|
+
`, [
|
|
39
|
+
chunk_volumetrics_gi,
|
|
40
|
+
chunk_volumetrics_froxel_centre_ws,
|
|
41
|
+
chunk_brick4_sample_sh,
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Froxel GI under `ShadeIndirectLightingMode.Brick4`: the sparse volumetric lightmap's probes,
|
|
46
|
+
* interpolated at each froxel's centre and truncated from SH3 to SH2. See `chunk_volumetrics_gi` for
|
|
47
|
+
* what a GI module is.
|
|
48
|
+
*
|
|
49
|
+
* @type {ComputeShader}
|
|
50
|
+
*/
|
|
51
|
+
export const shader_volumetrics_gi_brick4 = ComputeShader.from({
|
|
52
|
+
label: "Volumetrics / GI Brick4",
|
|
53
|
+
resources,
|
|
54
|
+
body,
|
|
55
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Froxel GI under `ShadeIndirectLightingMode.IBL`: the environment, as
|
|
3
|
+
* `GPULightCollection.environment_sh` holds it (`shader_project_environment_sh`), at every froxel.
|
|
4
|
+
* See `chunk_volumetrics_gi` for what a GI module is.
|
|
5
|
+
*
|
|
6
|
+
* @type {ComputeShader}
|
|
7
|
+
*/
|
|
8
|
+
export const shader_volumetrics_gi_ibl: ComputeShader;
|
|
9
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
10
|
+
//# sourceMappingURL=shader_volumetrics_gi_ibl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_volumetrics_gi_ibl.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.js"],"names":[],"mappings":"AAmCA;;;;;;GAMG;AACH,wCAFU,aAAa,CAMpB;8BA5C2B,+BAA+B"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ENVIRONMENT_SH_TYPE } from "../../light/environment/shader_project_environment_sh.js";
|
|
2
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
3
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
4
|
+
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
5
|
+
import { chunk_volumetrics_gi } from "./chunk_volumetrics_gi.js";
|
|
6
|
+
import { VOLUMETRICS_GI_WORKGROUP_RESOLUTION, volumetrics_gi_resource_group } from "./volumetrics_gi_resources.js";
|
|
7
|
+
|
|
8
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
9
|
+
|
|
10
|
+
resources.addGroup(
|
|
11
|
+
volumetrics_gi_resource_group()
|
|
12
|
+
.addUniform("environment_sh", ENVIRONMENT_SH_TYPE)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const body = CodeChunk.from(
|
|
16
|
+
//language=WGSL
|
|
17
|
+
`
|
|
18
|
+
@compute @workgroup_size(${VOLUMETRICS_GI_WORKGROUP_RESOLUTION.join(", ")})
|
|
19
|
+
fn main(@builtin(global_invocation_id) voxel: vec3<u32>) {
|
|
20
|
+
if (any(voxel >= textureDimensions(tGIY))) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// the environment is infinitely far: every froxel receives the same field
|
|
25
|
+
volumetrics_gi_store(voxel, array<vec3<f32>, 4>(
|
|
26
|
+
environment_sh[0].xyz,
|
|
27
|
+
environment_sh[1].xyz,
|
|
28
|
+
environment_sh[2].xyz,
|
|
29
|
+
environment_sh[3].xyz,
|
|
30
|
+
));
|
|
31
|
+
}
|
|
32
|
+
`, [
|
|
33
|
+
chunk_volumetrics_gi,
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Froxel GI under `ShadeIndirectLightingMode.IBL`: the environment, as
|
|
38
|
+
* `GPULightCollection.environment_sh` holds it (`shader_project_environment_sh`), at every froxel.
|
|
39
|
+
* See `chunk_volumetrics_gi` for what a GI module is.
|
|
40
|
+
*
|
|
41
|
+
* @type {ComputeShader}
|
|
42
|
+
*/
|
|
43
|
+
export const shader_volumetrics_gi_ibl = ComputeShader.from({
|
|
44
|
+
label: "Volumetrics / GI IBL",
|
|
45
|
+
resources,
|
|
46
|
+
body,
|
|
47
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Froxel GI under `ShadeIndirectLightingMode.LPV`: the light probe volume's tetrahedral mesh, its
|
|
3
|
+
* probes (radiance SH2) interpolated barycentrically at each froxel's centre. See
|
|
4
|
+
* `chunk_volumetrics_gi` for what a GI module is.
|
|
5
|
+
*
|
|
6
|
+
* @type {ComputeShader}
|
|
7
|
+
*/
|
|
8
|
+
export const shader_volumetrics_gi_lpv: ComputeShader;
|
|
9
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
10
|
+
//# sourceMappingURL=shader_volumetrics_gi_lpv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_volumetrics_gi_lpv.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.js"],"names":[],"mappings":"AAmDA;;;;;;GAMG;AACH,wCAFU,aAAa,CAMpB;8BAzD2B,+BAA+B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { LPV_SHADER_RESOURCE_GROUP } from "../../global_illumination/probe/octahedral/LPV_SHADER_RESOURCE_GROUP.js";
|
|
2
|
+
import { chunk_lpv_mesh_interpolation_probe_sh } from "../../shader/chunk/light/lpv/chunk_lpv_mesh_interpolation_probe_sh.js";
|
|
3
|
+
import { chunk_lpv_mesh_lookup_nearest_cell } from "../../shader/chunk/light/lpv/chunk_lpv_mesh_lookup_nearest_cell.js";
|
|
4
|
+
import { INVALID_TET_DECLARATION } from "../../shader/chunk/light/lpv/INVALID_TET_DECLARATION.js";
|
|
5
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
6
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
7
|
+
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
8
|
+
import { chunk_volumetrics_gi } from "./chunk_volumetrics_gi.js";
|
|
9
|
+
import { chunk_volumetrics_froxel_centre_ws } from "./chunk_volumetrics_froxel_centre_ws.js";
|
|
10
|
+
import { VOLUMETRICS_GI_WORKGROUP_RESOLUTION, volumetrics_gi_resource_group } from "./volumetrics_gi_resources.js";
|
|
11
|
+
|
|
12
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
13
|
+
|
|
14
|
+
resources.addGroup(volumetrics_gi_resource_group());
|
|
15
|
+
resources.addGroup(LPV_SHADER_RESOURCE_GROUP);
|
|
16
|
+
|
|
17
|
+
const body = CodeChunk.from(
|
|
18
|
+
//language=WGSL
|
|
19
|
+
`
|
|
20
|
+
@compute @workgroup_size(${VOLUMETRICS_GI_WORKGROUP_RESOLUTION.join(", ")})
|
|
21
|
+
fn main(@builtin(global_invocation_id) voxel: vec3<u32>) {
|
|
22
|
+
let resolution = textureDimensions(tGIY);
|
|
23
|
+
|
|
24
|
+
if (any(voxel >= resolution)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let position = volumetrics_froxel_centre_ws(voxel, resolution);
|
|
29
|
+
|
|
30
|
+
var weights: vec4<f32>;
|
|
31
|
+
let tet = lpv_mesh_lookup_nearest_cell(position, &weights);
|
|
32
|
+
|
|
33
|
+
// Outside the probe mesh there is nothing to interpolate, and the deferred LPV pass gives such a
|
|
34
|
+
// point no indirect light either. No visibility mask: that needs a surface normal, and a froxel
|
|
35
|
+
// has none.
|
|
36
|
+
var radiance = array<vec3<f32>, 4>();
|
|
37
|
+
|
|
38
|
+
if (tet != INVALID_TET) {
|
|
39
|
+
radiance = lpv_mesh_interpolation_probe_sh(weights, tet);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
volumetrics_gi_store(voxel, radiance);
|
|
43
|
+
}
|
|
44
|
+
`, [
|
|
45
|
+
chunk_volumetrics_gi,
|
|
46
|
+
chunk_volumetrics_froxel_centre_ws,
|
|
47
|
+
chunk_lpv_mesh_lookup_nearest_cell,
|
|
48
|
+
chunk_lpv_mesh_interpolation_probe_sh,
|
|
49
|
+
INVALID_TET_DECLARATION,
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Froxel GI under `ShadeIndirectLightingMode.LPV`: the light probe volume's tetrahedral mesh, its
|
|
54
|
+
* probes (radiance SH2) interpolated barycentrically at each froxel's centre. See
|
|
55
|
+
* `chunk_volumetrics_gi` for what a GI module is.
|
|
56
|
+
*
|
|
57
|
+
* @type {ComputeShader}
|
|
58
|
+
*/
|
|
59
|
+
export const shader_volumetrics_gi_lpv = ComputeShader.from({
|
|
60
|
+
label: "Volumetrics / GI LPV",
|
|
61
|
+
resources,
|
|
62
|
+
body,
|
|
63
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bindings every froxel GI module has, whatever its mode reads: where the froxels are, and the
|
|
3
|
+
* two volumes it writes (`chunk_volumetrics_gi`). rgba16float for both, because rg16float is not a
|
|
4
|
+
* storage format without texture-formats-tier1.
|
|
5
|
+
*
|
|
6
|
+
* @returns {ShaderResourceGroupDescriptor}
|
|
7
|
+
*/
|
|
8
|
+
export function volumetrics_gi_resource_group(): ShaderResourceGroupDescriptor;
|
|
9
|
+
/**
|
|
10
|
+
* Workgroup shape of every froxel GI module, `[x, y, z]` in froxels: flat in z like the lighting
|
|
11
|
+
* pass, and 64 invocations.
|
|
12
|
+
*
|
|
13
|
+
* @type {number[]}
|
|
14
|
+
*/
|
|
15
|
+
export const VOLUMETRICS_GI_WORKGROUP_RESOLUTION: number[];
|
|
16
|
+
import { ShaderResourceGroupDescriptor } from "../../shader/resource/ShaderResourceGroupDescriptor.js";
|
|
17
|
+
//# sourceMappingURL=volumetrics_gi_resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"volumetrics_gi_resources.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,iDAFa,6BAA6B,CAQzC;AAED;;;;;GAKG;AACH,kDAFU,MAAM,EAAE,CAE2C;8CAxBf,wDAAwD"}
|