@woosh/meep-engine 3.11.0 → 3.11.2
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/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +294 -290
- package/src/engine/graphics3/ParticipatingMedia.d.ts +111 -0
- package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMedia.js +203 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +34 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +73 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +87 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.js +184 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/volumetrics_froxel/README.md +191 -0
- package/src/shade/playground/volumetrics_froxel/index.html +270 -0
- package/src/shade/playground/volumetrics_froxel/main.d.ts +2 -0
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -0
- package/src/shade/playground/volumetrics_froxel/main.js +917 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts +119 -0
- package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -0
- package/src/shade/playground/volumetrics_froxel/measure.js +559 -0
- package/src/shade/renderer/Renderer.d.ts +13 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +45 -18
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts +14 -13
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +133 -129
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +480 -315
- package/src/shade/renderer/volumetrics/NOTES.md +691 -9
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +5 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +21 -2
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +26 -0
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/SceneVolumetrics.js +64 -21
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js +84 -28
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts +98 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.js +111 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts +84 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js +252 -0
- package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.d.ts +21 -0
- package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.js +47 -0
- package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.js +75 -64
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.d.ts +37 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.js +56 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts +43 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.js +145 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +20 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +48 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts +38 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.js +107 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +4 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +577 -465
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +418 -324
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +14 -3
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts +8 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +174 -0
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.js +48 -36
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +25 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/CPUBitmapData.js +33 -0
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +2221 -2215
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +1297 -1117
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts +69 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts.map +1 -0
- package/src/shade/wgsl/emulator/cpu_texture_gather.js +148 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts +16 -0
- package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/cpu_texture_sample.js +176 -172
|
@@ -1,324 +1,418 @@
|
|
|
1
|
-
import { vec3f } from "../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
-
import { WebGPUArray } from "../shader/type/WebGPUArray.js";
|
|
3
|
-
import { CAMERA_UNIFORM_STRUCT } from "../camera/CAMERA_UNIFORM_STRUCT.js";
|
|
4
|
-
import { chunk_rgb_to_luminance } from "../shader/chunk/color/chunk_rgb_to_luminance.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
let
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
let
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
direction
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
optical_depth
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
1
|
+
import { vec3f } from "../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../shader/type/WebGPUArray.js";
|
|
3
|
+
import { CAMERA_UNIFORM_STRUCT } from "../camera/CAMERA_UNIFORM_STRUCT.js";
|
|
4
|
+
import { chunk_rgb_to_luminance } from "../shader/chunk/color/chunk_rgb_to_luminance.js";
|
|
5
|
+
import { chunk_stbn_sample_vec3 } from "../shader/chunk/noise/chunk_stbn_sample_vec3.js";
|
|
6
|
+
import { chunk_camera_ray_from_uv } from "../shader/chunk/geometry/ray/chunk_camera_ray_from_uv.js";
|
|
7
|
+
import { RAY_STRUCT } from "../shader/chunk/geometry/ray/RAY_STRUCT.js";
|
|
8
|
+
import {
|
|
9
|
+
chunk_directional_lights_iteration_mask
|
|
10
|
+
} from "../shader/chunk/light/io/chunk_directional_lights_iteration_mask.js";
|
|
11
|
+
import {
|
|
12
|
+
chunk_get_directional_light_info_by_index
|
|
13
|
+
} from "../shader/chunk/light/io/chunk_get_directional_light_info_by_index.js";
|
|
14
|
+
import {
|
|
15
|
+
chunk_get_point_light_info_by_index
|
|
16
|
+
} from "../shader/chunk/light/io/chunk_get_point_light_info_by_index.js";
|
|
17
|
+
import { chunk_get_spot_light_info_by_index } from "../shader/chunk/light/io/chunk_get_spot_light_info_by_index.js";
|
|
18
|
+
import { chunk_texel_coordinate_to_uv } from "../shader/chunk/texture/chunk_texel_coordinate_to_uv.js";
|
|
19
|
+
import { chunk_uv_to_texel_coordinate } from "../shader/chunk/texture/chunk_uv_to_texel_coordinate.js";
|
|
20
|
+
import { CodeChunk } from "../shader/compiler/CodeChunk.js";
|
|
21
|
+
import { ComputeShader } from "../shader/ComputeShader.js";
|
|
22
|
+
import { ShaderResourceSetDescriptor } from "../shader/resource/ShaderResourceSetDescriptor.js";
|
|
23
|
+
import { chunk_shadowmap_get_light_visibility } from "../shadow/map/shader/chunk_shadowmap_get_light_visibility.js";
|
|
24
|
+
import { SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR } from "../shadow/map/SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR.js";
|
|
25
|
+
import { SAMPLER_LINEAR_UPSCALE } from "../texture/SAMPLER_LINEAR_UPSCALE.js";
|
|
26
|
+
import { VIEW_UNIFORM_STRUCT } from "../view/VIEW_UNIFORM_STRUCT.js";
|
|
27
|
+
import { chunk_cluster_depth_from_z_slice } from "../light/cluster/chunk_cluster_depth_from_z_slice.js";
|
|
28
|
+
import { chunk_cluster_depth_to_z_slice } from "../light/cluster/chunk_cluster_depth_to_z_slice.js";
|
|
29
|
+
import { chunk_light_cluster_counts } from "../light/cluster/chunk_light_cluster_counts.js";
|
|
30
|
+
import { chunk_light_cluster_metadata_by_position } from "../light/cluster/chunk_light_cluster_metadata_by_position.js";
|
|
31
|
+
import { LIGHT_CLUSTER_LOOKUP_STRUCT } from "../light/cluster/shader_cluster_assign_lights.js";
|
|
32
|
+
import { chunk_sky_lut_compute_uv } from "../atmosphere/chunk_sky_lut_compute_uv.js";
|
|
33
|
+
import { chunk_calculate_multiscattering } from "./chunk_calculate_multiscattering.js";
|
|
34
|
+
import { chunk_camera_ray_planar_depth_scale } from "./chunk_camera_ray_planar_depth_scale.js";
|
|
35
|
+
import { chunk_volumetrics_froxel_content_offset } from "./chunk_volumetrics_froxel_content_offset.js";
|
|
36
|
+
import { chunk_integrate_optical_depth } from "./chunk_integrate_optical_depth.js";
|
|
37
|
+
import {
|
|
38
|
+
chunk_volumetrics_sun_optical_depth,
|
|
39
|
+
volumetrics_sun_shadow_texture_name
|
|
40
|
+
} from "./chunk_volumetrics_sun_optical_depth.js";
|
|
41
|
+
import { VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT } from "./VOLUMETRICS_SUN_SHADOW_RESOLUTION.js";
|
|
42
|
+
import { chunk_volumetrics_column_jitter } from "./chunk_volumetrics_column_jitter.js";
|
|
43
|
+
import { chunk_volumetrics_local_light_shadow } from "./chunk_volumetrics_local_light_shadow.js";
|
|
44
|
+
import { VOLUMETRICS_METADATA_STRUCT } from "./VOLUMETRICS_METADATA_STRUCT.js";
|
|
45
|
+
|
|
46
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
47
|
+
|
|
48
|
+
const primary_group = resources.createGroup()
|
|
49
|
+
.addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
|
|
50
|
+
.addUniform("camera", CAMERA_UNIFORM_STRUCT)
|
|
51
|
+
.addUniform("view", VIEW_UNIFORM_STRUCT)
|
|
52
|
+
.addTexture("tSunTransmittance", "float", "2d")
|
|
53
|
+
.addTexture("tMultiScattering", "float", "2d")
|
|
54
|
+
.addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
|
|
55
|
+
.addTexture("tSTBN_vec3", "unfilterable-float", "3d")
|
|
56
|
+
.addTexture("tParticipatingMedia0", "float", "3d")
|
|
57
|
+
.addTexture("tParticipatingMedia1", "float", "3d");
|
|
58
|
+
|
|
59
|
+
// Q-04: the sun's optical depth, pre-integrated along the light axis by
|
|
60
|
+
// shader_volumetrics_build_sun_shadow_volume, one cascade per texture and innermost first.
|
|
61
|
+
// Sampled, not marched.
|
|
62
|
+
for (let cascade = 0; cascade < VOLUMETRICS_SUN_SHADOW_CASCADE_COUNT; cascade++) {
|
|
63
|
+
primary_group.addTexture(volumetrics_sun_shadow_texture_name(cascade), "float", "3d");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
primary_group.addStorageTexture("tLighting", "rgba16float", "3d", "write-only")
|
|
67
|
+
|
|
68
|
+
// Lighting information
|
|
69
|
+
resources.createGroup()
|
|
70
|
+
|
|
71
|
+
.addStorageBuffer("light_data", WebGPUArray.u32)
|
|
72
|
+
// clusters
|
|
73
|
+
.addUniform("cluster_parameters", vec3f)
|
|
74
|
+
.addStorageBuffer("cluster_lookup", LIGHT_CLUSTER_LOOKUP_STRUCT)
|
|
75
|
+
.addStorageBuffer("cluster_data", WebGPUArray.u32)
|
|
76
|
+
// shadows
|
|
77
|
+
.addTexture("shadowmapAtlas", "depth")
|
|
78
|
+
.addSampler("sCompareLinear", "comparison", SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR)
|
|
79
|
+
|
|
80
|
+
const body = CodeChunk.from(
|
|
81
|
+
//language=WGSL
|
|
82
|
+
`
|
|
83
|
+
@compute @workgroup_size(16,16)
|
|
84
|
+
fn main(
|
|
85
|
+
@builtin(global_invocation_id) voxel_coord : vec3<u32>
|
|
86
|
+
){
|
|
87
|
+
let resolution = textureDimensions(tParticipatingMedia0);
|
|
88
|
+
|
|
89
|
+
if(any(voxel_coord >= resolution)){
|
|
90
|
+
// overflow
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Logical near/far, NOT the projection-derived range: the projection is infinite-far
|
|
95
|
+
// reverse-Z, so its far resolves to ~3.4e38 (FLOAT32_MAX). That value would leave the last
|
|
96
|
+
// froxel slice's z1 (and z1*z1*z1 below) at +Inf. clip_near_far is the bounded logical range,
|
|
97
|
+
// matching the participating-media build shader.
|
|
98
|
+
let near_far = camera.clip_near_far;
|
|
99
|
+
|
|
100
|
+
// same jitter valud for all voxels in Z column
|
|
101
|
+
// must be the same for PM and Lights
|
|
102
|
+
let z_jitter = volumetrics_column_jitter(voxel_coord.xy, view.frame_index);
|
|
103
|
+
|
|
104
|
+
let z_slice_0 = f32(voxel_coord.z ) + z_jitter;
|
|
105
|
+
let z_slice_1 = f32(voxel_coord.z + 1) + z_jitter;
|
|
106
|
+
|
|
107
|
+
let z0 = max(near_far.x, cluster_depth_from_z_slice( z_slice_0, volumetrics_metadata.froxel_cluster_parameters, f32(resolution.z) ));
|
|
108
|
+
let z1 = min(near_far.y, cluster_depth_from_z_slice( z_slice_1, volumetrics_metadata.froxel_cluster_parameters, f32(resolution.z) ));
|
|
109
|
+
|
|
110
|
+
// 2. Cubic mix gives uniform distribution in World Space Volume
|
|
111
|
+
let z3_min = z0 * z0 * z0;
|
|
112
|
+
let z3_max = z1 * z1 * z1;
|
|
113
|
+
|
|
114
|
+
var inScatteringSum = vec3<f32>(0.0);
|
|
115
|
+
var extinctionSum = 0.0;
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
// One sample per froxel. The 0.95-blend TAA downstream is a ~39-effective-sample temporal
|
|
119
|
+
// integrator; supersampling here as well spends N times this pass removing variance that filter
|
|
120
|
+
// removes anyway — and spends it at the Monte Carlo rate, because the samples were independent
|
|
121
|
+
// white noise and converged as 1/sqrt(N). Raising this is only worth it with the temporal
|
|
122
|
+
// filter off.
|
|
123
|
+
const SAMPLE_COUNT = 1u;
|
|
124
|
+
|
|
125
|
+
for(var i = 0u; i < SAMPLE_COUNT; i++){
|
|
126
|
+
|
|
127
|
+
// Spatiotemporal blue noise rather than a per-froxel hash. What lets 1 spp survive a
|
|
128
|
+
// temporal filter is each froxel seeing a well-distributed sequence over frames, which is
|
|
129
|
+
// STBN's defining property and exactly what white noise lacks — measured against the murmur
|
|
130
|
+
// hash it reaches the same error in roughly half the frames, across the whole window the
|
|
131
|
+
// 0.95 blend spans.
|
|
132
|
+
//
|
|
133
|
+
// The xy offset is load-bearing, not decoration. The aerial pass reads this same volume at
|
|
134
|
+
// (voxel_coord.xy, frame_index) and consumes all three channels, so sampling it there would
|
|
135
|
+
// not merely correlate the two passes' jitters — it would make them the same number. Two
|
|
136
|
+
// nuisance variables locked together stop covering the sample domain and the estimator
|
|
137
|
+
// converges to the wrong value, a bias that does NOT shrink with more frames, so no TAA
|
|
138
|
+
// window recovers it. Measured worst case |r| against any aerial channel: 1.0000 at zero
|
|
139
|
+
// offset, 0.0027 here.
|
|
140
|
+
//
|
|
141
|
+
// froxel z rides the temporal axis so froxels down a column do not all share one value —
|
|
142
|
+
// the fetch is indexed by column, and STBN's z axis is the one built to be well distributed.
|
|
143
|
+
const STBN_DECORRELATION_OFFSET = vec2<u32>(37u, 71u);
|
|
144
|
+
|
|
145
|
+
let noise = stbn_sample_vec3(vec3(
|
|
146
|
+
voxel_coord.xy + STBN_DECORRELATION_OFFSET,
|
|
147
|
+
(view.frame_index + voxel_coord.z) * SAMPLE_COUNT + i
|
|
148
|
+
));
|
|
149
|
+
|
|
150
|
+
// [0..1] — offset (jitter - 0.5) must be centered on the froxel for every axis. The depth
|
|
151
|
+
// axis is stratified so that raising SAMPLE_COUNT converges faster than 1/sqrt(N); a no-op
|
|
152
|
+
// while it is 1.
|
|
153
|
+
let jitter = vec3(noise.xy, (f32(i) + noise.z) / f32(SAMPLE_COUNT));
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
// Interpolate the cubes, then take the cube root
|
|
157
|
+
let z3_sample = mix(z3_min, z3_max, jitter.z);
|
|
158
|
+
let view_depth = pow(z3_sample, 0.333333);
|
|
159
|
+
|
|
160
|
+
let sample_z_index:f32 = cluster_depth_to_z_slice(
|
|
161
|
+
view_depth,
|
|
162
|
+
volumetrics_metadata.froxel_cluster_parameters,
|
|
163
|
+
f32(resolution.z)
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// 'saturate' prevents accidental out-of-bounds samples
|
|
167
|
+
let tile_uv = saturate(
|
|
168
|
+
texel_coordinate_to_uv(vec2f(voxel_coord.xy) + (jitter.xy - 0.5), resolution.xy)
|
|
169
|
+
);
|
|
170
|
+
let view_ray = camera_ray_from_uv(tile_uv, camera);
|
|
171
|
+
|
|
172
|
+
// The PM volumes are CELL-AVERAGED: texel k holds the slab [k+j, k+1+j], so its content
|
|
173
|
+
// sits at slice k + j + delta, not at slice k. Addressing them with the plain texel-centre
|
|
174
|
+
// convention is what the boundary-sampled aerial LUT wants, and reads the medium about half
|
|
175
|
+
// a froxel too far out. delta is a property of the depth curve — see the chunk.
|
|
176
|
+
let content_offset = volumetrics_froxel_content_offset(volumetrics_metadata.froxel_cluster_parameters.z);
|
|
177
|
+
|
|
178
|
+
let uvw = vec3<f32>(tile_uv, (sample_z_index + 0.5 - content_offset) / f32(resolution.z));
|
|
179
|
+
|
|
180
|
+
let participating_media0 = textureSampleLevel(tParticipatingMedia0, sLinear, uvw, 0.0);
|
|
181
|
+
let participating_media1 = textureSampleLevel(tParticipatingMedia1, sLinear, uvw, 0.0);
|
|
182
|
+
|
|
183
|
+
let participating_media_scattering = participating_media0.rgb;
|
|
184
|
+
let participating_media_extinction = participating_media1.rgb;
|
|
185
|
+
let participating_media_phase_g = participating_media1.a;
|
|
186
|
+
|
|
187
|
+
// Accumulate the (linear) mono extinction coefficient. Carried in tLighting.a below so the
|
|
188
|
+
// 3D TAA accumulates sigma_t alongside the in-scatter (Hillaire: temporally integrate the
|
|
189
|
+
// LINEAR extinction, never the non-linear transmittance).
|
|
190
|
+
extinctionSum += rgb_to_luminance(participating_media_extinction);
|
|
191
|
+
|
|
192
|
+
let view_pixel_coord = uv_to_texel_coordinate(tile_uv, vec2(view.width, view.height));
|
|
193
|
+
|
|
194
|
+
// view_depth is a PLANAR view-space depth and view_ray.direction is unit length, so the
|
|
195
|
+
// depth has to be converted to a distance along the ray before stepping. Multiplying them
|
|
196
|
+
// directly stops on the arc of constant distance instead of the plane of constant depth,
|
|
197
|
+
// short by cos(theta) — exact on the centre axis, ~72% of the intended depth in the corners
|
|
198
|
+
// of a 50 degree vertical FOV. Radial, which is why it reads as "the fog looks a bit off"
|
|
199
|
+
// rather than as an offset.
|
|
200
|
+
//
|
|
201
|
+
// Everything downstream assumes the planar reading: the light cluster is looked up at the
|
|
202
|
+
// planar depth, the shadow lookup happens at this position, and the TAA reconstructs froxel
|
|
203
|
+
// centres as planar slabs.
|
|
204
|
+
let position_ws = view_ray.origin
|
|
205
|
+
+ view_ray.direction * (view_depth * camera_ray_planar_depth_scale(view_ray.direction, camera));
|
|
206
|
+
|
|
207
|
+
// Global lights (directional) — iterate over the first 32 slots
|
|
208
|
+
// of the directional light table (max enforced by GPULightCollection).
|
|
209
|
+
var directional_bits = directional_lights_iteration_mask(&light_data);
|
|
210
|
+
while (directional_bits != 0u) {
|
|
211
|
+
let directional_index = countTrailingZeros(directional_bits);
|
|
212
|
+
directional_bits &= ~(1u << directional_index);
|
|
213
|
+
|
|
214
|
+
let sun = get_directional_light_info_by_index(&light_data, directional_index);
|
|
215
|
+
|
|
216
|
+
let sun_lut_uv = sky_lut_compute_uv(position_ws, sun.direction);
|
|
217
|
+
|
|
218
|
+
let shadow_term = shadowmap_get_directional_light_visibility(
|
|
219
|
+
&light_data,
|
|
220
|
+
directional_index,
|
|
221
|
+
position_ws,
|
|
222
|
+
// toward-camera, matching the deferred cascade-blend convention. The consumer
|
|
223
|
+
// (shadowmap_csm_compute_cascade_blended) negates this internally; the deferred
|
|
224
|
+
// caller passes the surface->camera vector, whereas view_ray.direction is
|
|
225
|
+
// camera->scene, so it must be negated here to agree.
|
|
226
|
+
-view_ray.direction,
|
|
227
|
+
sun.direction
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
let u = dot(sun.direction, view_ray.direction);
|
|
231
|
+
|
|
232
|
+
// sample atmospheric transmittance
|
|
233
|
+
let transmittance_atmospheric = textureSampleLevel(
|
|
234
|
+
tSunTransmittance,
|
|
235
|
+
sLinear,
|
|
236
|
+
sun_lut_uv, 0.0
|
|
237
|
+
).rgb;
|
|
238
|
+
|
|
239
|
+
// Q-04. Every froxel on this sun ray is asking for the same integral, one increment
|
|
240
|
+
// apart, and the march recomputes all of it from scratch for each: O(froxels * steps)
|
|
241
|
+
// to produce O(froxels) of information. The sun is where that is worst, because its
|
|
242
|
+
// tmax is the distance to the sun clipped to the frustum, so the march spans the whole
|
|
243
|
+
// grid rather than the few metres a lamp's does.
|
|
244
|
+
//
|
|
245
|
+
// So read the answer out of the cascades built once this frame with their axis on the
|
|
246
|
+
// sun, where the increment relation IS the storage — see
|
|
247
|
+
// shader_volumetrics_build_sun_shadow_volume. Same quantity, same units, one fetch.
|
|
248
|
+
//
|
|
249
|
+
// The march below is not an alternative to it, it is what is left for the lights the
|
|
250
|
+
// cascades do not cover: a second directional light, since there is one ladder and it
|
|
251
|
+
// is aligned to one direction, and the two cases that cannot place a box at all, which
|
|
252
|
+
// sun_shadow_light_index reports by holding a value no light index can equal.
|
|
253
|
+
var optical_depth: vec3<f32>;
|
|
254
|
+
|
|
255
|
+
if (directional_index == volumetrics_metadata.sun_shadow_light_index) {
|
|
256
|
+
|
|
257
|
+
optical_depth = volumetrics_sun_optical_depth(position_ws);
|
|
258
|
+
|
|
259
|
+
} else {
|
|
260
|
+
|
|
261
|
+
// .direction points TOWARD the light; march the optical-depth ray toward the light (+direction).
|
|
262
|
+
let shadow_ray = ${RAY_STRUCT.make({
|
|
263
|
+
origin: "position_ws",
|
|
264
|
+
direction: "sun.direction",
|
|
265
|
+
tmax: "sun.distance",
|
|
266
|
+
})};
|
|
267
|
+
|
|
268
|
+
optical_depth = integrate_optical_depth(shadow_ray);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let ms = calculate_multiscattering(
|
|
272
|
+
optical_depth,
|
|
273
|
+
participating_media_scattering,
|
|
274
|
+
participating_media_extinction,
|
|
275
|
+
u,
|
|
276
|
+
participating_media_phase_g,
|
|
277
|
+
volumetrics_metadata.ms_octave_count,
|
|
278
|
+
volumetrics_metadata.ms_extinction_decay
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
inScatteringSum += shadow_term * ms * transmittance_atmospheric * sun.color;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Local lights
|
|
285
|
+
let cluster_metadata = light_cluster_metadata_by_position(
|
|
286
|
+
view_pixel_coord,
|
|
287
|
+
view_depth,
|
|
288
|
+
vec2( view.width, view.height )
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
let cluster_offset = cluster_metadata.offset;
|
|
292
|
+
let point_count = light_cluster_count_point(cluster_metadata.counts);
|
|
293
|
+
let spot_count = light_cluster_count_spot(cluster_metadata.counts);
|
|
294
|
+
|
|
295
|
+
for (var j = 0u; j < point_count; j++) {
|
|
296
|
+
let light_index = cluster_data[cluster_offset + j];
|
|
297
|
+
var direct_light = get_point_light_info_by_index(&light_data, light_index, position_ws);
|
|
298
|
+
|
|
299
|
+
if (all(direct_light.color == vec3(0.0))) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let u = dot(direct_light.direction, view_ray.direction);
|
|
304
|
+
|
|
305
|
+
// .direction points TOWARD the light; march the optical-depth ray toward the light (+direction).
|
|
306
|
+
let shadow_ray = ${RAY_STRUCT.make({
|
|
307
|
+
origin: "position_ws",
|
|
308
|
+
direction: "direct_light.direction",
|
|
309
|
+
tmax: "direct_light.distance",
|
|
310
|
+
})};
|
|
311
|
+
|
|
312
|
+
let optical_depth = integrate_optical_depth(shadow_ray);
|
|
313
|
+
|
|
314
|
+
let ms = calculate_multiscattering(
|
|
315
|
+
optical_depth,
|
|
316
|
+
participating_media_scattering,
|
|
317
|
+
participating_media_extinction,
|
|
318
|
+
u,
|
|
319
|
+
participating_media_phase_g,
|
|
320
|
+
volumetrics_metadata.ms_octave_count,
|
|
321
|
+
volumetrics_metadata.ms_extinction_decay
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
// Before this, integrate_optical_depth was the ONLY thing occluding a local light:
|
|
325
|
+
// the medium shadowed itself and geometry did not shadow it at all, so a torch behind a
|
|
326
|
+
// wall lit the fog through the wall and a light through a window cast no shaft. The
|
|
327
|
+
// directional loop above has always multiplied its shadow map in; this is the same
|
|
328
|
+
// operation for the clustered lights, which is what Frostbite and UE both do in the
|
|
329
|
+
// froxel pass. One nearest atlas tap rather than the deferred path's filter kernel —
|
|
330
|
+
// see the chunk for why that is not a compromise here.
|
|
331
|
+
let shadow_term = volumetrics_point_light_shadow(&light_data, light_index, position_ws);
|
|
332
|
+
|
|
333
|
+
inScatteringSum += shadow_term * ms * direct_light.color;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
for (var k = 0u; k < spot_count; k++) {
|
|
337
|
+
let light_index = cluster_data[cluster_offset + point_count + k];
|
|
338
|
+
var direct_light = get_spot_light_info_by_index(&light_data, light_index, position_ws);
|
|
339
|
+
|
|
340
|
+
if (all(direct_light.color == vec3(0.0))) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
let u = dot(direct_light.direction, view_ray.direction);
|
|
345
|
+
|
|
346
|
+
// .direction points TOWARD the light; march the optical-depth ray toward the light (+direction).
|
|
347
|
+
let shadow_ray = ${RAY_STRUCT.make({
|
|
348
|
+
origin: "position_ws",
|
|
349
|
+
direction: "direct_light.direction",
|
|
350
|
+
tmax: "direct_light.distance",
|
|
351
|
+
})};
|
|
352
|
+
|
|
353
|
+
let optical_depth = integrate_optical_depth(shadow_ray);
|
|
354
|
+
|
|
355
|
+
let ms = calculate_multiscattering(
|
|
356
|
+
optical_depth,
|
|
357
|
+
participating_media_scattering,
|
|
358
|
+
participating_media_extinction,
|
|
359
|
+
u,
|
|
360
|
+
participating_media_phase_g,
|
|
361
|
+
volumetrics_metadata.ms_octave_count,
|
|
362
|
+
volumetrics_metadata.ms_extinction_decay
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
// see the point loop above
|
|
366
|
+
let shadow_term = volumetrics_spot_light_shadow(&light_data, light_index, position_ws);
|
|
367
|
+
|
|
368
|
+
inScatteringSum += shadow_term * ms * direct_light.color;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
var inScattering = inScatteringSum / f32(SAMPLE_COUNT);
|
|
374
|
+
|
|
375
|
+
// .a carries the mono extinction coefficient so the aerial pass can read a temporally-stable
|
|
376
|
+
// sigma_t (after the 3D TAA) instead of re-sampling the raw per-frame-jittered PM extinction.
|
|
377
|
+
// The composited fog transmittance is already mono (rgb_to_luminance of the integrated
|
|
378
|
+
// throughput), so collapsing extinction to luminance only drops the subtle chromatic
|
|
379
|
+
// depth-attenuation of the in-scatter.
|
|
380
|
+
let extinction = extinctionSum / f32(SAMPLE_COUNT);
|
|
381
|
+
|
|
382
|
+
textureStore(tLighting, voxel_coord, vec4<f32>(inScattering, extinction));
|
|
383
|
+
}
|
|
384
|
+
`, [
|
|
385
|
+
chunk_cluster_depth_from_z_slice,
|
|
386
|
+
chunk_cluster_depth_to_z_slice,
|
|
387
|
+
chunk_texel_coordinate_to_uv,
|
|
388
|
+
chunk_camera_ray_from_uv,
|
|
389
|
+
chunk_camera_ray_planar_depth_scale,
|
|
390
|
+
chunk_volumetrics_froxel_content_offset,
|
|
391
|
+
chunk_uv_to_texel_coordinate,
|
|
392
|
+
|
|
393
|
+
chunk_stbn_sample_vec3,
|
|
394
|
+
|
|
395
|
+
chunk_light_cluster_metadata_by_position,
|
|
396
|
+
chunk_light_cluster_counts,
|
|
397
|
+
chunk_directional_lights_iteration_mask,
|
|
398
|
+
chunk_get_directional_light_info_by_index,
|
|
399
|
+
chunk_get_point_light_info_by_index,
|
|
400
|
+
chunk_get_spot_light_info_by_index,
|
|
401
|
+
chunk_shadowmap_get_light_visibility,
|
|
402
|
+
chunk_volumetrics_local_light_shadow,
|
|
403
|
+
chunk_sky_lut_compute_uv,
|
|
404
|
+
|
|
405
|
+
RAY_STRUCT.declaration_chunk,
|
|
406
|
+
chunk_integrate_optical_depth,
|
|
407
|
+
chunk_volumetrics_sun_optical_depth,
|
|
408
|
+
chunk_calculate_multiscattering,
|
|
409
|
+
chunk_rgb_to_luminance,
|
|
410
|
+
chunk_volumetrics_column_jitter,
|
|
411
|
+
]
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
export const shader_volumetrics_build_lighting = ComputeShader.from({
|
|
415
|
+
label: "Volumetrics / build lighting",
|
|
416
|
+
resources,
|
|
417
|
+
body
|
|
418
|
+
})
|