@woosh/meep-engine 3.63.3 → 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/CHANGELOG.md +51 -0
- package/package.json +1 -1
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts +14 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts.map +1 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.js +51 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +2 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +51 -70
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +8 -64
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts +17 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.js +64 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts +30 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts.map +1 -0
- package/src/core/math/linalg/solve_box_constrained_qp.js +205 -0
- 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/engine/physics/constraint/soft_spring_coefficients.d.ts +24 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.d.ts.map +1 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.js +38 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +16 -8
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +54 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +192 -7
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +3 -5
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +3 -5
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts +183 -12
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +1046 -121
- 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/playground/tonemap_sdr/README.md +11 -8
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +2 -2
- package/src/shade/renderer/Renderer.d.ts +5 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +15 -88
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts +14 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts.map +1 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.js +62 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +158 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.js +337 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js +15 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts +6 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js +84 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts +10 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js +25 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js +20 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts +14 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js +30 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts +54 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.js +63 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +106 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.js +474 -0
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +5 -13
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +5 -44
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts +7 -25
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js +11 -51
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts +20 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js +103 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_HDR_none.js → shader_tonemap_HDR_lut.js} +22 -18
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_LDR_aces.js → shader_tonemap_LDR_lut.js} +24 -24
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts +23 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js +92 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts +15 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js +73 -0
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -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/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +62 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +140 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js +65 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js +38 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.js +41 -0
- 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
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -8
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
- package/src/shade/renderer/ShadeToneMappingMode.d.ts +0 -15
- package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +0 -1
- package/src/shade/renderer/ShadeToneMappingMode.js +0 -41
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.js +0 -79
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +0 -17
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +0 -101
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.js +0 -71
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.js +0 -76
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts +0 -3
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.js +0 -44
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
|
]),
|
|
@@ -13,7 +13,7 @@ export class TinyGltf {
|
|
|
13
13
|
* @readonly
|
|
14
14
|
* @type {TextureFormat}
|
|
15
15
|
*/
|
|
16
|
-
static readonly "__#
|
|
16
|
+
static readonly "__#312@#UNCOMPRESSED_TARGET": TextureFormat;
|
|
17
17
|
/**
|
|
18
18
|
* @param {AssetManager} assetManager
|
|
19
19
|
* @param {AssetRequestScope} [scope]
|
|
@@ -51,7 +51,7 @@ export class NSS {
|
|
|
51
51
|
* @returns {number}
|
|
52
52
|
*/
|
|
53
53
|
static recommended_jitter_sequence_size(upscale_ratio: number): number;
|
|
54
|
-
static "__#
|
|
54
|
+
static "__#220@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
|
|
55
55
|
/**
|
|
56
56
|
* @param {GraphicsContext} graphics
|
|
57
57
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear Rec.709 (D65) to AP1 (ACES white), Bradford-adapted, as Unreal's `WorkingColorSpace.ToAP1` for an sRGB
|
|
3
|
+
* working space. Row-major.
|
|
4
|
+
* @type {Float64Array}
|
|
5
|
+
*/
|
|
6
|
+
export const M3_REC709_TO_AP1: Float64Array;
|
|
7
|
+
/**
|
|
8
|
+
* The inverse of {@link M3_REC709_TO_AP1}. Row-major.
|
|
9
|
+
* @type {Float64Array}
|
|
10
|
+
*/
|
|
11
|
+
export const M3_AP1_TO_REC709: Float64Array;
|
|
12
|
+
/**
|
|
13
|
+
* - `CRM_FROM_REC709_TO_AP1` and `CRM_FROM_AP1_TO_REC709`: {@link M3_REC709_TO_AP1} and its inverse.
|
|
14
|
+
* - `AP1_LUMINANCE`: AP1's contribution of each channel to Y, the row Unreal calls `AP1_RGB2Y`.
|
|
15
|
+
*
|
|
16
|
+
* Derived from the two spaces' chromaticities, so neither matrix is a rounded transcription of the other.
|
|
17
|
+
*
|
|
18
|
+
* @type {CodeChunk}
|
|
19
|
+
*/
|
|
20
|
+
export const chunk_CRM_REC709_AP1: CodeChunk;
|
|
21
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
22
|
+
//# sourceMappingURL=chunk_CRM_REC709_AP1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_CRM_REC709_AP1.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,+BAFU,YAAY,CAE8B;AAIpD;;;GAGG;AACH,+BAFU,YAAY,CAE8B;AAYpD;;;;;;;GAOG;AACH,mCAFU,SAAS,CASjB;0BAzDwB,gCAAgC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { m3_chromatic_adaptation_bradford } from "../../../../../../core/color/xyz/m3_chromatic_adaptation_bradford.js";
|
|
2
|
+
import { m3_rgb_to_xyz_from_primaries } from "../../../../../../core/color/xyz/m3_rgb_to_xyz_from_primaries.js";
|
|
3
|
+
import { m3_invert } from "../../../../../../core/geom/mat3/m3_invert.js";
|
|
4
|
+
import { m3_multiply } from "../../../../../../core/geom/mat3/m3_multiply.js";
|
|
5
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
6
|
+
|
|
7
|
+
const REC709_TO_XYZ = new Float64Array(9);
|
|
8
|
+
m3_rgb_to_xyz_from_primaries(REC709_TO_XYZ, [0.640, 0.330, 0.300, 0.600, 0.150, 0.060], 0.3127, 0.3290);
|
|
9
|
+
|
|
10
|
+
// ACES AP1 (ACEScg) primaries and the ACES white, S-2014-004
|
|
11
|
+
const AP1_WHITE_X = 0.32168;
|
|
12
|
+
const AP1_WHITE_Y = 0.33767;
|
|
13
|
+
const AP1_TO_XYZ = new Float64Array(9);
|
|
14
|
+
m3_rgb_to_xyz_from_primaries(AP1_TO_XYZ, [0.713, 0.293, 0.165, 0.830, 0.128, 0.044], AP1_WHITE_X, AP1_WHITE_Y);
|
|
15
|
+
|
|
16
|
+
const XYZ_TO_AP1 = new Float64Array(9);
|
|
17
|
+
m3_invert(XYZ_TO_AP1, AP1_TO_XYZ);
|
|
18
|
+
|
|
19
|
+
const D65_TO_ACES_WHITE = new Float64Array(9);
|
|
20
|
+
m3_chromatic_adaptation_bradford(D65_TO_ACES_WHITE, 0.3127, 0.3290, AP1_WHITE_X, AP1_WHITE_Y);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Linear Rec.709 (D65) to AP1 (ACES white), Bradford-adapted, as Unreal's `WorkingColorSpace.ToAP1` for an sRGB
|
|
24
|
+
* working space. Row-major.
|
|
25
|
+
* @type {Float64Array}
|
|
26
|
+
*/
|
|
27
|
+
export const M3_REC709_TO_AP1 = new Float64Array(9);
|
|
28
|
+
m3_multiply(M3_REC709_TO_AP1, D65_TO_ACES_WHITE, REC709_TO_XYZ);
|
|
29
|
+
m3_multiply(M3_REC709_TO_AP1, XYZ_TO_AP1, M3_REC709_TO_AP1);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The inverse of {@link M3_REC709_TO_AP1}. Row-major.
|
|
33
|
+
* @type {Float64Array}
|
|
34
|
+
*/
|
|
35
|
+
export const M3_AP1_TO_REC709 = new Float64Array(9);
|
|
36
|
+
m3_invert(M3_AP1_TO_REC709, M3_REC709_TO_AP1);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Float64Array} m row-major
|
|
40
|
+
* @returns {string} a WGSL `mat3x3<f32>` constructor, column by column
|
|
41
|
+
*/
|
|
42
|
+
function wgsl_mat3(m) {
|
|
43
|
+
const column = c => `vec3<f32>(${m[c]}, ${m[3 + c]}, ${m[6 + c]})`;
|
|
44
|
+
return `mat3x3<f32>(${column(0)}, ${column(1)}, ${column(2)})`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* - `CRM_FROM_REC709_TO_AP1` and `CRM_FROM_AP1_TO_REC709`: {@link M3_REC709_TO_AP1} and its inverse.
|
|
49
|
+
* - `AP1_LUMINANCE`: AP1's contribution of each channel to Y, the row Unreal calls `AP1_RGB2Y`.
|
|
50
|
+
*
|
|
51
|
+
* Derived from the two spaces' chromaticities, so neither matrix is a rounded transcription of the other.
|
|
52
|
+
*
|
|
53
|
+
* @type {CodeChunk}
|
|
54
|
+
*/
|
|
55
|
+
export const chunk_CRM_REC709_AP1 = CodeChunk.from(
|
|
56
|
+
//language=WGSL
|
|
57
|
+
`
|
|
58
|
+
const CRM_FROM_REC709_TO_AP1 = ${wgsl_mat3(M3_REC709_TO_AP1)};
|
|
59
|
+
const CRM_FROM_AP1_TO_REC709 = ${wgsl_mat3(M3_AP1_TO_REC709)};
|
|
60
|
+
const AP1_LUMINANCE = vec3<f32>(${AP1_TO_XYZ[3]}, ${AP1_TO_XYZ[4]}, ${AP1_TO_XYZ[5]});
|
|
61
|
+
`
|
|
62
|
+
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `color_grade(scene, grade, keys)`: exposed scene-linear Rec.709 through a {@link ColorGrade}, white balance, then
|
|
3
|
+
* primaries, then hue curves, to Rec.709 again, not negative. `grade` is the grade's {@link COLOR_GRADE_STRUCT} and
|
|
4
|
+
* `keys` the curves' keyframes. See `ColorGrade` for what each stage does.
|
|
5
|
+
*
|
|
6
|
+
* Also defines each stage on its own: `color_grade_primaries(ap1, grade)` and
|
|
7
|
+
* `color_grade_hue_curves(color, counts, keys)`.
|
|
8
|
+
*
|
|
9
|
+
* @type {CodeChunk}
|
|
10
|
+
*/
|
|
11
|
+
export const chunk_color_grade: CodeChunk;
|
|
12
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
13
|
+
//# sourceMappingURL=chunk_color_grade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_color_grade.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,gCAFU,SAAS,CA0HjB;0BAxIwB,gCAAgC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { ANIMATION_CURVE_KEYFRAME_STRUCT } from "../../../../animation/ANIMATION_CURVE_KEYFRAME_STRUCT.js";
|
|
2
|
+
import { chunk_animation_curve_evaluate_keys } from "../../../../animation/chunk_animation_curve_evaluate_keys.js";
|
|
3
|
+
import { COLOR_GRADE_STRUCT } from "../../../../deferred/tonemap/ColorGrade.js";
|
|
4
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
5
|
+
import { chunk_CRM_REC709_AP1 } from "../conversion/chunk_CRM_REC709_AP1.js";
|
|
6
|
+
import { chunk_linear_srgb_to_oklab } from "../oklab/chunk_linear_srgb_to_oklab.js";
|
|
7
|
+
import { chunk_oklab_compute_max_saturation } from "../oklab/chunk_oklab_compute_max_saturation.js";
|
|
8
|
+
import { chunk_oklab_to_linear_srgb } from "../oklab/chunk_oklab_to_linear_srgb.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `color_grade(scene, grade, keys)`: exposed scene-linear Rec.709 through a {@link ColorGrade}, white balance, then
|
|
12
|
+
* primaries, then hue curves, to Rec.709 again, not negative. `grade` is the grade's {@link COLOR_GRADE_STRUCT} and
|
|
13
|
+
* `keys` the curves' keyframes. See `ColorGrade` for what each stage does.
|
|
14
|
+
*
|
|
15
|
+
* Also defines each stage on its own: `color_grade_primaries(ap1, grade)` and
|
|
16
|
+
* `color_grade_hue_curves(color, counts, keys)`.
|
|
17
|
+
*
|
|
18
|
+
* @type {CodeChunk}
|
|
19
|
+
*/
|
|
20
|
+
export const chunk_color_grade = CodeChunk.from(
|
|
21
|
+
//language=WGSL
|
|
22
|
+
`
|
|
23
|
+
// Unreal's ColorCorrect: one zone's grade, in AP1
|
|
24
|
+
fn color_grade_correct(
|
|
25
|
+
color: vec3<f32>,
|
|
26
|
+
saturation: vec3<f32>,
|
|
27
|
+
contrast: vec3<f32>,
|
|
28
|
+
gamma: vec3<f32>,
|
|
29
|
+
gain: vec3<f32>,
|
|
30
|
+
offset: vec3<f32>,
|
|
31
|
+
) -> vec3<f32> {
|
|
32
|
+
let luma = dot(color, AP1_LUMINANCE);
|
|
33
|
+
|
|
34
|
+
var c = max(vec3<f32>(0.0), mix(vec3<f32>(luma), color, saturation));
|
|
35
|
+
c = pow(c * (1.0 / 0.18), contrast) * 0.18;
|
|
36
|
+
c = pow(c, 1.0 / gamma);
|
|
37
|
+
|
|
38
|
+
return c * gain + offset;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Unreal's ColorCorrectAll: the three zones, blended by luma
|
|
42
|
+
fn color_grade_primaries(ap1: vec3<f32>, grade: ${COLOR_GRADE_STRUCT.wgsl_ref}) -> vec3<f32> {
|
|
43
|
+
let luma = dot(ap1, AP1_LUMINANCE);
|
|
44
|
+
|
|
45
|
+
let shadows = color_grade_correct(
|
|
46
|
+
ap1,
|
|
47
|
+
grade.shadows_saturation.xyz, grade.shadows_contrast.xyz, grade.shadows_gamma.xyz,
|
|
48
|
+
grade.shadows_gain.xyz, grade.shadows_offset.xyz,
|
|
49
|
+
);
|
|
50
|
+
let midtones = color_grade_correct(
|
|
51
|
+
ap1,
|
|
52
|
+
grade.midtones_saturation.xyz, grade.midtones_contrast.xyz, grade.midtones_gamma.xyz,
|
|
53
|
+
grade.midtones_gain.xyz, grade.midtones_offset.xyz,
|
|
54
|
+
);
|
|
55
|
+
let highlights = color_grade_correct(
|
|
56
|
+
ap1,
|
|
57
|
+
grade.highlights_saturation.xyz, grade.highlights_contrast.xyz, grade.highlights_gamma.xyz,
|
|
58
|
+
grade.highlights_gain.xyz, grade.highlights_offset.xyz,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
let weight_shadows = 1.0 - smoothstep(0.0, grade.zone_bounds.x, luma);
|
|
62
|
+
let weight_highlights = smoothstep(grade.zone_bounds.y, grade.zone_bounds.z, luma);
|
|
63
|
+
let weight_midtones = 1.0 - weight_shadows - weight_highlights;
|
|
64
|
+
|
|
65
|
+
return shadows * weight_shadows + midtones * weight_midtones + highlights * weight_highlights;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// hue shift, chroma scale and lightness against OkLCh hue; counts.xyz are the three curves' keys, in that order
|
|
69
|
+
fn color_grade_hue_curves(
|
|
70
|
+
color: vec3<f32>,
|
|
71
|
+
counts: vec4<u32>,
|
|
72
|
+
keys: ptr<storage, array<${ANIMATION_CURVE_KEYFRAME_STRUCT.wgsl_ref}>, read>,
|
|
73
|
+
) -> vec3<f32> {
|
|
74
|
+
if (all(counts.xyz == vec3<u32>(0u))) {
|
|
75
|
+
return color;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let lab = linear_srgb_to_oklab(color);
|
|
79
|
+
let chroma = length(lab.yz);
|
|
80
|
+
|
|
81
|
+
// a grey has no hue, and every edit below leaves it where it is
|
|
82
|
+
if (chroma <= 0.0 || lab.x <= 0.0) {
|
|
83
|
+
return color;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let direction = lab.yz / chroma;
|
|
87
|
+
let hue_signed = degrees(atan2(direction.y, direction.x));
|
|
88
|
+
let hue = select(hue_signed, hue_signed + 360.0, hue_signed < 0.0);
|
|
89
|
+
|
|
90
|
+
var shift = 0.0;
|
|
91
|
+
var scale = 1.0;
|
|
92
|
+
var stops = 0.0;
|
|
93
|
+
|
|
94
|
+
if (counts.x > 0u) {
|
|
95
|
+
shift = animation_curve_evaluate_keys(keys, 0u, counts.x, hue);
|
|
96
|
+
}
|
|
97
|
+
if (counts.y > 0u) {
|
|
98
|
+
scale = animation_curve_evaluate_keys(keys, counts.x, counts.y, hue);
|
|
99
|
+
}
|
|
100
|
+
if (counts.z > 0u) {
|
|
101
|
+
stops = animation_curve_evaluate_keys(keys, counts.x + counts.y, counts.z, hue);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// saturation relative to the Rec.709 gamut's edge at this hue: 0 for a grey, 1 on the edge
|
|
105
|
+
let relative = min(chroma / lab.x / oklab_compute_max_saturation(direction.x, direction.y), 1.0);
|
|
106
|
+
|
|
107
|
+
let angle = radians(shift);
|
|
108
|
+
let rotated = vec2<f32>(
|
|
109
|
+
direction.x * cos(angle) - direction.y * sin(angle),
|
|
110
|
+
direction.x * sin(angle) + direction.y * cos(angle),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Oklab is the cube root of a linear map, so scaling L, a and b by cbrt(2^k) scales the light by exactly 2^k
|
|
114
|
+
let exposure = exp2(stops * relative / 3.0);
|
|
115
|
+
|
|
116
|
+
return oklab_to_linear_srgb(vec3<f32>(lab.x, rotated * (chroma * scale)) * exposure);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fn color_grade(
|
|
120
|
+
scene: vec3<f32>,
|
|
121
|
+
grade: ${COLOR_GRADE_STRUCT.wgsl_ref},
|
|
122
|
+
keys: ptr<storage, array<${ANIMATION_CURVE_KEYFRAME_STRUCT.wgsl_ref}>, read>,
|
|
123
|
+
) -> vec3<f32> {
|
|
124
|
+
let white_balance = mat3x3<f32>(grade.white_balance_c0.xyz, grade.white_balance_c1.xyz, grade.white_balance_c2.xyz);
|
|
125
|
+
|
|
126
|
+
let ap1 = color_grade_primaries(CRM_FROM_REC709_TO_AP1 * (white_balance * scene), grade);
|
|
127
|
+
|
|
128
|
+
let graded = max(CRM_FROM_AP1_TO_REC709 * ap1, vec3<f32>(0.0));
|
|
129
|
+
|
|
130
|
+
return max(color_grade_hue_curves(graded, grade.curve_counts, keys), vec3<f32>(0.0));
|
|
131
|
+
}
|
|
132
|
+
`, [
|
|
133
|
+
COLOR_GRADE_STRUCT.declaration_chunk,
|
|
134
|
+
chunk_animation_curve_evaluate_keys,
|
|
135
|
+
chunk_CRM_REC709_AP1,
|
|
136
|
+
chunk_linear_srgb_to_oklab,
|
|
137
|
+
chunk_oklab_to_linear_srgb,
|
|
138
|
+
chunk_oklab_compute_max_saturation,
|
|
139
|
+
]
|
|
140
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `oklab_compute_max_saturation(a, b)`: the largest saturation S = C / L in linear sRGB (Rec.709) at the hue of the
|
|
3
|
+
* unit Oklab direction (a, b), where the first channel reaches zero. Ottosson's polynomial and one Halley step; the
|
|
4
|
+
* WGSL twin of `core/color/oklab/compute_max_saturation.js`.
|
|
5
|
+
*
|
|
6
|
+
* @see https://bottosson.github.io/posts/gamutclipping/
|
|
7
|
+
* @type {CodeChunk}
|
|
8
|
+
*/
|
|
9
|
+
export const chunk_oklab_compute_max_saturation: CodeChunk;
|
|
10
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
11
|
+
//# sourceMappingURL=chunk_oklab_compute_max_saturation.d.ts.map
|
package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_oklab_compute_max_saturation.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,iDAFU,SAAS,CAwDjB;0BAhEwB,gCAAgC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `oklab_compute_max_saturation(a, b)`: the largest saturation S = C / L in linear sRGB (Rec.709) at the hue of the
|
|
5
|
+
* unit Oklab direction (a, b), where the first channel reaches zero. Ottosson's polynomial and one Halley step; the
|
|
6
|
+
* WGSL twin of `core/color/oklab/compute_max_saturation.js`.
|
|
7
|
+
*
|
|
8
|
+
* @see https://bottosson.github.io/posts/gamutclipping/
|
|
9
|
+
* @type {CodeChunk}
|
|
10
|
+
*/
|
|
11
|
+
export const chunk_oklab_compute_max_saturation = CodeChunk.from(
|
|
12
|
+
//language=WGSL
|
|
13
|
+
`
|
|
14
|
+
fn oklab_compute_max_saturation(a: f32, b: f32) -> f32 {
|
|
15
|
+
// the channel that reaches zero first selects the coefficients
|
|
16
|
+
var k0: f32; var k1: f32; var k2: f32; var k3: f32; var k4: f32;
|
|
17
|
+
var wl: f32; var wm: f32; var ws: f32;
|
|
18
|
+
|
|
19
|
+
if (-1.88170328 * a - 0.80936493 * b > 1.0) {
|
|
20
|
+
// red
|
|
21
|
+
k0 = 1.19086277; k1 = 1.76576728; k2 = 0.59662641; k3 = 0.75515197; k4 = 0.56771245;
|
|
22
|
+
wl = 4.0767416621; wm = -3.3077115913; ws = 0.2309699292;
|
|
23
|
+
} else if (1.81444104 * a - 1.19445276 * b > 1.0) {
|
|
24
|
+
// green
|
|
25
|
+
k0 = 0.73956515; k1 = -0.45954404; k2 = 0.08285427; k3 = 0.12541070; k4 = 0.14503204;
|
|
26
|
+
wl = -1.2684380046; wm = 2.6097574011; ws = -0.3413193965;
|
|
27
|
+
} else {
|
|
28
|
+
// blue
|
|
29
|
+
k0 = 1.35733652; k1 = -0.00915799; k2 = -1.15130210; k3 = -0.50559606; k4 = 0.00692167;
|
|
30
|
+
wl = -0.0041960863; wm = -0.7034186147; ws = 1.7076147010;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var s = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
|
|
34
|
+
|
|
35
|
+
let k_l = 0.3963377774 * a + 0.2158037573 * b;
|
|
36
|
+
let k_m = -0.1055613458 * a - 0.0638541728 * b;
|
|
37
|
+
let k_s = -0.0894841775 * a - 1.2914855480 * b;
|
|
38
|
+
|
|
39
|
+
let l_ = 1.0 + s * k_l;
|
|
40
|
+
let m_ = 1.0 + s * k_m;
|
|
41
|
+
let s_ = 1.0 + s * k_s;
|
|
42
|
+
|
|
43
|
+
let l = l_ * l_ * l_;
|
|
44
|
+
let m = m_ * m_ * m_;
|
|
45
|
+
let s3 = s_ * s_ * s_;
|
|
46
|
+
|
|
47
|
+
let l_ds = 3.0 * k_l * l_ * l_;
|
|
48
|
+
let m_ds = 3.0 * k_m * m_ * m_;
|
|
49
|
+
let s_ds = 3.0 * k_s * s_ * s_;
|
|
50
|
+
|
|
51
|
+
let l_ds2 = 6.0 * k_l * k_l * l_;
|
|
52
|
+
let m_ds2 = 6.0 * k_m * k_m * m_;
|
|
53
|
+
let s_ds2 = 6.0 * k_s * k_s * s_;
|
|
54
|
+
|
|
55
|
+
let f = wl * l + wm * m + ws * s3;
|
|
56
|
+
let f1 = wl * l_ds + wm * m_ds + ws * s_ds;
|
|
57
|
+
let f2 = wl * l_ds2 + wm * m_ds2 + ws * s_ds2;
|
|
58
|
+
|
|
59
|
+
// one Halley step
|
|
60
|
+
s = s - f * f1 / (f1 * f1 - 0.5 * f * f2);
|
|
61
|
+
|
|
62
|
+
return s;
|
|
63
|
+
}
|
|
64
|
+
`
|
|
65
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The EETF of ITU-R BT.2390 (§5.4.1): maps a PQ signal mastered for a display reaching `source_peak` onto one
|
|
3
|
+
* reaching `target_peak`, all three PQ signals, with black at zero on both.
|
|
4
|
+
*
|
|
5
|
+
* The signal is first normalised to the source's range. Up to the knee, KS = 1.5 × maxLum − 0.5, it passes
|
|
6
|
+
* through; past it, a Hermite spline carries it to maxLum, the target's peak in the same normalisation, which the
|
|
7
|
+
* source's peak reaches with zero slope. The spline meets the identity at the knee with slope 1. A signal past
|
|
8
|
+
* `source_peak` is held at it. A target at or above the source passes every signal through.
|
|
9
|
+
*
|
|
10
|
+
* @type {CodeChunk}
|
|
11
|
+
*/
|
|
12
|
+
export const chunk_bt2390_eetf: CodeChunk;
|
|
13
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
14
|
+
//# sourceMappingURL=chunk_bt2390_eetf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_bt2390_eetf.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,gCAFU,SAAS,CA0BjB;0BArCwB,gCAAgC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CodeChunk } from "../../../compiler/CodeChunk.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The EETF of ITU-R BT.2390 (§5.4.1): maps a PQ signal mastered for a display reaching `source_peak` onto one
|
|
5
|
+
* reaching `target_peak`, all three PQ signals, with black at zero on both.
|
|
6
|
+
*
|
|
7
|
+
* The signal is first normalised to the source's range. Up to the knee, KS = 1.5 × maxLum − 0.5, it passes
|
|
8
|
+
* through; past it, a Hermite spline carries it to maxLum, the target's peak in the same normalisation, which the
|
|
9
|
+
* source's peak reaches with zero slope. The spline meets the identity at the knee with slope 1. A signal past
|
|
10
|
+
* `source_peak` is held at it. A target at or above the source passes every signal through.
|
|
11
|
+
*
|
|
12
|
+
* @type {CodeChunk}
|
|
13
|
+
*/
|
|
14
|
+
export const chunk_bt2390_eetf = CodeChunk.from(
|
|
15
|
+
//language=WGSL
|
|
16
|
+
`
|
|
17
|
+
fn bt2390_eetf(signal: f32, source_peak: f32, target_peak: f32) -> f32 {
|
|
18
|
+
let e1 = clamp(signal / source_peak, 0.0, 1.0);
|
|
19
|
+
|
|
20
|
+
let max_lum = target_peak / source_peak;
|
|
21
|
+
let ks = 1.5 * max_lum - 0.5;
|
|
22
|
+
|
|
23
|
+
if (e1 < ks || ks >= 1.0) {
|
|
24
|
+
return e1 * source_peak;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let t = (e1 - ks) / (1.0 - ks);
|
|
28
|
+
let t2 = t * t;
|
|
29
|
+
let t3 = t2 * t;
|
|
30
|
+
|
|
31
|
+
let e2 = (2.0 * t3 - 3.0 * t2 + 1.0) * ks
|
|
32
|
+
+ (t3 - 2.0 * t2 + t) * (1.0 - ks)
|
|
33
|
+
+ (-2.0 * t3 + 3.0 * t2) * max_lum;
|
|
34
|
+
|
|
35
|
+
return e2 * source_peak;
|
|
36
|
+
}
|
|
37
|
+
`
|
|
38
|
+
);
|