@woosh/meep-engine 3.34.0 → 3.35.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.
Files changed (90) hide show
  1. package/package.json +1 -1
  2. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +25 -11
  3. package/src/shade/device/timing/profile/GPUProfileSession.d.ts.map +1 -1
  4. package/src/shade/device/timing/profile/GPUProfileSession.js +553 -474
  5. package/src/shade/playground/avboit/main.d.ts.map +1 -1
  6. package/src/shade/playground/avboit/main.js +888 -916
  7. package/src/shade/playground/particle_ecs/README.md +13 -7
  8. package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +5 -5
  9. package/src/shade/playground/particle_ecs/bonfire_effects.js +5 -5
  10. package/src/shade/playground/particle_ecs/effects/smoke.json +1859 -1859
  11. package/src/shade/playground/particle_ecs/effects/soot.json +1605 -1605
  12. package/src/shade/playground/particle_system/README.md +1 -2
  13. package/src/shade/playground/profile_hotkey.d.ts.map +1 -1
  14. package/src/shade/playground/profile_hotkey.js +4 -40
  15. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  16. package/src/shade/playground/skinned_blas_refit/main.js +4 -39
  17. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
  18. package/src/shade/playground/volumetrics_froxel/main.js +4 -39
  19. package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
  20. package/src/shade/playground/volumetrics_froxel/measure.js +2 -4
  21. package/src/shade/renderer/Renderer.d.ts +1 -1
  22. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  23. package/src/shade/renderer/Renderer.js +3 -1
  24. package/src/shade/renderer/light/GPULightCollection.d.ts +9 -1
  25. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  26. package/src/shade/renderer/light/GPULightCollection.js +41 -0
  27. package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts +37 -0
  28. package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts.map +1 -0
  29. package/src/shade/renderer/light/environment/shader_project_environment_sh.js +105 -0
  30. package/src/shade/renderer/particles/DESIGN.md +65 -8
  31. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +7 -1
  32. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  33. package/src/shade/renderer/particles/GPUParticleSystem.js +1247 -1244
  34. package/src/shade/renderer/particles/graph_particles_avboit.d.ts +7 -1
  35. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  36. package/src/shade/renderer/particles/graph_particles_avboit.js +9 -0
  37. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
  38. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +4 -2
  39. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +15 -9
  40. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
  41. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +29 -11
  42. package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.d.ts +24 -0
  43. package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.d.ts.map +1 -0
  44. package/src/shade/renderer/particles/shaders/chunk_particle_lighting_model.js +45 -0
  45. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +3 -0
  46. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
  47. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +38 -0
  48. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  49. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +190 -185
  50. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +8 -0
  51. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  52. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +5 -0
  53. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +8 -1
  54. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  55. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +9 -0
  56. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +13 -3
  57. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  58. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +9 -1
  59. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts +39 -0
  60. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts.map +1 -0
  61. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js +107 -0
  62. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.d.ts +15 -0
  63. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.d.ts.map +1 -0
  64. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.js +44 -0
  65. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts +19 -0
  66. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts.map +1 -0
  67. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +48 -0
  68. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts +29 -0
  69. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts.map +1 -0
  70. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +90 -0
  71. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.d.ts +10 -0
  72. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.d.ts.map +1 -0
  73. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_brick4.js +55 -0
  74. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.d.ts +10 -0
  75. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.d.ts.map +1 -0
  76. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_ibl.js +47 -0
  77. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.d.ts +10 -0
  78. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.d.ts.map +1 -0
  79. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi_lpv.js +63 -0
  80. package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.d.ts +17 -0
  81. package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.d.ts.map +1 -0
  82. package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.js +26 -0
  83. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +8 -1
  84. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  85. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +50 -2
  86. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  87. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +488 -436
  88. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +1 -1
  89. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  90. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +254 -63
@@ -1,185 +1,190 @@
1
- import { RenderPipelineDescriptor } from "../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
2
- import { DepthStencilState } from "../../../descriptor/pipeline/render/DepthStencilState.js";
3
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
- import { CAMERA_UNIFORM_STRUCT } from "../../camera/CAMERA_UNIFORM_STRUCT.js";
5
- import { chunk_sample_volumetrics } from "../../deferred/chunk_sample_volumetrics.js";
6
- import { AVBOIT_EXTINCT_TRANSMITTANCE } from "../../rasterize/native/avboit/AVBOIT_CONSTANTS.js";
7
- import { AVBOIT_WARP_STRUCT } from "../../rasterize/native/avboit/AVBOIT_WARP_STRUCT.js";
8
- import { AVBOIT_DRAW_TARGETS } from "../../rasterize/native/avboit/avboit_draw_fragment_body.js";
9
- import { chunk_avboit_sample_transmittance } from "../../rasterize/native/avboit/chunk_avboit_sample_transmittance.js";
10
- import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
11
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
12
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
13
- import { SAMPLER_LINEAR_UPSCALE } from "../../texture/SAMPLER_LINEAR_UPSCALE.js";
14
- import { VIEW_UNIFORM_STRUCT } from "../../view/VIEW_UNIFORM_STRUCT.js";
15
- import { VOLUMETRICS_METADATA_STRUCT } from "../../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
16
- import { EMITTER_FLAG } from "../data/PARTICLE_EMITTER_STRUCT.js";
17
- import { PARTICLE_SOFT_FADE_RANGE } from "../ParticleConstants.js";
18
- import { chunk_particle_avboit_contribution } from "./chunk_particle_avboit_contribution.js";
19
- import { chunk_particle_scene_view_depth } from "./chunk_particle_scene_view_depth.js";
20
- import { chunk_particle_billboard_vertex } from "./chunk_particle_billboard_vertex.js";
21
- import { chunk_particle_lighting_unlit } from "./chunk_particle_lighting.js";
22
-
23
- /**
24
- * The particles' AVBOIT draw: the billboard quads at internal resolution, depth-tested against the
25
- * opaque scene, into the four accumulators the transparent meshes draw into
26
- * (`avboit_draw_fragment_body`). The particle counterpart of `shader_avboit_draw_ibl`.
27
- *
28
- * Per fragment: the atlas sample times the particle colour, the soft-depth fade against the scene
29
- * depth and the lighting hook, the volumetric fog composite exactly as the mesh draw applies it,
30
- * then the transmittance of everything in front from the integral texture — and a fragment the
31
- * volume already calls extinct is discarded unshaded.
32
- *
33
- * What is written depends on how the particle blends:
34
- *
35
- * - **alpha / premultiplied** — a surface: `color += premultiplied × T`, `norm += coverage × T`,
36
- * `extinction += -log(1 - coverage)`, the same three the meshes write, with an untinted
37
- * `T_self = 1 - coverage`; the splat recorded exactly that.
38
- * - **additive** — light: `emission += premultiplied × T`, nothing else. It joins the resolve
39
- * attenuated by what is in front of it and outside the coverage normalization, which is what an
40
- * additive fragment means.
41
- *
42
- * The scene depth is bound twice: as the read-only depth attachment the pipeline tests against, and
43
- * as the texture the soft fade reads. Both are reads, which WebGPU allows within one pass; the pass
44
- * is recorded with the attachment read-only for that reason.
45
- */
46
-
47
- const resources = new ShaderResourceSetDescriptor();
48
-
49
- resources.createGroup()
50
- .addUniform("camera", CAMERA_UNIFORM_STRUCT)
51
- .addUniform("view", VIEW_UNIFORM_STRUCT)
52
- .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
53
- .addStorageBuffer("pool", WebGPUArray.u32, false)
54
- .addStorageBuffer("draw_list", WebGPUArray.u32, false)
55
- .addStorageBuffer("emitter_database", WebGPUArray.u32, false)
56
- .addTexture("atlas", "float")
57
- .addSampler("atlas_sampler", "filtering")
58
- .addTexture("scene_depth", "unfilterable-float")
59
- // sampled through sLinear: linear, clamped on every axis, which is what the integral needs
60
- .addTexture("tIntegral", "float", "3d")
61
- .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
62
- // volumetrics (composited inline)
63
- .addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
64
- .addTexture("tVolumetrics", "float", "3d")
65
- .addTexture("tSTBN_vec3", "float", "3d");
66
-
67
- const body = CodeChunk.from(
68
- /* language=wgsl */ `
69
- const PARTICLE_FLAG_SOFT_DEPTH : u32 = ${EMITTER_FLAG.SOFT_DEPTH}u;
70
- const PARTICLE_FLAG_LIGHTING : u32 = ${EMITTER_FLAG.LIGHTING}u;
71
- const PARTICLE_SOFT_FADE_RANGE : f32 = ${PARTICLE_SOFT_FADE_RANGE};
72
-
73
- struct ParticleAVBOITDrawOutput {
74
- @location(0) color : vec4<f32>,
75
- @location(1) norm : vec4<f32>,
76
- @location(2) extinction : vec4<f32>,
77
- @location(3) emission : vec4<f32>,
78
- }
79
-
80
- // Each draw uses the same GPU-owned alive list. Clip the other modes before rasterization.
81
- fn particle_avboit_vertex(vi : u32, ii : u32, blend : u32) -> ParticleVertexOut {
82
- var out = particle_billboard_vertex(vi, ii);
83
- if (particle_avboit_draw_blend(out.color, out.blend) != blend) {
84
- out.clip = vec4<f32>(2.0, 2.0, 2.0, 1.0);
85
- }
86
- return out;
87
- }
88
-
89
- @vertex
90
- fn vs_alpha(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
91
- return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ALPHA);
92
- }
93
-
94
- @vertex
95
- fn vs_additive(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
96
- return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ADDITIVE);
97
- }
98
-
99
- @vertex
100
- fn vs_general(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
101
- return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_PREMULTIPLIED);
102
- }
103
-
104
- @fragment
105
- fn fs_main(in : ParticleVertexOut) -> ParticleAVBOITDrawOutput {
106
- let screen_uv = in.clip.xy / vec2<f32>(f32(view.width), f32(view.height));
107
-
108
- let transmittance = avboit_sample_transmittance(&warp, tIntegral, sLinear, screen_uv, in.view_depth);
109
-
110
- if (all(transmittance <= vec3<f32>(${AVBOIT_EXTINCT_TRANSMITTANCE}))) {
111
- // nothing this fragment contributes survives what is in front of it; skip the shading
112
- discard;
113
- }
114
-
115
- var color = textureSample(atlas, atlas_sampler, in.uv) * in.color;
116
-
117
- if ((in.flags & PARTICLE_FLAG_SOFT_DEPTH) != 0u) {
118
- let scene_vd = particle_scene_view_depth(textureLoad(scene_depth, vec2<i32>(in.clip.xy), 0).r, camera);
119
- color = particle_fade_color(color, in.blend, particle_soft_fade(scene_vd, in.view_depth, PARTICLE_SOFT_FADE_RANGE));
120
- }
121
-
122
- if ((in.flags & PARTICLE_FLAG_LIGHTING) != 0u) {
123
- color = particle_apply_lighting(color, in.world_position, normalize(in.normal));
124
- }
125
-
126
- if (particle_avboit_is_empty(color, in.blend)) {
127
- discard;
128
- }
129
-
130
- let volumetrics = sample_volumetrics(in.view_depth, screen_uv, in.clip.xy);
131
-
132
- let contribution = particle_avboit_contribution(color, in.blend, transmittance, volumetrics);
133
-
134
- var out : ParticleAVBOITDrawOutput;
135
-
136
- out.color = contribution.color;
137
- out.norm = contribution.norm;
138
- out.extinction = contribution.extinction;
139
- out.emission = contribution.emission;
140
-
141
- return out;
142
- }
143
- `, [
144
- chunk_particle_avboit_contribution,
145
- chunk_particle_scene_view_depth,
146
- chunk_particle_billboard_vertex,
147
- chunk_particle_lighting_unlit,
148
- chunk_sample_volumetrics,
149
- chunk_avboit_sample_transmittance,
150
- ]);
151
-
152
- const descriptor = ShaderDescriptor.from({ label: "Particle AVBOIT Draw", body, resources });
153
-
154
- /**
155
- * The variants share WGSL, bindings and attachments; only the vertex entry point and target writes
156
- * differ. Disabling unused targets avoids blending zeros over every billboard pixel.
157
- * @param {string} label
158
- * @param {string} entryPoint
159
- * @param {number[]} writeMasks
160
- * @returns {RenderPipelineDescriptor}
161
- */
162
- function create_draw_pipeline(label, entryPoint, writeMasks) {
163
- return RenderPipelineDescriptor.from({
164
- label,
165
- layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
166
- vertex: { module: { code: descriptor.source }, entryPoint },
167
- fragment: {
168
- module: { code: descriptor.source },
169
- entryPoint: "fs_main",
170
- targets: AVBOIT_DRAW_TARGETS.map((target, i) => ({ ...target, writeMask: writeMasks[i] })),
171
- },
172
- depthStencil: DepthStencilState.from({ format: "depth32float", depthWriteEnabled: false, depthCompare: "greater" }),
173
- primitive: { topology: "triangle-list", cullMode: "none" },
174
- });
175
- }
176
-
177
- export const PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Alpha", "vs_alpha", [0xF, 0xF, 0xF, 0]);
178
- export const PARTICLE_AVBOIT_DRAW_ADDITIVE_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Additive", "vs_additive", [0, 0, 0, 0xF]);
179
- export const PARTICLE_AVBOIT_DRAW_GENERAL_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw General", "vs_general", [0xF, 0xF, 0xF, 0xF]);
180
-
181
- /** The draw shader's resource set, for building its bind group. */
182
- export const PARTICLE_AVBOIT_DRAW_RESOURCES = resources;
183
-
184
- /** The assembled shader, for the validity tier. */
185
- export const shader_particle_avboit_draw = descriptor;
1
+ import { RenderPipelineDescriptor } from "../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
2
+ import { DepthStencilState } from "../../../descriptor/pipeline/render/DepthStencilState.js";
3
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
+ import { CAMERA_UNIFORM_STRUCT } from "../../camera/CAMERA_UNIFORM_STRUCT.js";
5
+ import { chunk_sample_volumetrics } from "../../deferred/chunk_sample_volumetrics.js";
6
+ import { AVBOIT_EXTINCT_TRANSMITTANCE } from "../../rasterize/native/avboit/AVBOIT_CONSTANTS.js";
7
+ import { AVBOIT_WARP_STRUCT } from "../../rasterize/native/avboit/AVBOIT_WARP_STRUCT.js";
8
+ import { AVBOIT_DRAW_TARGETS } from "../../rasterize/native/avboit/avboit_draw_fragment_body.js";
9
+ import { chunk_avboit_sample_transmittance } from "../../rasterize/native/avboit/chunk_avboit_sample_transmittance.js";
10
+ import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
11
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
12
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
13
+ import { SAMPLER_LINEAR_UPSCALE } from "../../texture/SAMPLER_LINEAR_UPSCALE.js";
14
+ import { VIEW_UNIFORM_STRUCT } from "../../view/VIEW_UNIFORM_STRUCT.js";
15
+ import { VOLUMETRICS_METADATA_STRUCT } from "../../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
16
+ import { EMITTER_FLAG } from "../data/PARTICLE_EMITTER_STRUCT.js";
17
+ import { PARTICLE_SOFT_FADE_RANGE } from "../ParticleConstants.js";
18
+ import { chunk_particle_avboit_contribution } from "./chunk_particle_avboit_contribution.js";
19
+ import { chunk_particle_scene_view_depth } from "./chunk_particle_scene_view_depth.js";
20
+ import { chunk_particle_billboard_vertex } from "./chunk_particle_billboard_vertex.js";
21
+ import { chunk_particle_lighting } from "./chunk_particle_lighting.js";
22
+
23
+ /**
24
+ * The particles' AVBOIT draw: the billboard quads at internal resolution, depth-tested against the
25
+ * opaque scene, into the four accumulators the transparent meshes draw into
26
+ * (`avboit_draw_fragment_body`). The particle counterpart of `shader_avboit_draw_ibl`.
27
+ *
28
+ * Per fragment: the atlas sample times the particle colour, the soft-depth fade against the scene
29
+ * depth, lighting for an emitter flagged `EMITTER_FLAG.LIGHTING` (`chunk_particle_lighting`: the
30
+ * froxel irradiance volume: the lights and the indirect lighting), the volumetric fog composite exactly as the
31
+ * mesh draw applies it, then the transmittance of everything in front from the integral texture —
32
+ * and a fragment the volume already calls extinct is discarded unshaded. An emitter without the
33
+ * flag is its own colour, which is what an additive one wants.
34
+ *
35
+ * What is written depends on how the particle blends:
36
+ *
37
+ * - **alpha / premultiplied** — a surface: `color += premultiplied × T`, `norm += coverage × T`,
38
+ * `extinction += -log(1 - coverage)`, the same three the meshes write, with an untinted
39
+ * `T_self = 1 - coverage`; the splat recorded exactly that.
40
+ * - **additive** — light: `emission += premultiplied × T`, nothing else. It joins the resolve
41
+ * attenuated by what is in front of it and outside the coverage normalization, which is what an
42
+ * additive fragment means.
43
+ *
44
+ * The scene depth is bound twice: as the read-only depth attachment the pipeline tests against, and
45
+ * as the texture the soft fade reads. Both are reads, which WebGPU allows within one pass; the pass
46
+ * is recorded with the attachment read-only for that reason.
47
+ */
48
+
49
+ const resources = new ShaderResourceSetDescriptor();
50
+
51
+ resources.createGroup()
52
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
53
+ .addUniform("view", VIEW_UNIFORM_STRUCT)
54
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
55
+ .addStorageBuffer("pool", WebGPUArray.u32, false)
56
+ .addStorageBuffer("draw_list", WebGPUArray.u32, false)
57
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, false)
58
+ .addTexture("atlas", "float")
59
+ .addSampler("atlas_sampler", "filtering")
60
+ .addTexture("scene_depth", "unfilterable-float")
61
+ // sampled through sLinear: linear, clamped on every axis, which is what the integral needs
62
+ .addTexture("tIntegral", "float", "3d")
63
+ .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
64
+ // volumetrics (composited inline)
65
+ .addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
66
+ .addTexture("tVolumetrics", "float", "3d")
67
+ .addTexture("tSTBN_vec3", "float", "3d")
68
+ // lighting (chunk_particle_lighting): the froxel irradiance volume, trilinear through sLinear
69
+ .addTexture("tIrradianceY", "float", "3d")
70
+ .addTexture("tIrradianceCoCg", "float", "3d");
71
+
72
+ const body = CodeChunk.from(
73
+ /* language=wgsl */ `
74
+ const PARTICLE_FLAG_SOFT_DEPTH : u32 = ${EMITTER_FLAG.SOFT_DEPTH}u;
75
+ const PARTICLE_FLAG_LIGHTING : u32 = ${EMITTER_FLAG.LIGHTING}u;
76
+ const PARTICLE_SOFT_FADE_RANGE : f32 = ${PARTICLE_SOFT_FADE_RANGE};
77
+
78
+ struct ParticleAVBOITDrawOutput {
79
+ @location(0) color : vec4<f32>,
80
+ @location(1) norm : vec4<f32>,
81
+ @location(2) extinction : vec4<f32>,
82
+ @location(3) emission : vec4<f32>,
83
+ }
84
+
85
+ // Each draw uses the same GPU-owned alive list. Clip the other modes before rasterization.
86
+ fn particle_avboit_vertex(vi : u32, ii : u32, blend : u32) -> ParticleVertexOut {
87
+ var out = particle_billboard_vertex(vi, ii);
88
+ if (particle_avboit_draw_blend(out.color, out.blend) != blend) {
89
+ out.clip = vec4<f32>(2.0, 2.0, 2.0, 1.0);
90
+ }
91
+ return out;
92
+ }
93
+
94
+ @vertex
95
+ fn vs_alpha(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
96
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ALPHA);
97
+ }
98
+
99
+ @vertex
100
+ fn vs_additive(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
101
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ADDITIVE);
102
+ }
103
+
104
+ @vertex
105
+ fn vs_general(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
106
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_PREMULTIPLIED);
107
+ }
108
+
109
+ @fragment
110
+ fn fs_main(in : ParticleVertexOut) -> ParticleAVBOITDrawOutput {
111
+ let screen_uv = in.clip.xy / vec2<f32>(f32(view.width), f32(view.height));
112
+
113
+ let transmittance = avboit_sample_transmittance(&warp, tIntegral, sLinear, screen_uv, in.view_depth);
114
+
115
+ if (all(transmittance <= vec3<f32>(${AVBOIT_EXTINCT_TRANSMITTANCE}))) {
116
+ // nothing this fragment contributes survives what is in front of it; skip the shading
117
+ discard;
118
+ }
119
+
120
+ var color = textureSample(atlas, atlas_sampler, in.uv) * in.color;
121
+
122
+ if ((in.flags & PARTICLE_FLAG_SOFT_DEPTH) != 0u) {
123
+ let scene_vd = particle_scene_view_depth(textureLoad(scene_depth, vec2<i32>(in.clip.xy), 0).r, camera);
124
+ color = particle_fade_color(color, in.blend, particle_soft_fade(scene_vd, in.view_depth, PARTICLE_SOFT_FADE_RANGE));
125
+ }
126
+
127
+ if ((in.flags & PARTICLE_FLAG_LIGHTING) != 0u) {
128
+ color = particle_apply_lighting(color, in.world_position, normalize(in.normal));
129
+ }
130
+
131
+ if (particle_avboit_is_empty(color, in.blend)) {
132
+ discard;
133
+ }
134
+
135
+ let volumetrics = sample_volumetrics(in.view_depth, screen_uv, in.clip.xy);
136
+
137
+ let contribution = particle_avboit_contribution(color, in.blend, transmittance, volumetrics);
138
+
139
+ var out : ParticleAVBOITDrawOutput;
140
+
141
+ out.color = contribution.color;
142
+ out.norm = contribution.norm;
143
+ out.extinction = contribution.extinction;
144
+ out.emission = contribution.emission;
145
+
146
+ return out;
147
+ }
148
+ `, [
149
+ chunk_particle_avboit_contribution,
150
+ chunk_particle_scene_view_depth,
151
+ chunk_particle_billboard_vertex,
152
+ chunk_particle_lighting,
153
+ chunk_sample_volumetrics,
154
+ chunk_avboit_sample_transmittance,
155
+ ]);
156
+
157
+ const descriptor = ShaderDescriptor.from({ label: "Particle AVBOIT Draw", body, resources });
158
+
159
+ /**
160
+ * The variants share WGSL, bindings and attachments; only the vertex entry point and target writes
161
+ * differ. Disabling unused targets avoids blending zeros over every billboard pixel.
162
+ * @param {string} label
163
+ * @param {string} entryPoint
164
+ * @param {number[]} writeMasks
165
+ * @returns {RenderPipelineDescriptor}
166
+ */
167
+ function create_draw_pipeline(label, entryPoint, writeMasks) {
168
+ return RenderPipelineDescriptor.from({
169
+ label,
170
+ layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
171
+ vertex: { module: { code: descriptor.source }, entryPoint },
172
+ fragment: {
173
+ module: { code: descriptor.source },
174
+ entryPoint: "fs_main",
175
+ targets: AVBOIT_DRAW_TARGETS.map((target, i) => ({ ...target, writeMask: writeMasks[i] })),
176
+ },
177
+ depthStencil: DepthStencilState.from({ format: "depth32float", depthWriteEnabled: false, depthCompare: "greater" }),
178
+ primitive: { topology: "triangle-list", cullMode: "none" },
179
+ });
180
+ }
181
+
182
+ export const PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Alpha", "vs_alpha", [0xF, 0xF, 0xF, 0]);
183
+ export const PARTICLE_AVBOIT_DRAW_ADDITIVE_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Additive", "vs_additive", [0, 0, 0, 0xF]);
184
+ export const PARTICLE_AVBOIT_DRAW_GENERAL_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw General", "vs_general", [0xF, 0xF, 0xF, 0xF]);
185
+
186
+ /** The draw shader's resource set, for building its bind group. */
187
+ export const PARTICLE_AVBOIT_DRAW_RESOURCES = resources;
188
+
189
+ /** The assembled shader, for the validity tier. */
190
+ export const shader_particle_avboit_draw = descriptor;
@@ -70,6 +70,10 @@ export type AVBOITSideChannel = {
70
70
  /**
71
71
  * draw the
72
72
  * channel's fragments into the accumulators; returns their handles after the draw.
73
+ * `volumetrics_irradiance` is what a fragment standing in a froxel is lit by
74
+ * (`chunk_volumetrics_irradiance_sh`), for a channel whose fragments are lit: the renderer's
75
+ * indirect lighting, whichever mode it runs, and the scene's lights, shadowed and attenuated by
76
+ * the fog, written by the pass that lights the fog.
73
77
  */
74
78
  avboit_draw: (args: {
75
79
  graph: import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
@@ -80,6 +84,10 @@ export type AVBOITSideChannel = {
80
84
  integral: number;
81
85
  volumetrics_lut: number;
82
86
  volumetrics_metadata: number;
87
+ volumetrics_irradiance: {
88
+ Y: number;
89
+ CoCg: number;
90
+ };
83
91
  accumulators: {
84
92
  color: number;
85
93
  norm: number;
@@ -1 +1 @@
1
- {"version":3,"file":"AVBOITSideChannel.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAoCc,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,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;;;;;;sBAE9D,MAAM,OAAO"}
1
+ {"version":3,"file":"AVBOITSideChannel.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAoCc,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;;;;;;sBAM9D,MAAM,OAAO"}
@@ -62,9 +62,14 @@
62
62
  * integral: number,
63
63
  * volumetrics_lut: number,
64
64
  * volumetrics_metadata: number,
65
+ * volumetrics_irradiance: {Y: number, CoCg: number},
65
66
  * accumulators: {color: number, norm: number, extinction: number, emission: number},
66
67
  * }) => {color: number, norm: number, extinction: number, emission: number}} avboit_draw draw the
67
68
  * channel's fragments into the accumulators; returns their handles after the draw.
69
+ * `volumetrics_irradiance` is what a fragment standing in a froxel is lit by
70
+ * (`chunk_volumetrics_irradiance_sh`), for a channel whose fragments are lit: the renderer's
71
+ * indirect lighting, whichever mode it runs, and the scene's lights, shadowed and attenuated by
72
+ * the fog, written by the pass that lights the fog.
68
73
  * @property {() => boolean} [avboit_is_empty] whether the channel would add nothing this frame;
69
74
  * asked before the orchestrator records, and a channel that answers `true` is not asked for
70
75
  * anything else in that frame.
@@ -155,13 +155,16 @@ export function avboit_create_accumulators(pass: FramePassBuilder, resolution: A
155
155
  * @param {number} options.shadowmap_atlas
156
156
  * @param {number} options.volumetrics_lut
157
157
  * @param {number} options.volumetrics_metadata
158
+ * @param {{Y: number, CoCg: number}} options.volumetrics_irradiance the froxel irradiance volume
159
+ * (`chunk_volumetrics_irradiance_sh`), for side channels that light their own fragments; the
160
+ * MBOIT orchestrator ignores it
158
161
  * @param {ShadeIndirectLightingMode} options.indirect_lighting_mode
159
162
  * @param {AVBOITSettings} [options.avboit] `Renderer.avboit`; the MBOIT orchestrator ignores it
160
163
  * @param {import("./AVBOITSideChannel.js").AVBOITSideChannel[]} [options.side_channels] non-meshlet
161
164
  * sources of transparent fragments; the MBOIT orchestrator ignores them
162
165
  * @returns {number} resource ID of the composited color texture
163
166
  */
164
- export function graph_rasterize_meshes_transparent_avboit({ graph, buckets, view_ctx, viewport, depth_texture, color_texture, limits, light_cluster_parameters, light_cluster_lookup, light_cluster_data, shadowmap_atlas, volumetrics_lut, volumetrics_metadata, indirect_lighting_mode, avboit, side_channels, }: {
167
+ export function graph_rasterize_meshes_transparent_avboit({ graph, buckets, view_ctx, viewport, depth_texture, color_texture, limits, light_cluster_parameters, light_cluster_lookup, light_cluster_data, shadowmap_atlas, volumetrics_lut, volumetrics_metadata, volumetrics_irradiance, indirect_lighting_mode, avboit, side_channels, }: {
165
168
  graph: FrameGraph;
166
169
  buckets: number;
167
170
  view_ctx: GPUViewContext;
@@ -175,6 +178,10 @@ export function graph_rasterize_meshes_transparent_avboit({ graph, buckets, view
175
178
  shadowmap_atlas: number;
176
179
  volumetrics_lut: number;
177
180
  volumetrics_metadata: number;
181
+ volumetrics_irradiance: {
182
+ Y: number;
183
+ CoCg: number;
184
+ };
178
185
  indirect_lighting_mode: ShadeIndirectLightingMode;
179
186
  avboit?: AVBOITSettings;
180
187
  side_channels?: import("./AVBOITSideChannel.js").AVBOITSideChannel[];
@@ -1 +1 @@
1
- {"version":3,"file":"graph_rasterize_meshes_transparent_avboit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js"],"names":[],"mappings":"AA4DA;;;;;GAKG;AACH,oDAHW,UAAU,MAAM,CAAC,GACf,MAAM,EAAE,CAOpB;AAED;;;;;;;;;;;;GAYG;AACH;IAT+B,KAAK;IACA,KAAK;IACd,MAAM,EAAtB,MAAM;IACqB,kBAAkB,EAA7C,UAAU,MAAM,CAAC;IACD,kBAAkB,EAAlC,MAAM;IACU,wBAAwB,EAAxC,MAAM;IACW,SAAS,GAA1B,MAAM;IACJ,MAAM,CA4DlB;AAED;;;;;;;;;;GAUG;AACH;IAP+B,KAAK;IACT,SAAS,EAAzB,MAAM;IACY,gBAAgB,EAAlC,MAAM,EAAE;IACmB,kBAAkB,EAA7C,UAAU,MAAM,CAAC;IACQ,MAAM,GAA/B,cAAc;IACZ,MAAM,CAsDlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,6KAFa;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAiJjE;AAED;;;;;;;;;;GAUG;AACH;IAP+B,KAAK;IACT,IAAI,EAApB,MAAM;IACU,UAAU,EAA1B,MAAM;IACU,QAAQ,EAAxB,MAAM;IACY,gBAAgB,EAAlC,MAAM,EAAE;IACN,MAAM,CAoClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qUAFa;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAC,CAwN7D;AAED;;;;;;;;GAQG;AACH,+EAHW,UAAU,MAAM,CAAC,GACf;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAe/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH;IAnB+B,KAAK;IACT,OAAO,EAAvB,MAAM;IACkB,QAAQ;IACd,QAAQ,EAA1B,MAAM,EAAE;IACQ,aAAa,EAA7B,MAAM;IACU,aAAa,EAA7B,MAAM;IACuB,MAAM;IACnB,wBAAwB,EAAxC,MAAM;IACU,oBAAoB,EAApC,MAAM;IACU,kBAAkB,EAAlC,MAAM;IACU,eAAe,EAA/B,MAAM;IACU,eAAe,EAA/B,MAAM;IACU,oBAAoB,EAApC,MAAM;IAC6B,sBAAsB,EAAzD,yBAAyB;IACA,MAAM,GAA/B,cAAc;IACiD,aAAa,GAA5E,OAAO,wBAAwB,EAAE,iBAAiB,EAAE;IAElD,MAAM,CAwRlB;+BA57B8B,qBAAqB;0CA9BV,uCAAuC"}
1
+ {"version":3,"file":"graph_rasterize_meshes_transparent_avboit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js"],"names":[],"mappings":"AA4DA;;;;;GAKG;AACH,oDAHW,UAAU,MAAM,CAAC,GACf,MAAM,EAAE,CAOpB;AAED;;;;;;;;;;;;GAYG;AACH;IAT+B,KAAK;IACA,KAAK;IACd,MAAM,EAAtB,MAAM;IACqB,kBAAkB,EAA7C,UAAU,MAAM,CAAC;IACD,kBAAkB,EAAlC,MAAM;IACU,wBAAwB,EAAxC,MAAM;IACW,SAAS,GAA1B,MAAM;IACJ,MAAM,CA4DlB;AAED;;;;;;;;;;GAUG;AACH;IAP+B,KAAK;IACT,SAAS,EAAzB,MAAM;IACY,gBAAgB,EAAlC,MAAM,EAAE;IACmB,kBAAkB,EAA7C,UAAU,MAAM,CAAC;IACQ,MAAM,GAA/B,cAAc;IACZ,MAAM,CAsDlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,6KAFa;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAiJjE;AAED;;;;;;;;;;GAUG;AACH;IAP+B,KAAK;IACT,IAAI,EAApB,MAAM;IACU,UAAU,EAA1B,MAAM;IACU,QAAQ,EAAxB,MAAM;IACY,gBAAgB,EAAlC,MAAM,EAAE;IACN,MAAM,CAoClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qUAFa;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAC,CAwN7D;AAED;;;;;;;;GAQG;AACH,+EAHW,UAAU,MAAM,CAAC,GACf;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAe/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IAtB+B,KAAK;IACT,OAAO,EAAvB,MAAM;IACkB,QAAQ;IACd,QAAQ,EAA1B,MAAM,EAAE;IACQ,aAAa,EAA7B,MAAM;IACU,aAAa,EAA7B,MAAM;IACuB,MAAM;IACnB,wBAAwB,EAAxC,MAAM;IACU,oBAAoB,EAApC,MAAM;IACU,kBAAkB,EAAlC,MAAM;IACU,eAAe,EAA/B,MAAM;IACU,eAAe,EAA/B,MAAM;IACU,oBAAoB,EAApC,MAAM;IAC6B,sBAAsB,EAAzD;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC;IAGU,sBAAsB,EAAzD,yBAAyB;IACA,MAAM,GAA/B,cAAc;IACiD,aAAa,GAA5E,OAAO,wBAAwB,EAAE,iBAAiB,EAAE;IAElD,MAAM,CA8RlB;+BAr8B8B,qBAAqB;0CA9BV,uCAAuC"}
@@ -708,6 +708,9 @@ export function avboit_create_accumulators(pass, resolution) {
708
708
  * @param {number} options.shadowmap_atlas
709
709
  * @param {number} options.volumetrics_lut
710
710
  * @param {number} options.volumetrics_metadata
711
+ * @param {{Y: number, CoCg: number}} options.volumetrics_irradiance the froxel irradiance volume
712
+ * (`chunk_volumetrics_irradiance_sh`), for side channels that light their own fragments; the
713
+ * MBOIT orchestrator ignores it
711
714
  * @param {ShadeIndirectLightingMode} options.indirect_lighting_mode
712
715
  * @param {AVBOITSettings} [options.avboit] `Renderer.avboit`; the MBOIT orchestrator ignores it
713
716
  * @param {import("./AVBOITSideChannel.js").AVBOITSideChannel[]} [options.side_channels] non-meshlet
@@ -730,6 +733,7 @@ export function graph_rasterize_meshes_transparent_avboit({
730
733
 
731
734
  volumetrics_lut,
732
735
  volumetrics_metadata,
736
+ volumetrics_irradiance,
733
737
 
734
738
  indirect_lighting_mode = ShadeIndirectLightingMode.IBL,
735
739
  avboit = DEFAULT_SETTINGS,
@@ -747,6 +751,10 @@ export function graph_rasterize_meshes_transparent_avboit({
747
751
 
748
752
  assert.isNonNegativeInteger(shadowmap_atlas, 'shadowmap_atlas');
749
753
 
754
+ assert.defined(volumetrics_irradiance, 'volumetrics_irradiance');
755
+ assert.isNonNegativeInteger(volumetrics_irradiance.Y, 'volumetrics_irradiance.Y');
756
+ assert.isNonNegativeInteger(volumetrics_irradiance.CoCg, 'volumetrics_irradiance.CoCg');
757
+
750
758
  assert.equal(view_ctx.isGPUViewContext, true, 'view_ctx.isGPUViewContext !== true');
751
759
 
752
760
  const scene_ctx = view_ctx.scene;
@@ -971,6 +979,7 @@ export function graph_rasterize_meshes_transparent_avboit({
971
979
  integral,
972
980
  volumetrics_lut,
973
981
  volumetrics_metadata,
982
+ volumetrics_irradiance,
974
983
  accumulators,
975
984
  });
976
985
  }
@@ -30,16 +30,26 @@ export class GPUViewVolumetrics {
30
30
  * @param {number} options.light_cluster_lookup
31
31
  * @param {number} options.light_cluster_parameters
32
32
  * @param {number} options.shadowmap_atlas
33
+ * @param {import("../ShadeIndirectLightingMode.js").ShadeIndirectLightingMode} options.indirect_lighting_mode the renderer's; picks the froxel GI
34
+ * module that starts the froxel irradiance volume
35
+ * @returns {{resolved: number, metadata: number, irradiance: {Y: number, CoCg: number}}} the
36
+ * integrated aerial LUT, the metadata buffer, and the froxel irradiance volume
37
+ * (chunk_volumetrics_irradiance_sh) for the transparent surfaces the lighting pass cannot see
33
38
  */
34
- graph_update({ graph, light_cluster_data, light_cluster_lookup, light_cluster_parameters, shadowmap_atlas, }: {
39
+ graph_update({ graph, light_cluster_data, light_cluster_lookup, light_cluster_parameters, shadowmap_atlas, indirect_lighting_mode, }: {
35
40
  graph: FrameGraph;
36
41
  light_cluster_data: number;
37
42
  light_cluster_lookup: number;
38
43
  light_cluster_parameters: number;
39
44
  shadowmap_atlas: number;
45
+ indirect_lighting_mode: import("../ShadeIndirectLightingMode.js").ShadeIndirectLightingMode;
40
46
  }): {
41
- resolved: any;
42
- metadata: any;
47
+ resolved: number;
48
+ metadata: number;
49
+ irradiance: {
50
+ Y: number;
51
+ CoCg: number;
52
+ };
43
53
  };
44
54
  #private;
45
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GPUViewVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/GPUViewVolumetrics.js"],"names":[],"mappings":"AAiCA;IAkII;;;;OAIG;IACH,kBAHW,cAAc,qBAwBxB;IAxHD;;OAEG;IACH,4BAOC;IAjBD;;OAEG;IACH,2BAEC;IAsCD;;OAEG;IACH,0BAEC;IAZD;;OAEG;IACH,yBAEC;IAwFD,gBAWC;IA6ND;;;;;;;;OAQG;IACH;QAN+B,KAAK,EAAzB,UAAU;QACM,kBAAkB,EAAlC,MAAM;QACU,oBAAoB,EAApC,MAAM;QACU,wBAAwB,EAAxC,MAAM;QACU,eAAe,EAA/B,MAAM;;;;MAoFhB;;CAEJ;yBA5eY,OAAO,2DAA2D,EAAE,UAAU;6BAC9E,OAAO,2BAA2B,EAAE,cAAc"}
1
+ {"version":3,"file":"GPUViewVolumetrics.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/GPUViewVolumetrics.js"],"names":[],"mappings":"AAiCA;IAkII;;;;OAIG;IACH,kBAHW,cAAc,qBAwBxB;IAxHD;;OAEG;IACH,4BAOC;IAjBD;;OAEG;IACH,2BAEC;IAsCD;;OAEG;IACH,0BAEC;IAZD;;OAEG;IACH,yBAEC;IAwFD,gBAWC;IA6ND;;;;;;;;;;;;;OAaG;IACH;QAX+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,CAyFvF;;CAEJ;yBApfY,OAAO,2DAA2D,EAAE,UAAU;6BAC9E,OAAO,2BAA2B,EAAE,cAAc"}
@@ -429,6 +429,11 @@ export class GPUViewVolumetrics {
429
429
  * @param {number} options.light_cluster_lookup
430
430
  * @param {number} options.light_cluster_parameters
431
431
  * @param {number} options.shadowmap_atlas
432
+ * @param {import("../ShadeIndirectLightingMode.js").ShadeIndirectLightingMode} options.indirect_lighting_mode the renderer's; picks the froxel GI
433
+ * module that starts the froxel irradiance volume
434
+ * @returns {{resolved: number, metadata: number, irradiance: {Y: number, CoCg: number}}} the
435
+ * integrated aerial LUT, the metadata buffer, and the froxel irradiance volume
436
+ * (chunk_volumetrics_irradiance_sh) for the transparent surfaces the lighting pass cannot see
432
437
  */
433
438
  graph_update({
434
439
  graph,
@@ -436,6 +441,7 @@ export class GPUViewVolumetrics {
436
441
  light_cluster_lookup,
437
442
  light_cluster_parameters,
438
443
  shadowmap_atlas,
444
+ indirect_lighting_mode,
439
445
  }) {
440
446
 
441
447
  const view = this.#view;
@@ -487,7 +493,7 @@ export class GPUViewVolumetrics {
487
493
  taa_output = graph_import_texture(graph, this.#volumetrics_textures[parity], "volumetrics taa output");
488
494
  }
489
495
 
490
- const { lut_aerial } = graph_build_volumetrics({
496
+ const { lut_aerial, irradiance } = graph_build_volumetrics({
491
497
  graph,
492
498
  camera,
493
499
  lights,
@@ -496,6 +502,7 @@ export class GPUViewVolumetrics {
496
502
  light_cluster_lookup,
497
503
  light_cluster_parameters,
498
504
  shadowmap_atlas,
505
+ indirect_lighting_mode,
499
506
 
500
507
  volumetrics_metadata: gr_metadata,
501
508
  volumetric_resolution: resolution,
@@ -511,6 +518,7 @@ export class GPUViewVolumetrics {
511
518
  return {
512
519
  resolved: lut_aerial,
513
520
  metadata: gr_metadata,
521
+ irradiance,
514
522
  };
515
523
  }
516
524