@woosh/meep-engine 3.64.0 → 3.64.1
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/graphics/texture/sampler/exr_to_sampler2d.d.ts +27 -0
- package/src/engine/graphics/texture/sampler/exr_to_sampler2d.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/exr_to_sampler2d.js +91 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_exr.d.ts +23 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_exr.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_exr.js +64 -0
- package/src/format/image/exr/ExrCompression.d.ts +22 -0
- package/src/format/image/exr/ExrCompression.d.ts.map +1 -0
- package/src/format/image/exr/ExrCompression.js +27 -0
- package/src/format/image/exr/ExrImage.d.ts +32 -0
- package/src/format/image/exr/ExrImage.d.ts.map +1 -0
- package/src/format/image/exr/ExrImage.js +32 -0
- package/src/format/image/exr/ExrPixelType.d.ts +13 -0
- package/src/format/image/exr/ExrPixelType.d.ts.map +1 -0
- package/src/format/image/exr/ExrPixelType.js +18 -0
- package/src/format/image/exr/exr_compare_names.d.ts +16 -0
- package/src/format/image/exr/exr_compare_names.d.ts.map +1 -0
- package/src/format/image/exr/exr_compare_names.js +25 -0
- package/src/format/image/exr/exr_constants.d.ts +49 -0
- package/src/format/image/exr/exr_constants.d.ts.map +1 -0
- package/src/format/image/exr/exr_constants.js +56 -0
- package/src/format/image/exr/exr_read.d.ts +32 -0
- package/src/format/image/exr/exr_read.d.ts.map +1 -0
- package/src/format/image/exr/exr_read.js +531 -0
- package/src/format/image/exr/exr_sample_bits.d.ts +16 -0
- package/src/format/image/exr/exr_sample_bits.d.ts.map +1 -0
- package/src/format/image/exr/exr_sample_bits.js +21 -0
- package/src/format/image/exr/exr_scanlines_per_chunk.d.ts +17 -0
- package/src/format/image/exr/exr_scanlines_per_chunk.d.ts.map +1 -0
- package/src/format/image/exr/exr_scanlines_per_chunk.js +31 -0
- package/src/format/image/exr/exr_write.d.ts +27 -0
- package/src/format/image/exr/exr_write.d.ts.map +1 -0
- package/src/format/image/exr/exr_write.js +378 -0
- package/src/shade/playground/probe_clipmap/index.html +5 -0
- package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap/main.js +34 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +3 -15
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +4 -17
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +3 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +15 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +7 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +28 -17
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +18 -18
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +44 -48
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +8 -0
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +21 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_accumulate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js"],"names":[],"mappings":"AA+CA;;GAEG;AACH,wCAFU,YAAY,CAmBQ;
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_accumulate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js"],"names":[],"mappings":"AA+CA;;GAEG;AACH,wCAFU,YAAY,CAmBQ;AAwB9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,8CAFU,aAAa,CAgUpB;6BAlc0B,sCAAsC;8BAJrC,kCAAkC"}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
PROBE_RAY_STRUCT,
|
|
30
30
|
PROBE_RAY_SUMS_READ_RESOURCE,
|
|
31
31
|
PROBE_RAYS_READ_RESOURCE,
|
|
32
|
+
PROBE_REQUESTS_READ_RESOURCE,
|
|
32
33
|
PROBE_RESAMPLES_READ_RESOURCE,
|
|
33
34
|
PROBE_STATES_READ_RESOURCE,
|
|
34
35
|
PROBE_TRACE_READ_RESOURCE
|
|
@@ -36,7 +37,6 @@ import {
|
|
|
36
37
|
import { chunk_probe_clipmap_resampled } from "./chunk_probe_clipmap_resampled.js";
|
|
37
38
|
import {
|
|
38
39
|
PROBE_BACK_FACE_DEPTH,
|
|
39
|
-
PROBE_CHANGE_SIGNIFICANCE,
|
|
40
40
|
PROBE_DEPTH_LIMIT,
|
|
41
41
|
PROBE_DEPTH_TEXEL_RAYS,
|
|
42
42
|
PROBE_RADIANCE_SAMPLES_LIMIT,
|
|
@@ -82,6 +82,8 @@ resources.createGroup()
|
|
|
82
82
|
.add(PROBE_RADIANCE_HISTORY_RESOURCE)
|
|
83
83
|
.add(PROBE_DEPTH_HISTORY_RESOURCE)
|
|
84
84
|
.add(PROBE_ESTIMATORS_RESOURCE)
|
|
85
|
+
// the probes' L0 blends, as their last projection left them
|
|
86
|
+
.add(PROBE_REQUESTS_READ_RESOURCE)
|
|
85
87
|
// read only where the frame re-samples (chunk_probe_clipmap_resampled)
|
|
86
88
|
.add(PROBE_RESAMPLES_READ_RESOURCE)
|
|
87
89
|
// the factor the display multiplies radiance by ahead of its tone curve, as the last frame was shown
|
|
@@ -94,9 +96,9 @@ resources.createGroup()
|
|
|
94
96
|
* `probe_maps` (`probe_clipmap_maps_words`): two words a radiance texel, rgba as half floats; then a
|
|
95
97
|
* word a radiance texel, its rays this update, resolved in the low half and back faces in the high,
|
|
96
98
|
* which classification sums; then a word a depth texel, its moments as half floats; then a word a
|
|
97
|
-
* radiance texel,
|
|
98
|
-
* `
|
|
99
|
-
*
|
|
99
|
+
* radiance texel, its estimator after the update as the probe's L0 estimator sums it
|
|
100
|
+
* (`shader_probe_clipmap_project`): its short mean less its mean and its deviation (the estimator's own,
|
|
101
|
+
* floored at the display's exposure), luminance, as half floats; nothing for a texel no ray has reached.
|
|
100
102
|
*
|
|
101
103
|
* - **A texel's rays**: on a uniform update (`PROBE_UNIFORM_PERIOD`), `probe_clipmap_texel_ray`'s. On a
|
|
102
104
|
* guided one, the run that begins at its walk position in the probe's guide, at most
|
|
@@ -114,6 +116,10 @@ resources.createGroup()
|
|
|
114
116
|
* - The mean blends by at least 1/(a+1) until the count reaches its limit: a young texel is its running
|
|
115
117
|
* mean, which the estimator's blend reduction, nothing at its seed, would otherwise hold back. Past it
|
|
116
118
|
* the estimator alone, down to 1/8192 an update on a noisy texel.
|
|
119
|
+
* - And by at least the probe's L0 blend (`PROBE_REQUEST_STRUCT`'s `blend`), its L0 estimator's catch-up
|
|
120
|
+
* after its last update: a change in the probe's whole light, which the texels' own tests, a one-ray
|
|
121
|
+
* sample's noise apiece, do not see. The texel's own catch-up stays, for light that moves without
|
|
122
|
+
* changing L0.
|
|
117
123
|
* - Samples are clipped once the variance's window has passed, when 1/(a+1) is no longer its blend:
|
|
118
124
|
* before that it holds no spread to clip to.
|
|
119
125
|
* - A texel's first sample seeds both means. A texel no ray reached keeps its history.
|
|
@@ -268,34 +274,29 @@ fn main(
|
|
|
268
274
|
let tile = index_to_grid2d(slot, settings.radiance_tiles_per_row) * (n + 2u * settings.radiance_skirt) + settings.radiance_skirt;
|
|
269
275
|
let history = select(textureLoad(probe_radiance, tile + vec2<u32>(i % n, i / n), 0), vec4<f32>(0.0), updates == 0u);
|
|
270
276
|
|
|
277
|
+
let estimator = slot * texels + i;
|
|
278
|
+
|
|
271
279
|
var texel = history;
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
// so that one bright sample is one texel's at most
|
|
275
|
-
var change = vec2<f32>(0.0);
|
|
280
|
+
// the texel's estimator, its history's until a sample is blended
|
|
281
|
+
var e = probe_accumulate_estimator(history.rgb, probe_estimators[estimator]);
|
|
276
282
|
|
|
277
283
|
if (count > 0u) {
|
|
278
284
|
// the rays, and the neighbours' re-samples where the frame took them
|
|
279
285
|
let pooled = probe_clipmap_resampled(k * texels + i, sum, count);
|
|
280
286
|
let sample = pooled.rgb / pooled.w;
|
|
281
|
-
let
|
|
287
|
+
let before = e;
|
|
282
288
|
|
|
283
|
-
|
|
289
|
+
e = multiscale_mean_seed(sample);
|
|
284
290
|
|
|
285
291
|
if (history.a > 0.0) {
|
|
286
292
|
let ramp = 1.0 / (history.a + 1.0);
|
|
287
|
-
let before = probe_accumulate_estimator(history.rgb, probe_estimators[estimator]);
|
|
288
|
-
// the estimator's own floor on the deviation, at the display's exposure
|
|
289
|
-
let deviation = rgb_to_luminance(max(multiscale_mean_deviation_floor(before.short_mean, probe_exposure.value), sqrt(max(vec3<f32>(0.0), before.variance))));
|
|
290
|
-
|
|
291
|
-
change = vec2<f32>(clamp(rgb_to_luminance(sample - history.rgb) / deviation, -${PROBE_CHANGE_SIGNIFICANCE}.0, ${PROBE_CHANGE_SIGNIFICANCE}.0), 1.0);
|
|
292
293
|
|
|
293
294
|
e = multiscale_mean_add(
|
|
294
295
|
before,
|
|
295
296
|
sample,
|
|
296
297
|
max(ramp, ${PROBE_SHORT_BLEND}),
|
|
297
298
|
max(ramp, ${PROBE_VARIANCE_BLEND}),
|
|
298
|
-
select(0.0, ramp, history.a < ${PROBE_RADIANCE_SAMPLES_LIMIT}.0),
|
|
299
|
+
max(select(0.0, ramp, history.a < ${PROBE_RADIANCE_SAMPLES_LIMIT}.0), probe_requests[slot].blend),
|
|
299
300
|
ramp <= ${PROBE_VARIANCE_BLEND},
|
|
300
301
|
probe_exposure.value,
|
|
301
302
|
);
|
|
@@ -306,13 +307,23 @@ fn main(
|
|
|
306
307
|
probe_estimators[estimator] = probe_accumulate_estimator_words(e, slot, per_probe + 2u * i, updates);
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
// the estimator as the probe's L0 estimator sums it, its deviation floored at the display's exposure as
|
|
311
|
+
// the estimator's own; nothing for a texel no ray has reached
|
|
312
|
+
var state = vec2<f32>(0.0);
|
|
313
|
+
|
|
314
|
+
if (texel.a > 0.0) {
|
|
315
|
+
let deviation = max(multiscale_mean_deviation_floor(e.short_mean, probe_exposure.value), sqrt(max(vec3<f32>(0.0), e.variance)));
|
|
316
|
+
|
|
317
|
+
state = vec2<f32>(rgb_to_luminance(e.short_mean - e.mean), rgb_to_luminance(deviation));
|
|
318
|
+
}
|
|
319
|
+
|
|
309
320
|
// the count is whole, which any noise keeps
|
|
310
321
|
let stored = f16_round_stochastic(texel, vec4<f32>(probe_accumulate_store_noise(slot, i, updates), 0.0));
|
|
311
322
|
|
|
312
323
|
probe_maps[maps + 2u * i] = pack2x16float(stored.rg);
|
|
313
324
|
probe_maps[maps + 2u * i + 1u] = pack2x16float(stored.ba);
|
|
314
325
|
probe_maps[maps + 2u * texels + i] = count | (back_faces << 16u);
|
|
315
|
-
probe_maps[maps + 3u * texels + m * m + i] = pack2x16float(
|
|
326
|
+
probe_maps[maps + 3u * texels + m * m + i] = pack2x16float(state);
|
|
316
327
|
|
|
317
328
|
return;
|
|
318
329
|
}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts
CHANGED
|
@@ -6,9 +6,10 @@ export const PROBE_PROJECT_SETTINGS: WebGPUStruct;
|
|
|
6
6
|
* Projection, rows (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.8): a thread a row of each listed probe's
|
|
7
7
|
* radiance map, dispatched through `PROBE_DISPATCH_ROWS`. It sums the row's texels, new and kept, as
|
|
8
8
|
* RGB radiance SH3, `L·Y(ω)·dω` over each texel's solid angle, so that `sh3_color_get_irradiance_at` gives
|
|
9
|
-
* E; the row's rays this update, resolved and back faces; and
|
|
10
|
-
*
|
|
11
|
-
* the probe's
|
|
9
|
+
* E; the row's rays this update, resolved and back faces; and the row's part of L0 as the texels'
|
|
10
|
+
* estimators hold it, each texel by its solid angle: their short means less their means, their deviations
|
|
11
|
+
* squared (by the solid angle squared) and their short means, luminance. One row of the probe's projection
|
|
12
|
+
* each, which the probe's pass sums.
|
|
12
13
|
*
|
|
13
14
|
* @type {ComputeShader}
|
|
14
15
|
*/
|
|
@@ -25,21 +26,20 @@ export const shader_probe_clipmap_project_rows: ComputeShader;
|
|
|
25
26
|
* radiance is nothing, so their share would read a probe inside a solid as alive. Such an update keeps
|
|
26
27
|
* the probe's kind and its back-face share.
|
|
27
28
|
*
|
|
28
|
-
* **The probe's
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* - Otherwise half what it asked for last, down to the fewest: a converged probe sips.
|
|
29
|
+
* **The probe's L0 estimator** (§8.6, §8.8): a multi-scale mean estimator (`chunk_multiscale_mean`) over the
|
|
30
|
+
* probe's whole light, L0, the solid-angle-weighted sum of its radiance texels. Its short and long means are
|
|
31
|
+
* L0 of the texels' short and long means, and its deviation the root of their deviations' sum, each by its
|
|
32
|
+
* solid angle squared, as the rows sum them; its inconsistency and blend reduction are the probe's own, in
|
|
33
|
+
* `probe_requests`. Its catch-up, the published estimator's, decides what the probe's next update takes:
|
|
34
|
+
* - **Blend**: every texel's long mean blends by at least the catch-up (`shader_probe_clipmap_accumulate`).
|
|
35
|
+
* A one-ray texel's own test sees no change under its own noise; L0 pools every texel's evidence, so a
|
|
36
|
+
* change in the probe's whole light, brighter or darker, is found where no texel can find it.
|
|
37
|
+
* - **Rays**: the next guided update asks for half what the last asked for, raised toward the most by the
|
|
38
|
+
* catch-up, and never under the fewest: a probe whose light moved asks for more, a steady one sips.
|
|
39
|
+
* - After a probe's first update the most rays, a blend of nothing and the estimator seeded as a texel's is,
|
|
40
|
+
* an inconsistency of one and no blend reduction: its slot's last owner's state is not its own.
|
|
41
|
+
* - An update whose texels hold no spread, L0's deviation nothing, leaves the estimator as it was and halves
|
|
42
|
+
* the rays.
|
|
43
43
|
*
|
|
44
44
|
* @type {ComputeShader}
|
|
45
45
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_project.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_project.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js"],"names":[],"mappings":"AAgCA;;GAEG;AACH,qCAFU,YAAY,CAmBK;AAW3B;;;;;;;;;;GAUG;AACH,gDAFU,aAAa,CAyDpB;AAcH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,2CAFU,aAAa,CA0FpB;6BArP0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { chunk_rgb_to_luminance } from "../../../shader/chunk/color/chunk_rgb_to_luminance.js";
|
|
2
|
+
import { chunk_multiscale_mean } from "../../../shader/chunk/filter/chunk_multiscale_mean.js";
|
|
1
3
|
import {
|
|
2
4
|
chunk_octahedral_solid_angle
|
|
3
5
|
} from "../../../shader/chunk/geometry/octahedron/chunk_octahedral_solid_angle.js";
|
|
@@ -26,12 +28,7 @@ import {
|
|
|
26
28
|
PROBE_STATES_STORE_RESOURCE,
|
|
27
29
|
PROBE_TRACE_READ_RESOURCE
|
|
28
30
|
} from "./chunk_probe_clipmap.js";
|
|
29
|
-
import {
|
|
30
|
-
PROBE_CHANGE_SIGNIFICANCE,
|
|
31
|
-
PROBE_RADIANCE_SAMPLES_LIMIT,
|
|
32
|
-
PROBE_THREAD_WORKGROUP_SIZE,
|
|
33
|
-
PROBE_VARIANCE_BLEND
|
|
34
|
-
} from "./PROBE_CLIPMAP.js";
|
|
31
|
+
import { PROBE_SHORT_BLEND, PROBE_THREAD_WORKGROUP_SIZE } from "./PROBE_CLIPMAP.js";
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* @type {WebGPUStruct}
|
|
@@ -68,9 +65,10 @@ row_resources.createGroup()
|
|
|
68
65
|
* Projection, rows (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.8): a thread a row of each listed probe's
|
|
69
66
|
* radiance map, dispatched through `PROBE_DISPATCH_ROWS`. It sums the row's texels, new and kept, as
|
|
70
67
|
* RGB radiance SH3, `L·Y(ω)·dω` over each texel's solid angle, so that `sh3_color_get_irradiance_at` gives
|
|
71
|
-
* E; the row's rays this update, resolved and back faces; and
|
|
72
|
-
*
|
|
73
|
-
* the probe's
|
|
68
|
+
* E; the row's rays this update, resolved and back faces; and the row's part of L0 as the texels'
|
|
69
|
+
* estimators hold it, each texel by its solid angle: their short means less their means, their deviations
|
|
70
|
+
* squared (by the solid angle squared) and their short means, luminance. One row of the probe's projection
|
|
71
|
+
* each, which the probe's pass sums.
|
|
74
72
|
*
|
|
75
73
|
* @type {ComputeShader}
|
|
76
74
|
*/
|
|
@@ -106,13 +104,15 @@ fn main(
|
|
|
106
104
|
let uv = (vec2<f32>(f32(x), f32(row)) + 0.5) * inverse;
|
|
107
105
|
let solid_angle = octahedral_solid_angle(uv, inverse);
|
|
108
106
|
let rays = probe_maps[maps + 2u * texels + i];
|
|
109
|
-
|
|
107
|
+
// the texel's estimator: its short mean less its mean, and its deviation, luminance
|
|
108
|
+
let state = unpack2x16float(probe_maps[maps + 3u * texels + settings.depth_resolution * settings.depth_resolution + i]);
|
|
110
109
|
|
|
111
110
|
sh3_color_accumulate(&row_sum.sh, light * solid_angle, sh3_basis_at(uv_octahedral_unit_decode(uv)));
|
|
112
111
|
row_sum.resolved += rays & 0xFFFFu;
|
|
113
112
|
row_sum.back_faces += rays >> 16u;
|
|
114
|
-
row_sum.
|
|
115
|
-
row_sum.
|
|
113
|
+
row_sum.gap += state.x * solid_angle;
|
|
114
|
+
row_sum.variance += state.y * state.y * solid_angle * solid_angle;
|
|
115
|
+
row_sum.level += (rgb_to_luminance(light) + state.x) * solid_angle;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
probe_projection[thread] = row_sum;
|
|
@@ -124,6 +124,7 @@ fn main(
|
|
|
124
124
|
chunk_uv_octahedral_unit_decode,
|
|
125
125
|
chunk_sh3_basis_at,
|
|
126
126
|
chunk_sh3_color_accumulate,
|
|
127
|
+
chunk_rgb_to_luminance,
|
|
127
128
|
PROBE_PROJECTION_ROW_STRUCT.declaration_chunk,
|
|
128
129
|
]),
|
|
129
130
|
});
|
|
@@ -152,21 +153,20 @@ probe_resources.createGroup()
|
|
|
152
153
|
* radiance is nothing, so their share would read a probe inside a solid as alive. Such an update keeps
|
|
153
154
|
* the probe's kind and its back-face share.
|
|
154
155
|
*
|
|
155
|
-
* **The probe's
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* - Otherwise half what it asked for last, down to the fewest: a converged probe sips.
|
|
156
|
+
* **The probe's L0 estimator** (§8.6, §8.8): a multi-scale mean estimator (`chunk_multiscale_mean`) over the
|
|
157
|
+
* probe's whole light, L0, the solid-angle-weighted sum of its radiance texels. Its short and long means are
|
|
158
|
+
* L0 of the texels' short and long means, and its deviation the root of their deviations' sum, each by its
|
|
159
|
+
* solid angle squared, as the rows sum them; its inconsistency and blend reduction are the probe's own, in
|
|
160
|
+
* `probe_requests`. Its catch-up, the published estimator's, decides what the probe's next update takes:
|
|
161
|
+
* - **Blend**: every texel's long mean blends by at least the catch-up (`shader_probe_clipmap_accumulate`).
|
|
162
|
+
* A one-ray texel's own test sees no change under its own noise; L0 pools every texel's evidence, so a
|
|
163
|
+
* change in the probe's whole light, brighter or darker, is found where no texel can find it.
|
|
164
|
+
* - **Rays**: the next guided update asks for half what the last asked for, raised toward the most by the
|
|
165
|
+
* catch-up, and never under the fewest: a probe whose light moved asks for more, a steady one sips.
|
|
166
|
+
* - After a probe's first update the most rays, a blend of nothing and the estimator seeded as a texel's is,
|
|
167
|
+
* an inconsistency of one and no blend reduction: its slot's last owner's state is not its own.
|
|
168
|
+
* - An update whose texels hold no spread, L0's deviation nothing, leaves the estimator as it was and halves
|
|
169
|
+
* the rays.
|
|
170
170
|
*
|
|
171
171
|
* @type {ComputeShader}
|
|
172
172
|
*/
|
|
@@ -201,8 +201,9 @@ fn main(
|
|
|
201
201
|
|
|
202
202
|
sum.resolved += part.resolved;
|
|
203
203
|
sum.back_faces += part.back_faces;
|
|
204
|
-
sum.
|
|
205
|
-
sum.
|
|
204
|
+
sum.gap += part.gap;
|
|
205
|
+
sum.variance += part.variance;
|
|
206
|
+
sum.level += part.level;
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
let state = probe_states[slot].x;
|
|
@@ -227,28 +228,22 @@ fn main(
|
|
|
227
228
|
probe_records[slot].sh = probe_record_sh_encode(sum.sh);
|
|
228
229
|
probe_records[slot].traced_frame = settings.frame;
|
|
229
230
|
|
|
230
|
-
// the
|
|
231
|
+
// the L0 estimator: the next update's blend and rays
|
|
231
232
|
var request = probe_requests[slot];
|
|
232
233
|
|
|
233
234
|
if (updates == 0u) {
|
|
234
|
-
// its slot's last owner's
|
|
235
|
-
request = ${PROBE_REQUEST_STRUCT.make({ rays: "settings.rays_max",
|
|
236
|
-
} else if (sum.
|
|
237
|
-
let
|
|
238
|
-
let
|
|
239
|
-
let
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
let mean = mix(request.change_mean, held, blend);
|
|
247
|
-
|
|
248
|
-
request.change_variance = mix(request.change_variance, (held - request.change_mean) * (held - mean), blend);
|
|
249
|
-
request.change_mean = mean;
|
|
250
|
-
request.changes = min(request.changes + 1u, ${PROBE_RADIANCE_SAMPLES_LIMIT}u);
|
|
251
|
-
request.rays = select(max(settings.rays_min, request.rays >> 1u), settings.rays_max, moved);
|
|
235
|
+
// seeded: its slot's last owner's state is not its own
|
|
236
|
+
request = ${PROBE_REQUEST_STRUCT.make({ rays: "settings.rays_max", blend: "0.0", inconsistency: "1.0", reduction: "0.0" })};
|
|
237
|
+
} else if (sum.variance > 0.0) {
|
|
238
|
+
let deviation = sqrt(sum.variance);
|
|
239
|
+
let relative = abs(sum.gap) / deviation;
|
|
240
|
+
let inconsistency = mix(request.inconsistency, relative, ${PROBE_SHORT_BLEND});
|
|
241
|
+
let blend = saturate(multiscale_mean_catch_up(relative, inconsistency, request.reduction));
|
|
242
|
+
|
|
243
|
+
request.reduction = mix(request.reduction, multiscale_mean_blend_reduction(sum.level / deviation), MULTISCALE_MEAN_REDUCTION_BLEND);
|
|
244
|
+
request.inconsistency = inconsistency;
|
|
245
|
+
request.blend = blend;
|
|
246
|
+
request.rays = max(settings.rays_min, u32(round(mix(f32(request.rays >> 1u), f32(settings.rays_max), blend))));
|
|
252
247
|
} else {
|
|
253
248
|
request.rays = max(settings.rays_min, request.rays >> 1u);
|
|
254
249
|
}
|
|
@@ -259,6 +254,7 @@ fn main(
|
|
|
259
254
|
chunk_probe_clipmap,
|
|
260
255
|
chunk_probe_clipmap_guide,
|
|
261
256
|
chunk_folded_workgroup_index,
|
|
257
|
+
chunk_multiscale_mean,
|
|
262
258
|
PROBE_PROJECTION_ROW_STRUCT.declaration_chunk,
|
|
263
259
|
PROBE_REQUEST_STRUCT.declaration_chunk,
|
|
264
260
|
]),
|
|
@@ -8,8 +8,16 @@
|
|
|
8
8
|
* fn multiscale_mean_seed(sample: vec3f) -> MultiscaleMean
|
|
9
9
|
* fn multiscale_mean_add(e: MultiscaleMean, sample: vec3f, short_blend: f32, variance_blend: f32, mean_blend_min: f32, clip: bool, exposure: f32) -> MultiscaleMean
|
|
10
10
|
* fn multiscale_mean_deviation_floor(short_mean: vec3f, exposure: f32) -> vec3f
|
|
11
|
+
* fn multiscale_mean_catch_up(relative: f32, inconsistency: f32, reduction: f32) -> f32
|
|
12
|
+
* fn multiscale_mean_blend_reduction(level: f32) -> f32
|
|
13
|
+
* const MULTISCALE_MEAN_REDUCTION_BLEND: f32
|
|
11
14
|
* ```
|
|
12
15
|
*
|
|
16
|
+
* `multiscale_mean_catch_up` and `multiscale_mean_blend_reduction` are the long mean's decision alone, for an
|
|
17
|
+
* estimator over a quantity the caller keeps the means of itself: `relative` the means' gap over the deviation,
|
|
18
|
+
* `inconsistency` its smoothed history, `reduction` the blend reduction as it stood before this sample, and `level`
|
|
19
|
+
* the short mean over the deviation. The reduction follows `level`'s by `MULTISCALE_MEAN_REDUCTION_BLEND` a sample.
|
|
20
|
+
*
|
|
13
21
|
* `MultiscaleMean` is {@link MULTISCALE_MEAN_STRUCT}.
|
|
14
22
|
*
|
|
15
23
|
* - **Exposure**: the factor the display multiplies the samples by ahead of its tone curve, Unreal Engine's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk_multiscale_mean.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"chunk_multiscale_mean.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,oCAFU,SAAS,CAiEZ;0BAlImB,6BAA6B"}
|
|
@@ -16,8 +16,16 @@ const EXPOSURE_MAX = '1.70141183e38';
|
|
|
16
16
|
* fn multiscale_mean_seed(sample: vec3f) -> MultiscaleMean
|
|
17
17
|
* fn multiscale_mean_add(e: MultiscaleMean, sample: vec3f, short_blend: f32, variance_blend: f32, mean_blend_min: f32, clip: bool, exposure: f32) -> MultiscaleMean
|
|
18
18
|
* fn multiscale_mean_deviation_floor(short_mean: vec3f, exposure: f32) -> vec3f
|
|
19
|
+
* fn multiscale_mean_catch_up(relative: f32, inconsistency: f32, reduction: f32) -> f32
|
|
20
|
+
* fn multiscale_mean_blend_reduction(level: f32) -> f32
|
|
21
|
+
* const MULTISCALE_MEAN_REDUCTION_BLEND: f32
|
|
19
22
|
* ```
|
|
20
23
|
*
|
|
24
|
+
* `multiscale_mean_catch_up` and `multiscale_mean_blend_reduction` are the long mean's decision alone, for an
|
|
25
|
+
* estimator over a quantity the caller keeps the means of itself: `relative` the means' gap over the deviation,
|
|
26
|
+
* `inconsistency` its smoothed history, `reduction` the blend reduction as it stood before this sample, and `level`
|
|
27
|
+
* the short mean over the deviation. The reduction follows `level`'s by `MULTISCALE_MEAN_REDUCTION_BLEND` a sample.
|
|
28
|
+
*
|
|
21
29
|
* `MultiscaleMean` is {@link MULTISCALE_MEAN_STRUCT}.
|
|
22
30
|
*
|
|
23
31
|
* - **Exposure**: the factor the display multiplies the samples by ahead of its tone curve, Unreal Engine's
|
|
@@ -79,6 +87,16 @@ fn multiscale_mean_deviation_floor(short_mean: vec3f, exposure: f32) -> vec3f {
|
|
|
79
87
|
return max(vec3f(sqrt(1e-5) / multiscale_mean_exposure(exposure)), max(abs(short_mean) * exp2(-10.0), vec3f(exp2(-24.0))));
|
|
80
88
|
}
|
|
81
89
|
|
|
90
|
+
const MULTISCALE_MEAN_REDUCTION_BLEND: f32 = 0.1;
|
|
91
|
+
|
|
92
|
+
fn multiscale_mean_catch_up(relative: f32, inconsistency: f32, reduction: f32) -> f32 {
|
|
93
|
+
return clamp(smoothstep(0.0, 1.0, relative * max(0.02, inconsistency - 0.2)), 1.0 / 256.0, 1.0) * reduction;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fn multiscale_mean_blend_reduction(level: f32) -> f32 {
|
|
97
|
+
return clamp(0.5 * level, 1.0 / 32.0, 1.0);
|
|
98
|
+
}
|
|
99
|
+
|
|
82
100
|
fn multiscale_mean_add(e: ${MULTISCALE_MEAN_STRUCT.wgsl_ref}, sample: vec3f, short_blend: f32, variance_blend: f32, mean_blend_min: f32, clip: bool, exposure: f32) -> ${MULTISCALE_MEAN_STRUCT.wgsl_ref} {
|
|
83
101
|
var y = sample;
|
|
84
102
|
|
|
@@ -95,15 +113,15 @@ fn multiscale_mean_add(e: ${MULTISCALE_MEAN_STRUCT.wgsl_ref}, sample: vec3f, sho
|
|
|
95
113
|
|
|
96
114
|
let relative = rgb_to_luminance(abs(e.mean - short_mean) / deviation);
|
|
97
115
|
let inconsistency = mix(e.inconsistency, relative, short_blend);
|
|
98
|
-
let reduction =
|
|
116
|
+
let reduction = multiscale_mean_blend_reduction(rgb_to_luminance(short_mean / deviation));
|
|
99
117
|
|
|
100
|
-
let catch_up =
|
|
118
|
+
let catch_up = multiscale_mean_catch_up(relative, inconsistency, e.reduction);
|
|
101
119
|
|
|
102
120
|
return ${MULTISCALE_MEAN_STRUCT.make({
|
|
103
121
|
mean: 'mix(e.mean, y, max(saturate(catch_up), mean_blend_min))',
|
|
104
122
|
short_mean: 'short_mean',
|
|
105
123
|
variance: 'variance',
|
|
106
|
-
reduction: 'mix(e.reduction, reduction,
|
|
124
|
+
reduction: 'mix(e.reduction, reduction, MULTISCALE_MEAN_REDUCTION_BLEND)',
|
|
107
125
|
inconsistency: 'inconsistency',
|
|
108
126
|
})};
|
|
109
127
|
}
|