@woosh/meep-engine 3.42.0 → 3.43.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 +91 -96
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/vgeo_runtime/README.md +5 -4
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +6 -5
- package/src/shade/renderer/atmosphere/GPUSky.d.ts +12 -0
- package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/GPUSky.js +162 -147
- package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +10 -3
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/particles/DESIGN.md +13 -9
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +9 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +23 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +4 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +74 -3
- package/src/shade/renderer/volumetrics/NOTES.md +1023 -957
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts +5 -4
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js +5 -4
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts +1 -1
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +1 -1
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts +1 -1
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +1 -1
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +41 -0
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +112 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +9 -23
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +18 -126
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts +22 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.js +228 -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 +0 -53
- package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts +4 -3
- package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/chunk_water_surface_sample.js +17 -7
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +69 -23
- package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.js +13 -5
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts +29 -8
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +155 -30
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts +6 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.js +157 -39
- package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts +91 -21
- package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/shader_water_particles.js +442 -70
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +11 -3
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +3 -0
|
@@ -39,8 +39,15 @@ fn estimate_sh_similarity(
|
|
|
39
39
|
// extract dominant luma direction
|
|
40
40
|
// Metro encodes SH coeffcients in axis-aligned way (L11, L1_1, L10) with L00 being in forth position (w)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
// Zero DC is black and has no dominant direction.
|
|
43
|
+
var a_luma_direction = vec3<f32>(0.0);
|
|
44
|
+
var b_luma_direction = vec3<f32>(0.0);
|
|
45
|
+
if (a.Y.w != 0.0) {
|
|
46
|
+
a_luma_direction = a.Y.xyz / a.Y.w;
|
|
47
|
+
}
|
|
48
|
+
if (b.Y.w != 0.0) {
|
|
49
|
+
b_luma_direction = b.Y.xyz / b.Y.w;
|
|
50
|
+
}
|
|
44
51
|
|
|
45
52
|
const DIRECTION_PHI = 10.0;
|
|
46
53
|
|
|
@@ -189,4 +196,4 @@ export const shader_lightmap_denoise_sh = ImageShader.from({
|
|
|
189
196
|
resources,
|
|
190
197
|
}),
|
|
191
198
|
targets: LIGHTMAP_SH_COLOR_TARGETS_DESCRIPTOR
|
|
192
|
-
})
|
|
199
|
+
})
|
|
@@ -13,7 +13,7 @@ export class TinyGltf {
|
|
|
13
13
|
* @readonly
|
|
14
14
|
* @type {TextureFormat}
|
|
15
15
|
*/
|
|
16
|
-
static readonly "__#
|
|
16
|
+
static readonly "__#265@#UNCOMPRESSED_TARGET": TextureFormat;
|
|
17
17
|
/**
|
|
18
18
|
* @param {AssetManager} assetManager
|
|
19
19
|
* @param {AssetRequestScope} [scope]
|
|
@@ -791,14 +791,18 @@ it is evaluated per pixel (`chunk_particle_lighting`, the model in `chunk_partic
|
|
|
791
791
|
a vertex need not be on screen, and one quad can span the frustum.
|
|
792
792
|
|
|
793
793
|
- **Direct light comes from the froxel irradiance volume** (`volumetrics/chunk_volumetrics_irradiance_sh`),
|
|
794
|
-
which `
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
`
|
|
798
|
-
|
|
799
|
-
and
|
|
800
|
-
|
|
801
|
-
|
|
794
|
+
which `shader_volumetrics_build_irradiance` writes: every directional, point and spot light at a
|
|
795
|
+
point jittered through the froxel every frame, shadowed, stored as luma SH2 + constant chroma (Metro's L1 YCoCg, 6 coefficients
|
|
796
|
+
in two `rgba16float` volumes, since `rg16float` is not a storage format without
|
|
797
|
+
`texture-formats-tier1`). The volume rides the orchestrator to side channels as
|
|
798
|
+
`volumetrics_irradiance`. Resolution is the fog's froxel grid — 16 px tiles and 64 slices — so light
|
|
799
|
+
and shadow edges inside a particle are soft. idTech 8 builds the same volume (Sousa, SIGGRAPH 2025,
|
|
800
|
+
p.29); Ghost of Tsushima lights particles from its haze grid the same way. idTech 8 builds it in the
|
|
801
|
+
pass that lights its fog, and this one did too until 2026-10-09, dimming each light by the medium
|
|
802
|
+
on its way in. That tied particle lighting to the fog's whole chain (media, sun cascades, sky LUTs),
|
|
803
|
+
so the fog could not be skipped in a scene without volumes. It now has its own pass with no medium
|
|
804
|
+
in it: a lit particle is lit as the surfaces beside it are, which the deferred and forward paths
|
|
805
|
+
never dimmed either, and the fog is composited over both. Chosen over per-pixel forward shading (UE's most expensive mode, and a
|
|
802
806
|
flat card lit that way goes black from behind), per-vertex/per-particle lighting (the light
|
|
803
807
|
clusters are screen-space: a point off screen has no light list, the artefact that moved idTech 8
|
|
804
808
|
off it) and a per-particle lighting atlas (DOOM 2016, CoD IW: best-looking, but it needs a
|
|
@@ -814,7 +818,7 @@ a vertex need not be on screen, and one quad can span the frustum.
|
|
|
814
818
|
- **Indirect light is in the same volume**, whatever the renderer's `indirect_lighting_mode`. The
|
|
815
819
|
froxel GI stage (`volumetrics/gi/`) starts the volume with one concrete module per mode — IBL,
|
|
816
820
|
Brick4, LPV — each asking its source what radiance arrives at the froxel's centre, as RGB SH2,
|
|
817
|
-
and `
|
|
821
|
+
and `shader_volumetrics_build_irradiance` adds the lights to that. The particle knows no mode: a new
|
|
818
822
|
GI system is one more module. IBL's source is `GPULightCollection.environment_sh`, the
|
|
819
823
|
environment projected to radiance SH2 when it changes (`shader_project_environment_sh`); Brick4
|
|
820
824
|
interpolates its probes (SH3, truncated) with a zero normal, which weighs every probe of the
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* returns what it reflects and transmits (`chunk_particle_lighting_model`), from the froxel
|
|
5
5
|
* irradiance volume (`chunk_volumetrics_irradiance_sh`) at the fragment: the renderer's indirect
|
|
6
6
|
* lighting, whichever mode it runs (the froxel GI stage, `volumetrics/gi/`), plus every directional,
|
|
7
|
-
* point and spot light, shadowed,
|
|
7
|
+
* point and spot light, shadowed, as the surfaces around the particle receive them. One trilinear read of each
|
|
8
8
|
* of its two textures, so the cost grows with neither the lights nor the GI; the price is resolution —
|
|
9
9
|
* a froxel is 16 pixels across and a slice deep, and light and shadow edges inside a particle are that
|
|
10
10
|
* soft.
|
|
@@ -10,7 +10,7 @@ import { chunk_particle_lighting_model } from "./chunk_particle_lighting_model.j
|
|
|
10
10
|
* returns what it reflects and transmits (`chunk_particle_lighting_model`), from the froxel
|
|
11
11
|
* irradiance volume (`chunk_volumetrics_irradiance_sh`) at the fragment: the renderer's indirect
|
|
12
12
|
* lighting, whichever mode it runs (the froxel GI stage, `volumetrics/gi/`), plus every directional,
|
|
13
|
-
* point and spot light, shadowed,
|
|
13
|
+
* point and spot light, shadowed, as the surfaces around the particle receive them. One trilinear read of each
|
|
14
14
|
* of its two textures, so the cost grows with neither the lights nor the GI; the price is resolution —
|
|
15
15
|
* a froxel is 16 pixels across and a slice deep, and light and shadow edges inside a particle are that
|
|
16
16
|
* soft.
|
|
@@ -53,7 +53,7 @@ export class NSS {
|
|
|
53
53
|
* @returns {number}
|
|
54
54
|
*/
|
|
55
55
|
static recommended_jitter_sequence_size(upscale_ratio: number): number;
|
|
56
|
-
static "__#
|
|
56
|
+
static "__#193@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
|
|
57
57
|
/**
|
|
58
58
|
* @param {GraphicsContext} graphics
|
|
59
59
|
*/
|
|
@@ -99,8 +99,9 @@ export type AVBOITSideChannel = {
|
|
|
99
99
|
* nothing into the volume passes `0`.
|
|
100
100
|
* `volumetrics_irradiance` is what a fragment standing in a froxel is lit by
|
|
101
101
|
* (`chunk_volumetrics_irradiance_sh`), for a channel whose fragments are lit: the renderer's
|
|
102
|
-
* indirect lighting, whichever mode it runs, and the scene's lights, shadowed
|
|
103
|
-
*
|
|
102
|
+
* indirect lighting, whichever mode it runs, and the scene's lights, shadowed — lit as the
|
|
103
|
+
* surfaces around it are, with no fog on the way in. Its own pass builds it, whether or not the
|
|
104
|
+
* scene has fog.
|
|
104
105
|
*/
|
|
105
106
|
avboit_draw: (args: {
|
|
106
107
|
graph: import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AVBOITSideChannel.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAoCc,CAAC,IAAI,EAAE;QAAC,KAAK,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QACjH,QAAc,EAAE,OAAO,iCAAiC,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QACzF,aAAmB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAC3E,WAAiB,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAC;QACvD,wBAA8B,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QACjG,eAAqB,EAAE,MAAM,CAAC;QAC9B,sBAA4B,EAAE,OAAO,uCAAuC,EAAE,yBAAyB,CAAC;KACrG,KAAK;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAC;;;;;sBAKtB,CAAC,IAAI,EAAE;QACpB,KAAW,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QAClG,MAAY,EAAE,MAAM,CAAC;QACrB,kBAAwB,EAAE,UAAU,MAAM,CAAC,CAAC;QAC5C,SAAe,EAAE,MAAM,CAAC;KACrB,KAAK,MAAM;;;;;;;;kBAED,CAAC,IAAI,EAAE;QACpB,KAAW,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QAClG,MAAY,EAAE,MAAM,CAAC;QACrB,IAAU,EAAE,MAAM,CAAC;QACnB,aAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAsB,EAAE,MAAM,EAAE,CAAC;QACjC,MAAY,EAAE;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAC,CAAC;KACjE,KAAK;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC
|
|
1
|
+
{"version":3,"file":"AVBOITSideChannel.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAoCc,CAAC,IAAI,EAAE;QAAC,KAAK,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QACjH,QAAc,EAAE,OAAO,iCAAiC,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QACzF,aAAmB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAC3E,WAAiB,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAC;QACvD,wBAA8B,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QACjG,eAAqB,EAAE,MAAM,CAAC;QAC9B,sBAA4B,EAAE,OAAO,uCAAuC,EAAE,yBAAyB,CAAC;KACrG,KAAK;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAC;;;;;sBAKtB,CAAC,IAAI,EAAE;QACpB,KAAW,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QAClG,MAAY,EAAE,MAAM,CAAC;QACrB,kBAAwB,EAAE,UAAU,MAAM,CAAC,CAAC;QAC5C,SAAe,EAAE,MAAM,CAAC;KACrB,KAAK,MAAM;;;;;;;;kBAED,CAAC,IAAI,EAAE;QACpB,KAAW,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QAClG,MAAY,EAAE,MAAM,CAAC;QACrB,IAAU,EAAE,MAAM,CAAC;QACnB,aAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAsB,EAAE,MAAM,EAAE,CAAC;QACjC,MAAY,EAAE;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAC,CAAC;KACjE,KAAK;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;;;;;;;;;;;;;;iBAKhD,CAAC,IAAI,EAAE;QACpB,KAAW,EAAE,OAAO,iEAAiE,EAAE,UAAU,CAAC;QAClG,QAAc,EAAE,OAAO,iCAAiC,EAAE,cAAc,CAAC;QACzE,MAAY,EAAE,MAAM,CAAC;QACrB,aAAmB,EAAE,MAAM,CAAC;QAC5B,IAAU,EAAE,MAAM,CAAC;QACnB,QAAc,EAAE,MAAM,CAAC;QACvB,eAAqB,EAAE,MAAM,CAAC;QAC9B,oBAA0B,EAAE,MAAM,CAAC;QACnC,sBAA4B,EAAE;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAC,CAAC;QACxD,YAAkB,EAAE;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAC,CAAC;KACrF,KAAK;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;;;;;;sBAW9D,CAAC,IAAI,EAAE,OAAO,iCAAiC,EAAE,cAAc,KAAK,OAAO"}
|
|
@@ -84,8 +84,9 @@
|
|
|
84
84
|
* nothing into the volume passes `0`.
|
|
85
85
|
* `volumetrics_irradiance` is what a fragment standing in a froxel is lit by
|
|
86
86
|
* (`chunk_volumetrics_irradiance_sh`), for a channel whose fragments are lit: the renderer's
|
|
87
|
-
* indirect lighting, whichever mode it runs, and the scene's lights, shadowed
|
|
88
|
-
*
|
|
87
|
+
* indirect lighting, whichever mode it runs, and the scene's lights, shadowed — lit as the
|
|
88
|
+
* surfaces around it are, with no fog on the way in. Its own pass builds it, whether or not the
|
|
89
|
+
* scene has fog.
|
|
89
90
|
* @property {(view: import("../../../view/GPUViewContext.js").GPUViewContext) => boolean} [avboit_is_empty] whether the channel would add nothing for this view;
|
|
90
91
|
* asked before the orchestrator records, and a channel that answers `true` is not asked for
|
|
91
92
|
* anything else in that frame.
|
|
@@ -38,6 +38,13 @@ export class GPUSceneContext {
|
|
|
38
38
|
*/
|
|
39
39
|
get scene(): Scene;
|
|
40
40
|
get volumetrics(): GPUSceneVolumetrics;
|
|
41
|
+
/**
|
|
42
|
+
* Not necessarily current: a reader calls {@link GPUSky#update} first, which does the work the
|
|
43
|
+
* first time and nothing after.
|
|
44
|
+
*
|
|
45
|
+
* @returns {GPUSky}
|
|
46
|
+
*/
|
|
47
|
+
get sky(): GPUSky;
|
|
41
48
|
/**
|
|
42
49
|
*
|
|
43
50
|
* @returns {GPULightCollection}
|
|
@@ -186,7 +193,7 @@ export class GPUSceneContext {
|
|
|
186
193
|
* Release this context's virtual geometry — everything {@link enable_virtual_geometry} built,
|
|
187
194
|
* so that a host tears a scene down by destroying the renderer and nothing of the streaming loop
|
|
188
195
|
* is left for it to find — then its rows, its database, its TLAS, its lights, its probe volume,
|
|
189
|
-
* its volumetrics, its volumetric light map, its animation and its skinning: every buffer the
|
|
196
|
+
* its volumetrics, its sky, its volumetric light map, its animation and its skinning: every buffer the
|
|
190
197
|
* context made. Safe to call twice, and on a context that never enabled virtual geometry.
|
|
191
198
|
*/
|
|
192
199
|
destroy(): void;
|
|
@@ -205,6 +212,7 @@ export type GPURecordWriter = import("../buffer/table/serde/generate_record_writ
|
|
|
205
212
|
import { Brick4LightMap } from "../global_illumination/brick4/Brick4LightMap.js";
|
|
206
213
|
import { Scene } from "./Scene.js";
|
|
207
214
|
import { GPUSceneVolumetrics } from "../volumetrics/GPUSceneVolumetrics.js";
|
|
215
|
+
import { GPUSky } from "../atmosphere/GPUSky.js";
|
|
208
216
|
import { GPULightCollection } from "../light/GPULightCollection.js";
|
|
209
217
|
import { GPULightProbeVolume } from "../global_illumination/lpv/GPULightProbeVolume.js";
|
|
210
218
|
import { GPUInstancesAccelerationStructure } from "./GPUInstancesAccelerationStructure.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GPUSceneContext.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/scene/GPUSceneContext.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GPUSceneContext.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/scene/GPUSceneContext.js"],"names":[],"mappings":"AAsEA;;;;;;;;;GASG;AACH;IA4JI;;;;OAIG;IACH,sBAHW,eAAe,SACf,KAAK,EAsCf;IAnMD;;;OAGG;IACH,aAFU,MAAM,CAEE;IAElB;;OAEG;IACH,YAFU,kBAAkB,CAEjB;IAEX;;OAEG;IACH,WAFU,kBAAkB,CAElB;IAGV;;OAEG;IACH,sBAFU,cAAc,CAEH;IASrB;;;OAGG;IACH,mBAEC;IAOD,uCAEC;IAUD;;;;;OAKG;IACH,kBAEC;IAQD;;;OAGG;IACH,iCAEC;IAOD;;;OAGG;IACH,8CAEC;IAOD;;;OAGG;IACH,8CAEC;IAgID;;OAEG;IACH,kDAEC;IAED;;OAEG;IACH,gDAEC;IAED;;OAEG;IACH,kDAEC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH;QAH0C,SAAS,GAAxC,oBAAoB;QAClB,yBAAyB,CAuDrC;IAED;;OAEG;IACH,6CAEC;IAYD;;;OAGG;IACH,kCAEC;IAED;;;;;OAKG;IACH,uCAEC;IAED;;;;;;;;;;;OAWG;IACH,uCAUC;IAED,+BAUC;IAED;;;;;;;;;;OAUG;IACH,yBAEC;IAED;;;;;OAKG;IACH,sCAMC;IAOD;;;;;;;OAOG;IACH,8EAEC;IA0BD;;;;;OAKG;IACH,cAsEC;IAED;;;OAGG;IACH,YAFW,eAAe,QA0BzB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,cAHW,sBAAsB,cACtB,MAAM,QAuBhB;IAoCD;;;;;;OAMG;IACH,gBAkBC;IAoCL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;;CAN1C;8BA9vBY,OAAO,uBAAuB,EAAE,eAAe;iCAC/C,OAAO,mCAAmC,EAAE,kBAAkB;iCAC9D,OAAO,mCAAmC,EAAE,kBAAkB;4BAC9D,OAAO,8BAA8B,EAAE,aAAa;8BACpD,OAAO,iDAAiD,EAAE,eAAe;+BAvBvD,iDAAiD;sBAK1D,YAAY;oCADE,uCAAuC;uBAFpD,yBAAyB;mCACb,gCAAgC;oCAF/B,mDAAmD;kDAKrC,wCAAwC;0CAhBhD,0DAA0D;8BAItE,8CAA8C;iCAF3C,iDAAiD;qCAG7C,qDAAqD;oCAGtD,qCAAqC;4BAC7C,gCAAgC;uCAQrB,iDAAiD;6BAM3D,wBAAwB;wCADb,mCAAmC;uCAfpC,wCAAwC"}
|
|
@@ -11,6 +11,7 @@ import { GPUAnimationManager } from "../animation/GPUAnimationManager.js";
|
|
|
11
11
|
import { GPUDatabase } from "../buffer/table/GPUDatabase.js";
|
|
12
12
|
import { Brick4LightMap } from "../global_illumination/brick4/Brick4LightMap.js";
|
|
13
13
|
import { GPULightProbeVolume } from "../global_illumination/lpv/GPULightProbeVolume.js";
|
|
14
|
+
import { GPUSky } from "../atmosphere/GPUSky.js";
|
|
14
15
|
import { GPULightCollection } from "../light/GPULightCollection.js";
|
|
15
16
|
import { GPUSceneVolumetrics } from "../volumetrics/GPUSceneVolumetrics.js";
|
|
16
17
|
import { Scene } from "./Scene.js";
|
|
@@ -125,6 +126,24 @@ export class GPUSceneContext {
|
|
|
125
126
|
return this.#volumetrics;
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
/**
|
|
130
|
+
* The atmosphere's LUTs, built once for the scene and read by every view that needs them. They
|
|
131
|
+
* depend on the atmosphere's constants alone, so no view owns a copy.
|
|
132
|
+
*
|
|
133
|
+
* @type {GPUSky}
|
|
134
|
+
*/
|
|
135
|
+
#sky;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Not necessarily current: a reader calls {@link GPUSky#update} first, which does the work the
|
|
139
|
+
* first time and nothing after.
|
|
140
|
+
*
|
|
141
|
+
* @returns {GPUSky}
|
|
142
|
+
*/
|
|
143
|
+
get sky() {
|
|
144
|
+
return this.#sky;
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
/**
|
|
129
148
|
* @type {GPULightCollection}
|
|
130
149
|
*/
|
|
@@ -253,6 +272,8 @@ export class GPUSceneContext {
|
|
|
253
272
|
scene.volumetrics
|
|
254
273
|
);
|
|
255
274
|
|
|
275
|
+
this.#sky = new GPUSky(graphics);
|
|
276
|
+
|
|
256
277
|
this.#animation_manager = new GPUAnimationManager(device, `GPUSceneContext[${this.id}]/Animation`, this);
|
|
257
278
|
}
|
|
258
279
|
|
|
@@ -718,7 +739,7 @@ export class GPUSceneContext {
|
|
|
718
739
|
* Release this context's virtual geometry — everything {@link enable_virtual_geometry} built,
|
|
719
740
|
* so that a host tears a scene down by destroying the renderer and nothing of the streaming loop
|
|
720
741
|
* is left for it to find — then its rows, its database, its TLAS, its lights, its probe volume,
|
|
721
|
-
* its volumetrics, its volumetric light map, its animation and its skinning: every buffer the
|
|
742
|
+
* its volumetrics, its sky, its volumetric light map, its animation and its skinning: every buffer the
|
|
722
743
|
* context made. Safe to call twice, and on a context that never enabled virtual geometry.
|
|
723
744
|
*/
|
|
724
745
|
destroy() {
|
|
@@ -733,6 +754,7 @@ export class GPUSceneContext {
|
|
|
733
754
|
this.#lights.destroy();
|
|
734
755
|
this.#light_probe_volume.destroy();
|
|
735
756
|
this.#volumetrics.destroy();
|
|
757
|
+
this.#sky.destroy();
|
|
736
758
|
this.volumetric_light_map.destroy();
|
|
737
759
|
this.#animation_manager.destroy();
|
|
738
760
|
if (this.#skinning !== null) {
|
|
@@ -34,7 +34,10 @@ export class GPUViewVolumetrics {
|
|
|
34
34
|
* module that starts the froxel irradiance volume
|
|
35
35
|
* @returns {{resolved: number, metadata: number, irradiance: {Y: number, CoCg: number}}} the
|
|
36
36
|
* integrated aerial LUT, the metadata buffer, and the froxel irradiance volume
|
|
37
|
-
* (chunk_volumetrics_irradiance_sh)
|
|
37
|
+
* (chunk_volumetrics_irradiance_sh) that lit particles are lit by. The two do not depend on
|
|
38
|
+
* each other, and a pass building only one of them is culled when nothing reads it. A scene
|
|
39
|
+
* with no participating-media volume records no fog at all, and `resolved` is then a constant:
|
|
40
|
+
* no in-scatter, full transmittance.
|
|
38
41
|
*/
|
|
39
42
|
graph_update({ graph, light_cluster_data, light_cluster_lookup, light_cluster_parameters, shadowmap_atlas, indirect_lighting_mode, }: {
|
|
40
43
|
graph: FrameGraph;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GPUViewVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/GPUViewVolumetrics.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GPUViewVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/GPUViewVolumetrics.js"],"names":[],"mappings":"AAkCA;IA2II;;;;OAIG;IACH,kBAHW,cAAc,qBAyCxB;IAlJD;;OAEG;IACH,4BAOC;IAjBD;;OAEG;IACH,2BAEC;IAsCD;;OAEG;IACH,0BAEC;IAZD;;OAEG;IACH,yBAEC;IAkHD,gBAaC;IA6ND;;;;;;;;;;;;;;;;OAgBG;IACH;QAd+B,KAAK,EAAzB,UAAU;QACM,kBAAkB,EAAlC,MAAM;QACU,oBAAoB,EAApC,MAAM;QACU,wBAAwB,EAAxC,MAAM;QACU,eAAe,EAA/B,MAAM;QACuE,sBAAsB,EAAnG,OAAO,iCAAiC,EAAE,yBAAyB;QAEjE;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC,CAmIvF;;CAEJ;yBA1jBY,OAAO,2DAA2D,EAAE,UAAU;6BAC9E,OAAO,2BAA2B,EAAE,cAAc"}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
build_volumetrics_sun_shadow_transform,
|
|
11
11
|
volumetrics_sun_shadow_cascade_far
|
|
12
12
|
} from "./build_volumetrics_sun_shadow_transform.js";
|
|
13
|
+
import { graph_build_froxel_irradiance } from "./graph_build_froxel_irradiance.js";
|
|
13
14
|
import { graph_build_volumetrics } from "./graph_build_volumetrics.js";
|
|
14
15
|
import {
|
|
15
16
|
VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT,
|
|
@@ -151,6 +152,15 @@ export class GPUViewVolumetrics {
|
|
|
151
152
|
*/
|
|
152
153
|
#sun_shadow_cascade_far = new Float32Array(4);
|
|
153
154
|
|
|
155
|
+
/**
|
|
156
|
+
* What the fog integrates to through no medium: nothing in-scattered (.rgb 0), everything
|
|
157
|
+
* transmitted (.a 1). Handed out in place of the aerial LUT on a frame whose scene has no
|
|
158
|
+
* participating-media volume, so every surface that samples the fog keeps doing so and reads
|
|
159
|
+
* it as none, for one texel and no pass. Written once, at construction.
|
|
160
|
+
* @type {GPUTextureContext}
|
|
161
|
+
*/
|
|
162
|
+
#no_medium;
|
|
163
|
+
|
|
154
164
|
/**
|
|
155
165
|
* @type {GPUTypedBuffer}
|
|
156
166
|
*/
|
|
@@ -181,6 +191,23 @@ export class GPUViewVolumetrics {
|
|
|
181
191
|
this.#volumetrics_textures[i] = texture;
|
|
182
192
|
}
|
|
183
193
|
|
|
194
|
+
const no_medium = new GPUTextureContext(device);
|
|
195
|
+
no_medium.descriptor.label = "volumetrics/no medium";
|
|
196
|
+
no_medium.descriptor.format = "rgba16float";
|
|
197
|
+
no_medium.descriptor.dimension = "3d";
|
|
198
|
+
no_medium.descriptor.size = [1, 1, 1];
|
|
199
|
+
no_medium.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
|
|
200
|
+
|
|
201
|
+
device.queue.writeTexture(
|
|
202
|
+
{ texture: no_medium.gpu_texture },
|
|
203
|
+
new Float16Array([0, 0, 0, 1]),
|
|
204
|
+
{ bytesPerRow: 8, rowsPerImage: 1 },
|
|
205
|
+
[1, 1, 1]
|
|
206
|
+
);
|
|
207
|
+
no_medium.incrementVersion();
|
|
208
|
+
|
|
209
|
+
this.#no_medium = no_medium;
|
|
210
|
+
|
|
184
211
|
this.#metadata = GPUTypedBuffer.create({
|
|
185
212
|
type: VOLUMETRICS_METADATA_STRUCT,
|
|
186
213
|
device,
|
|
@@ -200,6 +227,8 @@ export class GPUViewVolumetrics {
|
|
|
200
227
|
textures[i] = null;
|
|
201
228
|
}
|
|
202
229
|
|
|
230
|
+
this.#no_medium.destroy();
|
|
231
|
+
|
|
203
232
|
}
|
|
204
233
|
|
|
205
234
|
#update_resolution() {
|
|
@@ -433,7 +462,10 @@ export class GPUViewVolumetrics {
|
|
|
433
462
|
* module that starts the froxel irradiance volume
|
|
434
463
|
* @returns {{resolved: number, metadata: number, irradiance: {Y: number, CoCg: number}}} the
|
|
435
464
|
* integrated aerial LUT, the metadata buffer, and the froxel irradiance volume
|
|
436
|
-
* (chunk_volumetrics_irradiance_sh)
|
|
465
|
+
* (chunk_volumetrics_irradiance_sh) that lit particles are lit by. The two do not depend on
|
|
466
|
+
* each other, and a pass building only one of them is culled when nothing reads it. A scene
|
|
467
|
+
* with no participating-media volume records no fog at all, and `resolved` is then a constant:
|
|
468
|
+
* no in-scatter, full transmittance.
|
|
437
469
|
*/
|
|
438
470
|
graph_update({
|
|
439
471
|
graph,
|
|
@@ -479,6 +511,35 @@ export class GPUViewVolumetrics {
|
|
|
479
511
|
|
|
480
512
|
const resolution = this.#volumetrics_textures[0].size;
|
|
481
513
|
|
|
514
|
+
// Particle lighting first, and on its own: it reads no medium. The frame graph culls it when
|
|
515
|
+
// nothing reads it.
|
|
516
|
+
const irradiance = graph_build_froxel_irradiance({
|
|
517
|
+
graph,
|
|
518
|
+
camera,
|
|
519
|
+
view,
|
|
520
|
+
lights,
|
|
521
|
+
light_cluster_data,
|
|
522
|
+
light_cluster_lookup,
|
|
523
|
+
light_cluster_parameters,
|
|
524
|
+
shadowmap_atlas,
|
|
525
|
+
volumetrics_metadata: gr_metadata,
|
|
526
|
+
resolution,
|
|
527
|
+
indirect_lighting_mode,
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
if (view.scene.volumetrics.source.volumes.length === 0) {
|
|
531
|
+
// No medium: nothing scatters and nothing absorbs, so the fog is the identity everywhere
|
|
532
|
+
// and the passes that would integrate it to that are not recorded. Nothing accumulates
|
|
533
|
+
// either, which leaves the history stale for whenever a volume arrives.
|
|
534
|
+
this.#reset_history = true;
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
resolved: graph_import_texture(graph, this.#no_medium, "volumetrics no medium"),
|
|
538
|
+
metadata: gr_metadata,
|
|
539
|
+
irradiance,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
482
543
|
// Ping-pong the two persistent froxel textures: this frame writes [parity] and reads the
|
|
483
544
|
// previous frame's accumulation from [parity ^ 1]. On the first frame / after a resize the
|
|
484
545
|
// history is invalid, which #update_metadata signals via history_reset (the TAA then emits
|
|
@@ -493,16 +554,26 @@ export class GPUViewVolumetrics {
|
|
|
493
554
|
taa_output = graph_import_texture(graph, this.#volumetrics_textures[parity], "volumetrics taa output");
|
|
494
555
|
}
|
|
495
556
|
|
|
496
|
-
|
|
557
|
+
/*
|
|
558
|
+
The sun's transmittance and the multiple scattering are the scene sky's, built once and
|
|
559
|
+
read from here on. Brought current now rather than in a pass: the sky submits commands of
|
|
560
|
+
its own, which land ahead of this frame's -- recorded into the frame graph they would be
|
|
561
|
+
paid every frame, which is what they used to be. A no-op after the first call.
|
|
562
|
+
*/
|
|
563
|
+
const sky = view.scene.sky;
|
|
564
|
+
|
|
565
|
+
sky.update();
|
|
566
|
+
|
|
567
|
+
const { lut_aerial } = graph_build_volumetrics({
|
|
497
568
|
graph,
|
|
498
569
|
camera,
|
|
499
570
|
lights,
|
|
500
571
|
view,
|
|
572
|
+
sky,
|
|
501
573
|
light_cluster_data,
|
|
502
574
|
light_cluster_lookup,
|
|
503
575
|
light_cluster_parameters,
|
|
504
576
|
shadowmap_atlas,
|
|
505
|
-
indirect_lighting_mode,
|
|
506
577
|
|
|
507
578
|
volumetrics_metadata: gr_metadata,
|
|
508
579
|
volumetric_resolution: resolution,
|