@woosh/meep-engine 3.50.0 → 3.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/engine/graphics3/make_default_environment.d.ts.map +1 -1
- package/src/engine/graphics3/make_default_environment.js +11 -5
- package/src/shade/playground/particle_ecs/moonlit_environment.d.ts.map +1 -1
- package/src/shade/playground/particle_ecs/moonlit_environment.js +11 -5
- package/src/shade/playground/sh_exponential/sh_exp_playground_shaders.d.ts.map +1 -1
- package/src/shade/playground/sh_exponential/sh_exp_playground_shaders.js +3 -1
- package/src/shade/renderer/atmosphere/chunk_sample_environment_color.d.ts +3 -0
- package/src/shade/renderer/atmosphere/chunk_sample_environment_color.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_environment_color.js +11 -8
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts +6 -0
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +227 -215
- package/src/shade/renderer/deferred/SHADING_LIGHT_RESOURCE_GROUP.d.ts.map +1 -1
- package/src/shade/renderer/deferred/SHADING_LIGHT_RESOURCE_GROUP.js +2 -0
- package/src/shade/renderer/deferred/indirect/chunk_get_ibl_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/deferred/indirect/chunk_get_ibl_irradiance.js +4 -2
- package/src/shade/renderer/deferred/indirect/chunk_get_ibl_radiance.d.ts.map +1 -1
- package/src/shade/renderer/deferred/indirect/chunk_get_ibl_radiance.js +4 -2
- package/src/shade/renderer/deferred/shader_background.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_background.js +4 -2
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +3 -1
- package/src/shade/renderer/global_illumination/ibl/shader_diffuse_IBL.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/ibl/shader_diffuse_IBL.js +3 -1
- package/src/shade/renderer/global_illumination/ibl/shader_specular_IBL.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/ibl/shader_specular_IBL.js +3 -1
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.js +3 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.js +4 -2
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +44 -0
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_RESOURCE.d.ts +2 -1
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_RESOURCE.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_RESOURCE.js +3 -2
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_SAMPLER_RESOURCE.d.ts +14 -0
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_SAMPLER_RESOURCE.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/ENVIRONMENT_MAP_SAMPLER_RESOURCE.js +25 -0
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +3 -4
- package/src/shade/renderer/light/environment/octahedral_skirt_matches.d.ts +19 -0
- package/src/shade/renderer/light/environment/octahedral_skirt_matches.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/octahedral_skirt_matches.js +67 -0
- package/src/shade/renderer/light/environment/octahedral_skirt_source_texel.d.ts +16 -0
- package/src/shade/renderer/light/environment/octahedral_skirt_source_texel.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/octahedral_skirt_source_texel.js +35 -0
- package/src/shade/renderer/light/environment/resample_cube_to_octahedral.d.ts +7 -2
- package/src/shade/renderer/light/environment/resample_cube_to_octahedral.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +23 -7
- package/src/shade/renderer/light/environment/resample_equirectangular_to_octahedral.d.ts +8 -2
- package/src/shade/renderer/light/environment/resample_equirectangular_to_octahedral.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/resample_equirectangular_to_octahedral.js +24 -7
- package/src/shade/renderer/light/environment/sampler2d_octahedral_skirt_fill.d.ts +12 -0
- package/src/shade/renderer/light/environment/sampler2d_octahedral_skirt_fill.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/sampler2d_octahedral_skirt_fill.js +54 -0
- package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_environment_cells.d.ts +2 -2
- package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_environment_cells.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_environment_cells.js +5 -4
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +13 -9
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_project_environment_sh.js +3 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +3 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +3 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +3 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +3 -1
- package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.js +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +3 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts +0 -5
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.js +0 -6
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.js +4 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +3 -0
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +3 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js +1 -1
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_texel_uv.d.ts +15 -0
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_texel_uv.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_texel_uv.js +27 -0
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_uv.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_uv.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/texture/octahedral/chunk_texture_octahedral_skirt_uv.js +24 -0
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_sample_environment_map.d.ts +18 -1
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_sample_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_sample_environment_map.js +45 -27
- package/src/shade/renderer/view/GPUViewSkyContext.js +169 -169
- package/src/shade/renderer/volumetrics/NOTES.md +209 -0
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js +1 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_media_group_list.d.ts +36 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_media_group_list.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_media_group_list.js +129 -0
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +75 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_bin_participating_media.d.ts +26 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_bin_participating_media.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_bin_participating_media.js +110 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +38 -14
- 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 +9 -4
- package/src/shade/renderer/volumetrics/shader_volumetrics_split_participating_media.d.ts +31 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_split_participating_media.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_split_participating_media.js +139 -0
|
@@ -2,10 +2,28 @@ import {
|
|
|
2
2
|
chunk_sphere_probe_roughness_to_lod
|
|
3
3
|
} from "../../../../light/environment/chunk_sphere_probe_roughness_to_lod.js";
|
|
4
4
|
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
5
|
-
import {
|
|
5
|
+
import { chunk_uv_octahedral_unit_encode } from "../../geometry/octahedron/chunk_uv_octahedral_unit_encode.js";
|
|
6
|
+
import { chunk_texture_octahedral_skirt_uv } from "../octahedral/chunk_texture_octahedral_skirt_uv.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Works on
|
|
9
|
+
* Works on an octahedral-encoded pre-filtered environment map with a one-texel octahedral skirt on
|
|
10
|
+
* every level it reads (see `texture_octahedral_skirt_uv`).
|
|
11
|
+
*
|
|
12
|
+
* Trilinear as two hardware bilinear taps, one per level, blended here: each level's interior is its
|
|
13
|
+
* own size less the skirt, so one uv cannot address two levels and the sampler's own mip blend would
|
|
14
|
+
* read the coarser one up to a texel off. Most texture units filter trilinear at half the bilinear
|
|
15
|
+
* rate anyway, so the second tap costs about what the hardware blend would.
|
|
16
|
+
*
|
|
17
|
+
* Measured against the manual form this replaces (8 loads, 4 octahedral wraps a level, each wrap
|
|
18
|
+
* two integer divisions and remainders), radiance + irradiance over 1920x1080: 88 → 17 µs on an RTX
|
|
19
|
+
* 4090, 15.4 → 1.3 ms on an RDNA2 iGPU, whose integer division is emulated.
|
|
20
|
+
*
|
|
21
|
+
* Every level the roughness mapping reaches (0 to `SPHERE_PROBE_MIPMAP_LEVELS - 1`) must be at least
|
|
22
|
+
* 3 texels wide to have an interior. A level's size is the texture's halved and kept at 1 or more, as
|
|
23
|
+
* a level's extent is, so a smaller map (the renderer's 1x1 black stand-in, a test's constant) still
|
|
24
|
+
* samples at a finite uv. At the roughest level the second tap reads the level past it at weight 0; a
|
|
25
|
+
* texture without one clamps to the last level, which the weight discards just the same.
|
|
26
|
+
*
|
|
9
27
|
* @see https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/blob/1bbe66e7ea0d358e84af4471a90aa9c35b583de0/samples/hybridreflections/shaders/Common.hlsl#L118
|
|
10
28
|
* @type {CodeChunk}
|
|
11
29
|
*/
|
|
@@ -13,39 +31,39 @@ export const chunk_sample_environment_map = CodeChunk.from(
|
|
|
13
31
|
//language=WGSL
|
|
14
32
|
`
|
|
15
33
|
fn sample_environment_map(
|
|
16
|
-
tEnvironment:texture_2d<f32>,
|
|
17
|
-
|
|
34
|
+
tEnvironment: texture_2d<f32>,
|
|
35
|
+
sEnvironment: sampler,
|
|
36
|
+
direction: vec3<f32>,
|
|
18
37
|
roughness: f32
|
|
19
38
|
) -> vec3<f32> {
|
|
20
|
-
|
|
39
|
+
|
|
21
40
|
let lod = sphere_probe_roughness_to_lod(roughness);
|
|
22
|
-
|
|
23
|
-
let lod_0 =
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
let
|
|
41
|
+
|
|
42
|
+
let lod_0 = floor(lod);
|
|
43
|
+
let level_0 = u32(lod_0);
|
|
44
|
+
|
|
45
|
+
let octahedral_uv = uv_octahedral_unit_encode(direction);
|
|
46
|
+
let size = textureDimensions(tEnvironment).x;
|
|
47
|
+
|
|
48
|
+
let color_0 = textureSampleLevel(
|
|
27
49
|
tEnvironment,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
direction,
|
|
50
|
+
sEnvironment,
|
|
51
|
+
texture_octahedral_skirt_uv(octahedral_uv, f32(max(size >> level_0, 1u))),
|
|
31
52
|
lod_0
|
|
32
|
-
).rgb;
|
|
33
|
-
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
let color_1 = texture_octahedral_sample_bilinear(
|
|
53
|
+
).rgb;
|
|
54
|
+
|
|
55
|
+
let color_1 = textureSampleLevel(
|
|
37
56
|
tEnvironment,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
lod_1
|
|
57
|
+
sEnvironment,
|
|
58
|
+
texture_octahedral_skirt_uv(octahedral_uv, f32(max(size >> (level_0 + 1u), 1u))),
|
|
59
|
+
lod_0 + 1.0
|
|
42
60
|
).rgb;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return mix(color_0, color_1, f);
|
|
61
|
+
|
|
62
|
+
return mix(color_0, color_1, lod - lod_0);
|
|
46
63
|
}
|
|
47
64
|
`, [
|
|
48
65
|
chunk_sphere_probe_roughness_to_lod,
|
|
49
|
-
|
|
66
|
+
chunk_uv_octahedral_unit_encode,
|
|
67
|
+
chunk_texture_octahedral_skirt_uv,
|
|
50
68
|
]
|
|
51
|
-
);
|
|
69
|
+
);
|
|
@@ -1,170 +1,170 @@
|
|
|
1
|
-
import { m3_cm_compose_transform } from "../../../core/geom/mat3/m3_cm_compose_transform.js";
|
|
2
|
-
import { FrameGraph } from "../../../engine/graphics/render/frame_graph/FrameGraph.js";
|
|
3
|
-
import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
|
|
4
|
-
import sampler2d_to_html_canvas
|
|
5
|
-
from "../../../engine/graphics/texture/sampler/sampler2d_to_html_canvas.js";
|
|
6
|
-
import { writeCssTransformMatrix } from "../../../view/writeCssTransformMatrix.js";
|
|
7
|
-
import { TextureResourceDescriptor } from "../../device/graph/TextureResourceDescriptor.js";
|
|
8
|
-
import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
|
|
9
|
-
import { SPHERE_PROBE_MIPMAP_LEVELS } from "../light/environment/DEFINES.js";
|
|
10
|
-
import { graph_filter_environment_map } from "../light/environment/graph_filter_environment_map.js";
|
|
11
|
-
import { shader_sky_irradiance_lut } from "../atmosphere/shader_sky_irradiance_lut.js";
|
|
12
|
-
import { graph_image_pass } from "../shader/graph/graph_image_pass.js";
|
|
13
|
-
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
14
|
-
import { sampler_linear_to_sRGB } from "../texture/sampler_linear_to_sRGB.js";
|
|
15
|
-
|
|
16
|
-
let debug_counter = 0;
|
|
17
|
-
|
|
18
|
-
export class GPUViewSkyContext {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @type {GraphicsContext}
|
|
23
|
-
*/
|
|
24
|
-
#graphics;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @type {GPUTextureContext}
|
|
28
|
-
*/
|
|
29
|
-
#lut_sky;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
* @returns {GPUTextureContext}
|
|
35
|
-
*/
|
|
36
|
-
get irradiance_lut() {
|
|
37
|
-
return this.#lut_sky;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
* @param {GraphicsContext} graphics
|
|
43
|
-
*/
|
|
44
|
-
constructor(graphics) {
|
|
45
|
-
this.#graphics = graphics;
|
|
46
|
-
|
|
47
|
-
const device = graphics.device;
|
|
48
|
-
|
|
49
|
-
this.#lut_sky = new GPUTextureContext(device);
|
|
50
|
-
this.#lut_sky.descriptor.label = "Sky / Irradiance LUT";
|
|
51
|
-
this.#lut_sky.descriptor.format = "rgba16float";
|
|
52
|
-
this.#lut_sky.descriptor.mipLevelCount = SPHERE_PROBE_MIPMAP_LEVELS;
|
|
53
|
-
this.#lut_sky.descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT
|
|
54
|
-
| GPUTextureUsage.TEXTURE_BINDING
|
|
55
|
-
| GPUTextureUsage.STORAGE_BINDING
|
|
56
|
-
| GPUTextureUsage.COPY_SRC
|
|
57
|
-
;
|
|
58
|
-
this.#lut_sky.resize(
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
#needs_update = true;
|
|
63
|
-
|
|
64
|
-
set needs_update(v) {
|
|
65
|
-
if (v) {
|
|
66
|
-
this.#needs_update = true;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
*
|
|
72
|
-
* @param {GPUCameraContext} camera
|
|
73
|
-
* @param {GPUSceneContext} scene
|
|
74
|
-
*/
|
|
75
|
-
update(camera, scene) {
|
|
76
|
-
|
|
77
|
-
if (!this.#needs_update) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.#needs_update = false;
|
|
82
|
-
|
|
83
|
-
// ensure base sky LUTs are up-to-date
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
86
|
-
* @type {GPUSky}
|
|
87
|
-
*/
|
|
88
|
-
const scene_sky = scene.sky;
|
|
89
|
-
scene_sky.update();
|
|
90
|
-
|
|
91
|
-
const graph = new FrameGraph("sky update");
|
|
92
|
-
|
|
93
|
-
const command_ctx = ShadeGPUCommandContext.create(
|
|
94
|
-
this.#graphics,
|
|
95
|
-
"Renderer/main"
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const gr_transmittance = graph.import_resource("transmittance", TextureResourceDescriptor.fromTexture(scene_sky.lut_transmittance.gpu_texture), scene_sky.lut_transmittance);
|
|
99
|
-
const gr_multiscatter = graph.import_resource("multiscatter", TextureResourceDescriptor.fromTexture(scene_sky.lut_multiple_scattering.gpu_texture), scene_sky.lut_multiple_scattering);
|
|
100
|
-
const gr_sky = graph.import_resource("sky_irradiance", TextureResourceDescriptor.fromTexture(this.#lut_sky.gpu_texture), this.#lut_sky);
|
|
101
|
-
|
|
102
|
-
let [out] = graph_image_pass({
|
|
103
|
-
graph,
|
|
104
|
-
shader: shader_sky_irradiance_lut,
|
|
105
|
-
inputs: {
|
|
106
|
-
camera: camera.buffer,
|
|
107
|
-
|
|
108
|
-
light_data: scene.lights.buffer_data,
|
|
109
|
-
|
|
110
|
-
tSkyLutTransmittance: gr_transmittance,
|
|
111
|
-
tSkyLutMultiscatter: gr_multiscatter
|
|
112
|
-
},
|
|
113
|
-
output: [gr_sky]
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// convolve
|
|
117
|
-
out = graph_filter_environment_map({
|
|
118
|
-
graph,
|
|
119
|
-
map: out
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
command_ctx.encodeGraph(graph);
|
|
123
|
-
|
|
124
|
-
command_ctx.finish();
|
|
125
|
-
|
|
126
|
-
debug_counter++;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// this.debug(3);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async debug(mip = 0) {
|
|
133
|
-
if (this.__debug_waiting) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
this.__debug_waiting = true;
|
|
138
|
-
|
|
139
|
-
const texture = this.#lut_sky;
|
|
140
|
-
|
|
141
|
-
const data = await texture.download(mip);
|
|
142
|
-
|
|
143
|
-
const s = new Sampler2D(data, 4, texture.size[0] >> mip, texture.size[1] >> mip);
|
|
144
|
-
sampler_linear_to_sRGB(s);
|
|
145
|
-
|
|
146
|
-
const canvas = sampler2d_to_html_canvas(s, 255, 0, this.__debug_canvas);
|
|
147
|
-
|
|
148
|
-
if (this.__debug_canvas === undefined) {
|
|
149
|
-
|
|
150
|
-
canvas.style.zIndex = "100";
|
|
151
|
-
canvas.style.position = "absolute";
|
|
152
|
-
canvas.style.bottom = `${32}px`;
|
|
153
|
-
canvas.style.right = `${32}px`;
|
|
154
|
-
|
|
155
|
-
const transform = new Float32Array(9);
|
|
156
|
-
m3_cm_compose_transform(transform, 0, 0, 1, -1, 0, 0, 0);
|
|
157
|
-
writeCssTransformMatrix(transform, canvas);
|
|
158
|
-
|
|
159
|
-
document.body.appendChild(canvas);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.__debug_canvas = canvas;
|
|
163
|
-
|
|
164
|
-
this.__debug_waiting = false;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
destroy() {
|
|
168
|
-
this.#lut_sky.destroy();
|
|
169
|
-
}
|
|
1
|
+
import { m3_cm_compose_transform } from "../../../core/geom/mat3/m3_cm_compose_transform.js";
|
|
2
|
+
import { FrameGraph } from "../../../engine/graphics/render/frame_graph/FrameGraph.js";
|
|
3
|
+
import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
|
|
4
|
+
import sampler2d_to_html_canvas
|
|
5
|
+
from "../../../engine/graphics/texture/sampler/sampler2d_to_html_canvas.js";
|
|
6
|
+
import { writeCssTransformMatrix } from "../../../view/writeCssTransformMatrix.js";
|
|
7
|
+
import { TextureResourceDescriptor } from "../../device/graph/TextureResourceDescriptor.js";
|
|
8
|
+
import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
|
|
9
|
+
import { SPHERE_PROBE_MIPMAP_LEVELS } from "../light/environment/DEFINES.js";
|
|
10
|
+
import { graph_filter_environment_map } from "../light/environment/graph_filter_environment_map.js";
|
|
11
|
+
import { SKY_IRRADIANCE_LUT_RESOLUTION, shader_sky_irradiance_lut } from "../atmosphere/shader_sky_irradiance_lut.js";
|
|
12
|
+
import { graph_image_pass } from "../shader/graph/graph_image_pass.js";
|
|
13
|
+
import { GPUTextureContext } from "../texture/GPUTextureContext.js";
|
|
14
|
+
import { sampler_linear_to_sRGB } from "../texture/sampler_linear_to_sRGB.js";
|
|
15
|
+
|
|
16
|
+
let debug_counter = 0;
|
|
17
|
+
|
|
18
|
+
export class GPUViewSkyContext {
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @type {GraphicsContext}
|
|
23
|
+
*/
|
|
24
|
+
#graphics;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @type {GPUTextureContext}
|
|
28
|
+
*/
|
|
29
|
+
#lut_sky;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @returns {GPUTextureContext}
|
|
35
|
+
*/
|
|
36
|
+
get irradiance_lut() {
|
|
37
|
+
return this.#lut_sky;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param {GraphicsContext} graphics
|
|
43
|
+
*/
|
|
44
|
+
constructor(graphics) {
|
|
45
|
+
this.#graphics = graphics;
|
|
46
|
+
|
|
47
|
+
const device = graphics.device;
|
|
48
|
+
|
|
49
|
+
this.#lut_sky = new GPUTextureContext(device);
|
|
50
|
+
this.#lut_sky.descriptor.label = "Sky / Irradiance LUT";
|
|
51
|
+
this.#lut_sky.descriptor.format = "rgba16float";
|
|
52
|
+
this.#lut_sky.descriptor.mipLevelCount = SPHERE_PROBE_MIPMAP_LEVELS;
|
|
53
|
+
this.#lut_sky.descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT
|
|
54
|
+
| GPUTextureUsage.TEXTURE_BINDING
|
|
55
|
+
| GPUTextureUsage.STORAGE_BINDING
|
|
56
|
+
| GPUTextureUsage.COPY_SRC
|
|
57
|
+
;
|
|
58
|
+
this.#lut_sky.resize(SKY_IRRADIANCE_LUT_RESOLUTION, SKY_IRRADIANCE_LUT_RESOLUTION);
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#needs_update = true;
|
|
63
|
+
|
|
64
|
+
set needs_update(v) {
|
|
65
|
+
if (v) {
|
|
66
|
+
this.#needs_update = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @param {GPUCameraContext} camera
|
|
73
|
+
* @param {GPUSceneContext} scene
|
|
74
|
+
*/
|
|
75
|
+
update(camera, scene) {
|
|
76
|
+
|
|
77
|
+
if (!this.#needs_update) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.#needs_update = false;
|
|
82
|
+
|
|
83
|
+
// ensure base sky LUTs are up-to-date
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
* @type {GPUSky}
|
|
87
|
+
*/
|
|
88
|
+
const scene_sky = scene.sky;
|
|
89
|
+
scene_sky.update();
|
|
90
|
+
|
|
91
|
+
const graph = new FrameGraph("sky update");
|
|
92
|
+
|
|
93
|
+
const command_ctx = ShadeGPUCommandContext.create(
|
|
94
|
+
this.#graphics,
|
|
95
|
+
"Renderer/main"
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const gr_transmittance = graph.import_resource("transmittance", TextureResourceDescriptor.fromTexture(scene_sky.lut_transmittance.gpu_texture), scene_sky.lut_transmittance);
|
|
99
|
+
const gr_multiscatter = graph.import_resource("multiscatter", TextureResourceDescriptor.fromTexture(scene_sky.lut_multiple_scattering.gpu_texture), scene_sky.lut_multiple_scattering);
|
|
100
|
+
const gr_sky = graph.import_resource("sky_irradiance", TextureResourceDescriptor.fromTexture(this.#lut_sky.gpu_texture), this.#lut_sky);
|
|
101
|
+
|
|
102
|
+
let [out] = graph_image_pass({
|
|
103
|
+
graph,
|
|
104
|
+
shader: shader_sky_irradiance_lut,
|
|
105
|
+
inputs: {
|
|
106
|
+
camera: camera.buffer,
|
|
107
|
+
|
|
108
|
+
light_data: scene.lights.buffer_data,
|
|
109
|
+
|
|
110
|
+
tSkyLutTransmittance: gr_transmittance,
|
|
111
|
+
tSkyLutMultiscatter: gr_multiscatter
|
|
112
|
+
},
|
|
113
|
+
output: [gr_sky]
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// convolve
|
|
117
|
+
out = graph_filter_environment_map({
|
|
118
|
+
graph,
|
|
119
|
+
map: out
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
command_ctx.encodeGraph(graph);
|
|
123
|
+
|
|
124
|
+
command_ctx.finish();
|
|
125
|
+
|
|
126
|
+
debug_counter++;
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// this.debug(3);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async debug(mip = 0) {
|
|
133
|
+
if (this.__debug_waiting) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.__debug_waiting = true;
|
|
138
|
+
|
|
139
|
+
const texture = this.#lut_sky;
|
|
140
|
+
|
|
141
|
+
const data = await texture.download(mip);
|
|
142
|
+
|
|
143
|
+
const s = new Sampler2D(data, 4, texture.size[0] >> mip, texture.size[1] >> mip);
|
|
144
|
+
sampler_linear_to_sRGB(s);
|
|
145
|
+
|
|
146
|
+
const canvas = sampler2d_to_html_canvas(s, 255, 0, this.__debug_canvas);
|
|
147
|
+
|
|
148
|
+
if (this.__debug_canvas === undefined) {
|
|
149
|
+
|
|
150
|
+
canvas.style.zIndex = "100";
|
|
151
|
+
canvas.style.position = "absolute";
|
|
152
|
+
canvas.style.bottom = `${32}px`;
|
|
153
|
+
canvas.style.right = `${32}px`;
|
|
154
|
+
|
|
155
|
+
const transform = new Float32Array(9);
|
|
156
|
+
m3_cm_compose_transform(transform, 0, 0, 1, -1, 0, 0, 0);
|
|
157
|
+
writeCssTransformMatrix(transform, canvas);
|
|
158
|
+
|
|
159
|
+
document.body.appendChild(canvas);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.__debug_canvas = canvas;
|
|
163
|
+
|
|
164
|
+
this.__debug_waiting = false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
destroy() {
|
|
168
|
+
this.#lut_sky.destroy();
|
|
169
|
+
}
|
|
170
170
|
}
|
|
@@ -1118,3 +1118,212 @@ uniform wind of zero). On the software device, the froxel build dispatches the u
|
|
|
1118
1118
|
scene with no fluid and the full one when the field has a cascade, judged by the module it was
|
|
1119
1119
|
handed (red against a pass that never and one that always picks it). Driver: `wfu_*` in session
|
|
1120
1120
|
f2a32857's scratchpad, a one-off, adapted from the GPU fluid session's `s3g_*`.
|
|
1121
|
+
|
|
1122
|
+
## The media build walks its workgroup's volumes, pre-culled by a bin — measured on the iGPU, 2026-10-17
|
|
1123
|
+
|
|
1124
|
+
`shader_volumetrics_build_participating_media` walked every volume of the scene from every froxel.
|
|
1125
|
+
Each volume cost a plane transform and a six-plane box test even where it was nowhere near the
|
|
1126
|
+
froxel, and on a modest GPU that was the pass. On the box's AMD RDNA2 iGPU (2 CUs, headless
|
|
1127
|
+
Chrome, `--use-adapter-luid`) at 1898×982, small volumes placed beyond the far plane, where no
|
|
1128
|
+
froxel can reach them, cost the build **0.78 ms each**:
|
|
1129
|
+
|
|
1130
|
+
| volumes beyond the far plane | 0 | 16 | 64 | 256 |
|
|
1131
|
+
|---|---|---|---|---|
|
|
1132
|
+
| build participating media (ms) | 7.78 | 20.18 | 57.53 | 207.05 |
|
|
1133
|
+
|
|
1134
|
+
Lighting and TAA did not move in any arm (4.0–4.4 and 5.73–5.77 ms).
|
|
1135
|
+
|
|
1136
|
+
**Now a bin runs first.** `shader_volumetrics_bin_participating_media` dispatches one 64-lane
|
|
1137
|
+
workgroup per workgroup of the build (16×16 froxels × 1 slice). Its lanes take the volumes in
|
|
1138
|
+
turn, test each against the group's slab with the build's own rejection
|
|
1139
|
+
(`volumetrics_volume_in_slab`), and set the volume's bit in that group's list. The build then walks
|
|
1140
|
+
its group's list in row order. There is a list a group, a bit a volume, in a FrameGraph transient
|
|
1141
|
+
sized from the scene's volume count and cleared by the graph. A lane of the bin tests ⌈volumes /
|
|
1142
|
+
64⌉ volumes, whatever the resolution and however large a volume is.
|
|
1143
|
+
|
|
1144
|
+
**The output does not change.** A volume adds to a froxel only where its coverage is above zero,
|
|
1145
|
+
and coverage samples points inside the froxel. The group's slab holds every froxel of the group,
|
|
1146
|
+
widened a quarter froxel in xy and, in z, by the column jitter's half slice plus a quarter. So a
|
|
1147
|
+
volume that adds anything is in the list. The walk is in row order, so the sums add in the order
|
|
1148
|
+
they did. `shader_volumetrics_bin_participating_media.spec.js` runs both passes under the emulator
|
|
1149
|
+
and compares the build's bits through the bin's lists against lists holding every volume. It is red
|
|
1150
|
+
with the z widening cut to the jitter-free quarter slice (1,536 and 24 differing words), and green
|
|
1151
|
+
with it.
|
|
1152
|
+
|
|
1153
|
+
**The walk has a budget**, `VOLUMETRICS_MEDIA_GROUP_VOLUME_BUDGET` = 32, chosen. Past it a froxel
|
|
1154
|
+
drops its group's highest-indexed volumes. Before the bin the loop had no budget at all.
|
|
1155
|
+
|
|
1156
|
+
**After**, same driver, same scene, before/after/before/after in separate processes:
|
|
1157
|
+
|
|
1158
|
+
| volumes beyond the far plane | 0 | 16 | 64 | 256 | 1,024 |
|
|
1159
|
+
|---|---|---|---|---|---|
|
|
1160
|
+
| build participating media (ms) | 4.48 | 4.48 | 4.58 | 4.95 | 6.99 |
|
|
1161
|
+
| bin participating media (ms) | 0.37 | 0.37 | 0.56 | 1.15 | 3.54 |
|
|
1162
|
+
| sum, against before | 4.85 / 7.78 | 4.85 / 20.18 | 5.14 / 57.53 | 6.10 / 207.05 | 10.53 / — |
|
|
1163
|
+
|
|
1164
|
+
The two runs of each side agree to 0.01 ms. The scene's own six volumes, with nothing added, go
|
|
1165
|
+
from 7.78 to 4.85 ms. The old build was not run at 1,024; at 0.78 ms a volume it would be about
|
|
1166
|
+
0.8 s. At 1,024 the build's remaining growth is the list itself: 33 words a froxel to load.
|
|
1167
|
+
|
|
1168
|
+
The picture, by the README's protocol (45 frames settled, 16 averaged, block means of 32×32
|
|
1169
|
+
pixels): before against after reads a mean |d| of 0.117–0.156 with signed means within ±0.004,
|
|
1170
|
+
inside the floor between two processes running the *same* build (0.121 and 0.151).
|
|
1171
|
+
|
|
1172
|
+
**A defect this turned up, fixed below.** The build's Y flip negates as well as swapping
|
|
1173
|
+
(`planes[2] = -planes[3]; planes[3] = -t`), so its froxel's two Y planes face *out*. The corners
|
|
1174
|
+
`frustum_sample_point` builds are unchanged, being intersections, but `aabb3_intersects_frustum`
|
|
1175
|
+
on those planes keeps a box only when it spans the froxel's whole row. Measured on the emulator: a
|
|
1176
|
+
1×1×1 box at depth 10 covers rows 8.8–11.2 of a 20-row grid and fogs rows 9 and 10 only. The fog
|
|
1177
|
+
loses up to a row at every volume's top and bottom edge, and a volume thinner than a row is never
|
|
1178
|
+
drawn. The bin slices its slab with the planes facing in (`volumetrics_froxel_planes`: a swap, no
|
|
1179
|
+
negation). Inverted planes across a group's 16 rows rejected nearly every volume, and that is how
|
|
1180
|
+
it showed. The build keeps its arithmetic, so the output above stays byte-identical. Fixing it
|
|
1181
|
+
changes the fog.
|
|
1182
|
+
|
|
1183
|
+
**Not covered:** the aerial pass's far field, `far_sample_volumes` in
|
|
1184
|
+
`shader_volumetrics_build_scattering_lut`, still walks every volume at every march sample past
|
|
1185
|
+
`froxel_far`. With `froxel_far` at its default, the camera's far, that is only each column's last
|
|
1186
|
+
step, whose dithered depth can land past it: about one far-field sample a column a frame. The
|
|
1187
|
+
playground's `froxel_far` slider below 120 hands the whole tail to the far field, many samples a
|
|
1188
|
+
column. Measured in the same runs, at the default, the pass reads 0.40–0.47 ms with the scene's own
|
|
1189
|
+
volumes and 2.27 ms with 256 added. In the 1,024 run it reads 9.56 ms.
|
|
1190
|
+
|
|
1191
|
+
### The split ahead of the bin: a near field and a far field — measured on the iGPU, 2026-10-17
|
|
1192
|
+
|
|
1193
|
+
`shader_volumetrics_split_participating_media` runs before the bin, with one thread per volume.
|
|
1194
|
+
It drops a volume outside any of the grid's four side planes or its near plane. Those are the bin's
|
|
1195
|
+
planes, widened the same quarter froxel. The plane at `froxel_far` then sorts the rest:
|
|
1196
|
+
|
|
1197
|
+
- any part of a volume nearer than `froxel_far` puts it in the near field;
|
|
1198
|
+
- any part beyond it puts it in the far field;
|
|
1199
|
+
- a volume across it goes in both.
|
|
1200
|
+
|
|
1201
|
+
Each field is a list, a count and rows in no particular order, which the split appends to from a
|
|
1202
|
+
count of zero. The bin now tests only the near field, and the aerial pass's far field walks the
|
|
1203
|
+
far field (see "The aerial pass's far field walks the far-field list" below).
|
|
1204
|
+
|
|
1205
|
+
**The near field holds every volume the bin could keep, at the default `froxel_far`.** That
|
|
1206
|
+
default is the camera's far, where the bin's last groups end. The emulator spec runs split, bin
|
|
1207
|
+
and build together against lists holding every volume, byte for byte. It is red with the
|
|
1208
|
+
discriminator at half of `froxel_far`, and its own split cases are red with the far test's
|
|
1209
|
+
negation dropped. With `froxel_far` pulled nearer, the grid's last slice still reaches the camera's
|
|
1210
|
+
far, because its jittered slab clamps there. A volume wholly between the two now belongs to the
|
|
1211
|
+
far field alone and no longer reaches that slice. It had been counted by both until now.
|
|
1212
|
+
|
|
1213
|
+
**After**, against master (bin only), master/split/master/split in separate processes, with a third
|
|
1214
|
+
master run. Same driver, scene and 1898×982 as the section above, figures in ms:
|
|
1215
|
+
|
|
1216
|
+
| volumes beyond the far plane | 0 | 64 | 256 | 1,024 |
|
|
1217
|
+
|---|---|---|---|---|
|
|
1218
|
+
| split | 0.012–0.014 | 0.020–0.022 | 0.009–0.011 | 0.016–0.018 |
|
|
1219
|
+
| bin, master → split | 0.36–0.37 → 0.35 | 0.55–0.56 → 0.35 | 1.14–1.15 → 0.35 | 3.54 → 0.35 |
|
|
1220
|
+
| build, master → split | 4.48–4.50 → 4.17–4.18 | 4.57–4.61 → 4.29–4.31 | 4.94–4.98 → 4.69–4.71 | 7.03–7.11 → 6.87–6.95 |
|
|
1221
|
+
|
|
1222
|
+
The bin no longer grows with volumes the camera cannot see. The build's code is unchanged, yet it
|
|
1223
|
+
reads 0.3 ms less at every count. Its lists are now built from the near field only, which fits
|
|
1224
|
+
the split dropping volumes that a group's plane-by-plane test let through. That account is not
|
|
1225
|
+
verified.
|
|
1226
|
+
|
|
1227
|
+
The picture reads the same. Master against split gives a mean |d| of 0.057–0.164, with signed means
|
|
1228
|
+
within ±0.003. Two runs of the same build differ by 0.177 (master) and 0.284 (split). One master
|
|
1229
|
+
run read 1.54 against every other run, its own build's included, and is left out.
|
|
1230
|
+
|
|
1231
|
+
## The media build's Y planes face in — measured on the emulator and the iGPU, 2026-10-17
|
|
1232
|
+
|
|
1233
|
+
The build turned the metadata frustum's Y pair to the grid's rows by swapping and negating. That
|
|
1234
|
+
left both of a froxel's Y planes facing out (the defect above). It now takes the pair from
|
|
1235
|
+
`volumetrics_froxel_planes`, the same swap the bin slices its slabs with, and both planes face in.
|
|
1236
|
+
A plane and its negation meet the other planes at the same points, so the froxel's corners do not
|
|
1237
|
+
move. `frustum_sample_point`, the coverage estimate and the fade therefore read exactly what they
|
|
1238
|
+
did. Only the box test changes. It now rejects a volume only where the froxel lies wholly outside
|
|
1239
|
+
it. Before, it kept a volume only in the rows the volume spanned from top to bottom.
|
|
1240
|
+
|
|
1241
|
+
**On the emulator** (`shader_volumetrics_build_participating_media.spec.js`, a 40×20×8 grid, the
|
|
1242
|
+
bin spec's camera). Take a box 1 tall and 1 deep, across the whole view at depth 10. It projects
|
|
1243
|
+
onto rows 8.73–11.27. With its fade off, a froxel's fog is its coverage alone: the box fogged rows 9
|
|
1244
|
+
and 10, and now fogs 8 to 11, the rows it reaches. A box half a row tall across the middle of row 9,
|
|
1245
|
+
with the volume's default fade, fogged nothing and now fogs row 9. Both tests were red against the
|
|
1246
|
+
old flip (`[9, 10]` and `[]`) and are green. The bin's spec stays green against the corrected
|
|
1247
|
+
build: through the bin's lists the build still writes, bit for bit, what it writes with every volume
|
|
1248
|
+
listed.
|
|
1249
|
+
|
|
1250
|
+
**The fade hides half of what the box test dropped.** A froxel whose centre ray misses the box
|
|
1251
|
+
takes the fallback in `compute_volume_fade_factor`, the fade at the froxel's centre. Outside the
|
|
1252
|
+
box that is 0. So an edge froxel gets its fog back only when its centre ray reaches into the
|
|
1253
|
+
volume, which means only rows the volume covers past their middle. The 1×1×1 box at depth 10 with a
|
|
1254
|
+
fade of 0.25 still fogs rows 9 and 10 only: it covers rows 8 and 11 to about a quarter of their
|
|
1255
|
+
height, short of their middles. The fallback's comment calls this case "rare if coverage > 0", but
|
|
1256
|
+
at a volume's edges it is every froxel whose centre ray misses. Not changed here.
|
|
1257
|
+
|
|
1258
|
+
**In the playground, on the iGPU** (headless Chrome, `--use-adapter-luid`, 1898×982, so 119×62
|
|
1259
|
+
froxels of 16 px). Both flips ran in one page behind a temporary switch, on the bin as committed at
|
|
1260
|
+
`7f09e80b4`, before the split above; the split's spec holds the build's output byte for byte at the
|
|
1261
|
+
default `froxel_far`. By the README's protocol at each of the 11 viewpoints: old, new, old, new, each
|
|
1262
|
+
after a view change, a 45-frame settle and a 16-frame average. Each floor compares a flip with its own repeat. Mean luminance in 8-bit codes, per
|
|
1263
|
+
pixel:
|
|
1264
|
+
|
|
1265
|
+
| viewpoint | signed mean, old → new | floor, old / new | mean \|d\|, old → new | floor, old / new |
|
|
1266
|
+
|---|---|---|---|---|
|
|
1267
|
+
| Dead overview | +0.011, −0.013 | −0.000 / −0.025 | 0.162, 0.160 | 0.213 / 0.214 |
|
|
1268
|
+
| Fog bank, wide | +0.001, +0.000 | +0.001 / +0.000 | 0.303, 0.236 | 0.320 / 0.301 |
|
|
1269
|
+
| Inside the fog | +0.001, +0.002 | +0.002 / +0.003 | 0.138, 0.137 | 0.163 / 0.163 |
|
|
1270
|
+
| Island broadside | −0.007, −0.004 | +0.001 / +0.004 | 0.114, 0.124 | 0.153 / 0.168 |
|
|
1271
|
+
| Island from above | −0.008, −0.003 | −0.003 / +0.002 | 0.100, 0.093 | 0.134 / 0.124 |
|
|
1272
|
+
| Inside the cloud deck | −0.003, −0.002 | −0.003 / −0.002 | 0.081, 0.081 | 0.093 / 0.093 |
|
|
1273
|
+
| Volume edge | −0.007, −0.002 | −0.009 / −0.004 | 0.129, 0.141 | 0.185 / 0.199 |
|
|
1274
|
+
| Volume edge, above | −0.003, +0.001 | +0.006 / +0.010 | 0.130, 0.133 | 0.179 / 0.176 |
|
|
1275
|
+
| Beside the fog box | −0.003, −0.022 | +0.031 / +0.012 | 0.129, 0.131 | 0.159 / 0.158 |
|
|
1276
|
+
| Beside the fog box, deeper | +0.023, +0.023 | −0.013 / −0.013 | 0.126, 0.127 | 0.155 / 0.153 |
|
|
1277
|
+
| Under the island | +0.001, +0.002 | +0.011 / +0.013 | 0.129, 0.126 | 0.165 / 0.166 |
|
|
1278
|
+
|
|
1279
|
+
On 32×32 block means one block, in *Fog bank, wide*, moved the same way in both pairs by more
|
|
1280
|
+
than the largest block move between repeats of one flip: +0.09 and +0.07 against 0.06. No other
|
|
1281
|
+
block at any viewpoint did. The one viewpoint whose signed means agree and clear their floors,
|
|
1282
|
+
*Beside the fog box, deeper*, moves by 0.023 of a code. **The change is inside the picture's noise
|
|
1283
|
+
at every viewpoint.** The six volumes are large on screen and fade over 0.5–7 m, so a row at their
|
|
1284
|
+
edge carries little of their density. What the defect hid was fog in volumes that are thin or small
|
|
1285
|
+
on screen: one under 16 px tall here never drew at all. The floors span two captures and the
|
|
1286
|
+
signals one, so a slow drift (the noise scrolling with the wind) counts double in a floor. That is
|
|
1287
|
+
why the signals' mean |d| sits below the floors'.
|
|
1288
|
+
|
|
1289
|
+
**Cost: unchanged.** Old against new, alternating which goes first, two rounds a viewpoint: the
|
|
1290
|
+
media build reads 3.19–5.62 ms across the viewpoints, and new/old has a median of 0.998 (range
|
|
1291
|
+
0.982–1.026). More froxels at a volume's edge now run the coverage estimate, but too few to show.
|
|
1292
|
+
|
|
1293
|
+
Driver: `bench/job_flip.js` and `summarize_flip.mjs` in session b5223342's scratchpad, run by the
|
|
1294
|
+
bin session's `drive.mjs`.
|
|
1295
|
+
|
|
1296
|
+
## The aerial pass's far field walks the far-field list — measured on the iGPU, 2026-10-17
|
|
1297
|
+
|
|
1298
|
+
`far_sample_volumes` in `shader_volumetrics_build_scattering_lut` used to walk every volume of the
|
|
1299
|
+
scene at each march sample past `froxel_far`. It now walks the split's far field. The list holds
|
|
1300
|
+
every volume with some part beyond `froxel_far` and inside the grid's widened side planes. A sample
|
|
1301
|
+
on a column's view ray past `froxel_far` lies inside both, so a volume left off the list cannot
|
|
1302
|
+
contain it.
|
|
1303
|
+
|
|
1304
|
+
The list is in no particular order, so the sums round differently from frame to frame. Alex
|
|
1305
|
+
accepted that: the volumetric TAA and the final image's TAA absorb it.
|
|
1306
|
+
`shader_volumetrics_build_scattering_lut.far_field.spec.js` pins that the far field adds the
|
|
1307
|
+
volumes the list names and no others. It is red against the shader that walked every volume.
|
|
1308
|
+
|
|
1309
|
+
Master (the split, the far field unread) against this, in separate processes, at 1898×982, ms:
|
|
1310
|
+
|
|
1311
|
+
| aerial pass (`build scattering lut`) | 0 volumes added | 256 | 1,024 |
|
|
1312
|
+
|---|---|---|---|
|
|
1313
|
+
| `froxel_far` 40 m (camera far 120), master | 0.68–0.75 | 12.87–12.90 | 55.75–56.27 |
|
|
1314
|
+
| `froxel_far` 40 m, far-field list | 0.62–0.68 | 1.60–1.63 | 5.86–5.88 |
|
|
1315
|
+
| `froxel_far` at its default, master | 0.54 | 2.39 | 10.72 |
|
|
1316
|
+
| `froxel_far` at its default, far-field list | 0.63 | 0.69 | 1.13 |
|
|
1317
|
+
|
|
1318
|
+
The added volumes are the ones the earlier sections place beyond the far plane in random
|
|
1319
|
+
directions. The far field keeps only those inside the view's side planes. At the default the far
|
|
1320
|
+
field is reached only by each column's dithered last step, and the pass grew a tenth as fast to
|
|
1321
|
+
begin with. One run each at the default: its 0.09 ms at no added volumes is inside the 0.54–0.75
|
|
1322
|
+
the pass reads across all runs, and is not shown to be a cost. The media build reads the same in
|
|
1323
|
+
every arm.
|
|
1324
|
+
|
|
1325
|
+
The picture reads the same. At the default, master against list gives a mean |d| of 0.083 against
|
|
1326
|
+
floors of 0.075. At 40 m the pairs give 0.15 and 0.41, against 0.55 between the two runs of the
|
|
1327
|
+
list's own build. The first run of the batch read 1.58 against every other run, its own build's
|
|
1328
|
+
included, as one master run did in the section above. Both times it was the first run of a batch,
|
|
1329
|
+
so it is left out and taken as a property of the driver, not of either build.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VOLUMETRICS_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js"],"names":[],"mappings":"AAKA,uDA+
|
|
1
|
+
{"version":3,"file":"VOLUMETRICS_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js"],"names":[],"mappings":"AAKA,uDA+EU;6BAlFmB,gCAAgC"}
|