@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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("../../shader/compiler/CodeChunk.js").CodeChunk} CodeChunk
|
|
5
|
+
* @typedef {import("../../shader/resource/ShaderResourceGroupDescriptor.js").ShaderResourceGroupDescriptor} ShaderResourceGroupDescriptor
|
|
6
|
+
* @typedef {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A tone-mapping function, in WGSL, that {@link ToneMapper} bakes into its LUTs.
|
|
11
|
+
*
|
|
12
|
+
* {@link chunk} defines
|
|
13
|
+
*
|
|
14
|
+
* fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32>
|
|
15
|
+
*
|
|
16
|
+
* - `scene`: exposed linear Rec.709, 1 at the paper white. Not negative; the LUT's encoding clamps at zero.
|
|
17
|
+
* - `peak_nits`: the display's peak in cd/m². An SDR display is `PAPER_WHITE_NITS`.
|
|
18
|
+
* - returns linear Rec.2020 display light, 1 at the paper white (`PAPER_WHITE_NITS`).
|
|
19
|
+
*
|
|
20
|
+
* An operator whose chunk reads bindings of its own adds them in {@link declare} and supplies them in {@link bind}.
|
|
21
|
+
* The chunk is linked once into its bake shader, so its text must not change after first use.
|
|
22
|
+
*/
|
|
23
|
+
export class ToneMapOperator {
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} label
|
|
26
|
+
* @param {CodeChunk} chunk defines `tone_map_operator`, see the class
|
|
27
|
+
*/
|
|
28
|
+
constructor(label, chunk) {
|
|
29
|
+
assert.isString(label, 'label');
|
|
30
|
+
assert.defined(chunk, 'chunk');
|
|
31
|
+
assert.equal(chunk.isCodeChunk, true, 'chunk.isCodeChunk !== true');
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @readonly
|
|
35
|
+
* @type {string}
|
|
36
|
+
*/
|
|
37
|
+
this.label = label;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @readonly
|
|
41
|
+
* @type {CodeChunk}
|
|
42
|
+
*/
|
|
43
|
+
this.chunk = chunk;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Add the bindings {@link chunk} reads to the bake shader's group. None by default.
|
|
48
|
+
*
|
|
49
|
+
* @param {ShaderResourceGroupDescriptor} group
|
|
50
|
+
*/
|
|
51
|
+
declare(group) {
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Supply the bindings {@link declare} added, for a bake at `peak_nits`. None by default.
|
|
56
|
+
*
|
|
57
|
+
* @param {FrameGraph} graph the frame the bake is recorded into
|
|
58
|
+
* @param {number} peak_nits
|
|
59
|
+
* @param {Object} bindings the bake pass's bindings, to add to by name
|
|
60
|
+
*/
|
|
61
|
+
bind(graph, peak_nits, bindings) {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns the exposed scene colour into the canvas's colour, through a 3D LUT for each output.
|
|
3
|
+
*
|
|
4
|
+
* Each LUT maps exposed scene-linear Rec.709 to linear Rec.2020 display light, both as PQ (ST 2084) signals with 1 at
|
|
5
|
+
* the paper white, `PAPER_WHITE_NITS`; see `chunk_tonemap_lut`. Texel i of a LUT of N³ holds the scene signal
|
|
6
|
+
* i / (N - 1) along each axis, red fastest. Scene colour past 10000 cd/m², 49.3 × the paper white, reads the last
|
|
7
|
+
* texel. The apply passes take the LUT's output to the canvas's primaries and transfer curve.
|
|
8
|
+
*
|
|
9
|
+
* A LUT comes from {@link grade} and {@link operator}, baked at {@link lut_resolution} and baked again when any of them
|
|
10
|
+
* changes or, for the HDR LUT, when the display's peak does; or from the user, by {@link set_lut_sdr} and
|
|
11
|
+
* {@link set_lut_hdr}, which takes the place of the bake for that output until cleared. A user's LUT is not graded.
|
|
12
|
+
*/
|
|
13
|
+
export class ToneMapper {
|
|
14
|
+
/**
|
|
15
|
+
* @param {GPUDevice} device
|
|
16
|
+
*/
|
|
17
|
+
constructor(device: GPUDevice);
|
|
18
|
+
/**
|
|
19
|
+
* The tone-mapping function the LUTs are baked from. Unreal's default look unless set. Read every frame.
|
|
20
|
+
* @type {ToneMapOperator}
|
|
21
|
+
*/
|
|
22
|
+
operator: ToneMapOperator;
|
|
23
|
+
/**
|
|
24
|
+
* Texels along each edge of a baked LUT. At least 2, and at most the device's `maxTextureDimension3D`. Read every
|
|
25
|
+
* frame.
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
lut_resolution: number;
|
|
29
|
+
/**
|
|
30
|
+
* The colour grade ahead of {@link operator}, neutral unless changed. Read every frame; a change bakes again.
|
|
31
|
+
* @readonly
|
|
32
|
+
* @type {ColorGrade}
|
|
33
|
+
*/
|
|
34
|
+
readonly grade: ColorGrade;
|
|
35
|
+
/**
|
|
36
|
+
* The canvas's primaries and the display's peak, which the Renderer writes.
|
|
37
|
+
* @readonly
|
|
38
|
+
* @type {TonemapDisplaySettings}
|
|
39
|
+
*/
|
|
40
|
+
readonly display: TonemapDisplaySettings;
|
|
41
|
+
/**
|
|
42
|
+
* Supply the SDR LUT, in place of the one baked from {@link operator}.
|
|
43
|
+
*
|
|
44
|
+
* @param {number} resolution texels along each edge
|
|
45
|
+
* @param {Float32Array} data resolution³ RGB triples, red fastest, as the class describes
|
|
46
|
+
*/
|
|
47
|
+
set_lut_sdr(resolution: number, data: Float32Array): void;
|
|
48
|
+
/**
|
|
49
|
+
* Supply the HDR LUT, in place of the one baked from {@link operator}. It shows as graded: a display under
|
|
50
|
+
* `peak_nits` clips what it cannot reach.
|
|
51
|
+
*
|
|
52
|
+
* @param {number} resolution texels along each edge
|
|
53
|
+
* @param {Float32Array} data resolution³ RGB triples, red fastest, as the class describes
|
|
54
|
+
* @param {number} peak_nits the peak the LUT was graded for, cd/m²
|
|
55
|
+
*/
|
|
56
|
+
set_lut_hdr(resolution: number, data: Float32Array, peak_nits: number): void;
|
|
57
|
+
/**
|
|
58
|
+
* Go back to the SDR LUT baked from {@link operator}.
|
|
59
|
+
*/
|
|
60
|
+
clear_lut_sdr(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Go back to the HDR LUT baked from {@link operator}.
|
|
63
|
+
*/
|
|
64
|
+
clear_lut_hdr(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Make the SDR LUT from the HDR LUT supplied by {@link set_lut_hdr}, at its resolution: each texel through the
|
|
67
|
+
* BT.2390 EETF from the HDR LUT's graded peak down to the paper white, which keeps the hue and never passes SDR
|
|
68
|
+
* white. Built on the GPU in the next {@link render}, from the HDR LUT as it is then. Stays until
|
|
69
|
+
* {@link set_lut_sdr} or {@link clear_lut_sdr}.
|
|
70
|
+
*/
|
|
71
|
+
build_lut_sdr_from_hdr(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Offer the pipelines the next frame on this output needs.
|
|
74
|
+
*
|
|
75
|
+
* @param {PipelineEnquiry} enquiry
|
|
76
|
+
* @param {boolean} hdr
|
|
77
|
+
* @param {GPUTextureFormat} format the canvas's
|
|
78
|
+
*/
|
|
79
|
+
enquire_pipelines(enquiry: PipelineEnquiry, hdr: boolean, format: GPUTextureFormat): void;
|
|
80
|
+
/**
|
|
81
|
+
* Record the tone mapping of a frame: any LUT work it needs first, then the pass writing `target`.
|
|
82
|
+
*
|
|
83
|
+
* @param {Object} options
|
|
84
|
+
* @param {FrameGraph} options.graph
|
|
85
|
+
* @param {number} options.input_color the scene colour, linear Rec.709
|
|
86
|
+
* @param {number} options.exposure the exposure multiplier, a uniform
|
|
87
|
+
* @param {boolean} options.hdr whether the output is HDR
|
|
88
|
+
* @param {number} options.target the texture to write
|
|
89
|
+
* @returns {number} `target`, written
|
|
90
|
+
*/
|
|
91
|
+
render({ graph, input_color, exposure, hdr, target }: {
|
|
92
|
+
graph: FrameGraph;
|
|
93
|
+
input_color: number;
|
|
94
|
+
exposure: number;
|
|
95
|
+
hdr: boolean;
|
|
96
|
+
target: number;
|
|
97
|
+
}): number;
|
|
98
|
+
destroy(): void;
|
|
99
|
+
#private;
|
|
100
|
+
}
|
|
101
|
+
export type ToneMapOperator = import("./ToneMapOperator.js").ToneMapOperator;
|
|
102
|
+
export type PipelineEnquiry = import("../../../device/pipeline/PipelineEnquiry.js").PipelineEnquiry;
|
|
103
|
+
export type FrameGraph = import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
104
|
+
import { ColorGrade } from "./ColorGrade.js";
|
|
105
|
+
import { TonemapDisplaySettings } from "./TonemapDisplaySettings.js";
|
|
106
|
+
//# sourceMappingURL=ToneMapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToneMapper.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/ToneMapper.js"],"names":[],"mappings":"AA6FA;;;;;;;;;;;GAWG;AACH;IAmEI;;OAEG;IACH,+BAMC;IA3ED;;;OAGG;IACH,UAFU,eAAe,CAES;IAElC;;;;OAIG;IACH,gBAFU,MAAM,CAEI;IAEpB;;;;OAIG;IACH,gBAFU,UAAU,CAEK;IAEzB;;;;OAIG;IACH,kBAFU,sBAAsB,CAEO;IAoDvC;;;;;OAKG;IACH,wBAHW,MAAM,QACN,YAAY,QAKtB;IAED;;;;;;;OAOG;IACH,wBAJW,MAAM,QACN,YAAY,aACZ,MAAM,QAQhB;IAED;;OAEG;IACH,sBAIC;IAED;;OAEG;IACH,sBAGC;IAED;;;;;OAKG;IACH,+BASC;IAED;;;;;;OAMG;IACH,2BAJW,eAAe,OACf,OAAO,kCAMjB;IAED;;;;;;;;;;OAUG;IACH;QAP+B,KAAK,EAAzB,UAAU;QACM,WAAW,EAA3B,MAAM;QACU,QAAQ,EAAxB,MAAM;QACW,GAAG,EAApB,OAAO;QACS,MAAM,EAAtB,MAAM;QACJ,MAAM,CAyElB;IAED,gBAGC;;CAkIJ;8BAzcY,OAAO,sBAAsB,EAAE,eAAe;8BAC9C,OAAO,6CAA6C,EAAE,eAAe;yBACrE,OAAO,8DAA8D,EAAE,UAAU;2BAXxC,iBAAiB;uCAMhC,6BAA6B"}
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
|
|
3
|
+
import { graph_compute_pass } from "../../shader/graph/compute/graph_compute_pass.js";
|
|
4
|
+
import { graph_image_pass } from "../../shader/graph/graph_image_pass.js";
|
|
5
|
+
import { graph_import_raw_buffer } from "../../shader/graph/graph_import_raw_buffer.js";
|
|
6
|
+
import { graph_import_texture } from "../../shader/graph/graph_import_texture.js";
|
|
7
|
+
import { GPUTextureContext } from "../../texture/GPUTextureContext.js";
|
|
8
|
+
import { COLOR_GRADE_HEADER_FLOATS, ColorGrade } from "./ColorGrade.js";
|
|
9
|
+
import { shader_tonemap_HDR_lut } from "./shader_tonemap_HDR_lut.js";
|
|
10
|
+
import { shader_tonemap_LDR_lut } from "./shader_tonemap_LDR_lut.js";
|
|
11
|
+
import { shader_tonemap_lut_bake, TONEMAP_LUT_BAKE_GROUP } from "./shader_tonemap_lut_bake.js";
|
|
12
|
+
import { shader_tonemap_lut_sdr_from_hdr } from "./shader_tonemap_lut_sdr_from_hdr.js";
|
|
13
|
+
import { TONE_MAP_OPERATOR_ACES } from "./TONE_MAP_OPERATOR_ACES.js";
|
|
14
|
+
import { TonemapDisplaySettings } from "./TonemapDisplaySettings.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {import("./ToneMapOperator.js").ToneMapOperator} ToneMapOperator
|
|
18
|
+
* @typedef {import("../../../device/pipeline/PipelineEnquiry.js").PipelineEnquiry} PipelineEnquiry
|
|
19
|
+
* @typedef {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The pass that writes the canvas, for an SDR or an HDR output.
|
|
24
|
+
*
|
|
25
|
+
* @param {boolean} hdr
|
|
26
|
+
*/
|
|
27
|
+
function apply_shader(hdr) {
|
|
28
|
+
return hdr ? shader_tonemap_HDR_lut : shader_tonemap_LDR_lut;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* One LUT the tone mapper draws with, and what it holds.
|
|
33
|
+
*/
|
|
34
|
+
class ToneMapLut {
|
|
35
|
+
/**
|
|
36
|
+
* @param {GPUDevice} device
|
|
37
|
+
* @param {string} label
|
|
38
|
+
*/
|
|
39
|
+
constructor(device, label) {
|
|
40
|
+
/**
|
|
41
|
+
* @readonly
|
|
42
|
+
* @type {GPUTextureContext}
|
|
43
|
+
*/
|
|
44
|
+
this.texture = new GPUTextureContext(device);
|
|
45
|
+
this.texture.descriptor.label = label;
|
|
46
|
+
this.texture.descriptor.dimension = "3d";
|
|
47
|
+
this.texture.descriptor.format = "rgba16float";
|
|
48
|
+
this.texture.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING
|
|
49
|
+
| GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether the user supplied this LUT, rather than the tone mapper baking it from its operator.
|
|
53
|
+
* @type {boolean}
|
|
54
|
+
*/
|
|
55
|
+
this.user = false;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The operator, resolution and peak this LUT was baked for; `null` operator when it holds no bake.
|
|
59
|
+
* @type {ToneMapOperator|null}
|
|
60
|
+
*/
|
|
61
|
+
this.baked_operator = null;
|
|
62
|
+
this.baked_resolution = 0;
|
|
63
|
+
this.baked_peak_nits = NaN;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The packed grade this LUT was baked with, its bits compared with the grade's each frame.
|
|
67
|
+
* @type {Uint32Array}
|
|
68
|
+
*/
|
|
69
|
+
this.baked_grade = new Uint32Array(0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {Uint32Array} a
|
|
75
|
+
* @param {Uint32Array} b
|
|
76
|
+
* @returns {boolean} whether the two hold the same bits
|
|
77
|
+
*/
|
|
78
|
+
function same_words(a, b) {
|
|
79
|
+
const length = a.length;
|
|
80
|
+
|
|
81
|
+
if (length !== b.length) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (let i = 0; i < length; i++) {
|
|
86
|
+
if (a[i] !== b[i]) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Turns the exposed scene colour into the canvas's colour, through a 3D LUT for each output.
|
|
96
|
+
*
|
|
97
|
+
* Each LUT maps exposed scene-linear Rec.709 to linear Rec.2020 display light, both as PQ (ST 2084) signals with 1 at
|
|
98
|
+
* the paper white, `PAPER_WHITE_NITS`; see `chunk_tonemap_lut`. Texel i of a LUT of N³ holds the scene signal
|
|
99
|
+
* i / (N - 1) along each axis, red fastest. Scene colour past 10000 cd/m², 49.3 × the paper white, reads the last
|
|
100
|
+
* texel. The apply passes take the LUT's output to the canvas's primaries and transfer curve.
|
|
101
|
+
*
|
|
102
|
+
* A LUT comes from {@link grade} and {@link operator}, baked at {@link lut_resolution} and baked again when any of them
|
|
103
|
+
* changes or, for the HDR LUT, when the display's peak does; or from the user, by {@link set_lut_sdr} and
|
|
104
|
+
* {@link set_lut_hdr}, which takes the place of the bake for that output until cleared. A user's LUT is not graded.
|
|
105
|
+
*/
|
|
106
|
+
export class ToneMapper {
|
|
107
|
+
/**
|
|
108
|
+
* The tone-mapping function the LUTs are baked from. Unreal's default look unless set. Read every frame.
|
|
109
|
+
* @type {ToneMapOperator}
|
|
110
|
+
*/
|
|
111
|
+
operator = TONE_MAP_OPERATOR_ACES;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Texels along each edge of a baked LUT. At least 2, and at most the device's `maxTextureDimension3D`. Read every
|
|
115
|
+
* frame.
|
|
116
|
+
* @type {number}
|
|
117
|
+
*/
|
|
118
|
+
lut_resolution = 32;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The colour grade ahead of {@link operator}, neutral unless changed. Read every frame; a change bakes again.
|
|
122
|
+
* @readonly
|
|
123
|
+
* @type {ColorGrade}
|
|
124
|
+
*/
|
|
125
|
+
grade = new ColorGrade();
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The canvas's primaries and the display's peak, which the Renderer writes.
|
|
129
|
+
* @readonly
|
|
130
|
+
* @type {TonemapDisplaySettings}
|
|
131
|
+
*/
|
|
132
|
+
display = new TonemapDisplaySettings();
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @type {GPUDevice}
|
|
136
|
+
*/
|
|
137
|
+
#device;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @type {ToneMapLut}
|
|
141
|
+
*/
|
|
142
|
+
#sdr;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @type {ToneMapLut}
|
|
146
|
+
*/
|
|
147
|
+
#hdr;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The peak the user's HDR LUT was graded for, cd/m².
|
|
151
|
+
* @type {number}
|
|
152
|
+
*/
|
|
153
|
+
#hdr_graded_peak_nits = NaN;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Whether the next {@link render} builds the SDR LUT from the HDR one.
|
|
157
|
+
* @type {boolean}
|
|
158
|
+
*/
|
|
159
|
+
#sdr_from_hdr_pending = false;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* {@link grade} as this frame packed it.
|
|
163
|
+
* @type {Float32Array}
|
|
164
|
+
*/
|
|
165
|
+
#grade_data = new Float32Array(0);
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* {@link #grade_data}'s words.
|
|
169
|
+
* @type {Uint32Array}
|
|
170
|
+
*/
|
|
171
|
+
#grade_words = new Uint32Array(0);
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {GPUDevice} device
|
|
175
|
+
*/
|
|
176
|
+
constructor(device) {
|
|
177
|
+
assert.defined(device, 'device');
|
|
178
|
+
|
|
179
|
+
this.#device = device;
|
|
180
|
+
this.#sdr = new ToneMapLut(device, "Tonemap / SDR LUT");
|
|
181
|
+
this.#hdr = new ToneMapLut(device, "Tonemap / HDR LUT");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Supply the SDR LUT, in place of the one baked from {@link operator}.
|
|
186
|
+
*
|
|
187
|
+
* @param {number} resolution texels along each edge
|
|
188
|
+
* @param {Float32Array} data resolution³ RGB triples, red fastest, as the class describes
|
|
189
|
+
*/
|
|
190
|
+
set_lut_sdr(resolution, data) {
|
|
191
|
+
this.#upload(this.#sdr, resolution, data);
|
|
192
|
+
this.#sdr_from_hdr_pending = false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Supply the HDR LUT, in place of the one baked from {@link operator}. It shows as graded: a display under
|
|
197
|
+
* `peak_nits` clips what it cannot reach.
|
|
198
|
+
*
|
|
199
|
+
* @param {number} resolution texels along each edge
|
|
200
|
+
* @param {Float32Array} data resolution³ RGB triples, red fastest, as the class describes
|
|
201
|
+
* @param {number} peak_nits the peak the LUT was graded for, cd/m²
|
|
202
|
+
*/
|
|
203
|
+
set_lut_hdr(resolution, data, peak_nits) {
|
|
204
|
+
assert.isNumber(peak_nits, 'peak_nits');
|
|
205
|
+
assert.greaterThan(peak_nits, 0, 'peak_nits');
|
|
206
|
+
|
|
207
|
+
this.#upload(this.#hdr, resolution, data);
|
|
208
|
+
this.#hdr_graded_peak_nits = peak_nits;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Go back to the SDR LUT baked from {@link operator}.
|
|
213
|
+
*/
|
|
214
|
+
clear_lut_sdr() {
|
|
215
|
+
this.#sdr.user = false;
|
|
216
|
+
this.#sdr.baked_operator = null;
|
|
217
|
+
this.#sdr_from_hdr_pending = false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Go back to the HDR LUT baked from {@link operator}.
|
|
222
|
+
*/
|
|
223
|
+
clear_lut_hdr() {
|
|
224
|
+
this.#hdr.user = false;
|
|
225
|
+
this.#hdr.baked_operator = null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Make the SDR LUT from the HDR LUT supplied by {@link set_lut_hdr}, at its resolution: each texel through the
|
|
230
|
+
* BT.2390 EETF from the HDR LUT's graded peak down to the paper white, which keeps the hue and never passes SDR
|
|
231
|
+
* white. Built on the GPU in the next {@link render}, from the HDR LUT as it is then. Stays until
|
|
232
|
+
* {@link set_lut_sdr} or {@link clear_lut_sdr}.
|
|
233
|
+
*/
|
|
234
|
+
build_lut_sdr_from_hdr() {
|
|
235
|
+
assert.equal(this.#hdr.user, true, 'build_lut_sdr_from_hdr needs an HDR LUT from set_lut_hdr');
|
|
236
|
+
|
|
237
|
+
const resolution = this.#hdr.texture.width;
|
|
238
|
+
|
|
239
|
+
this.#sdr.texture.resize(resolution, resolution, resolution);
|
|
240
|
+
this.#sdr.user = true;
|
|
241
|
+
this.#sdr.baked_operator = null;
|
|
242
|
+
this.#sdr_from_hdr_pending = true;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Offer the pipelines the next frame on this output needs.
|
|
247
|
+
*
|
|
248
|
+
* @param {PipelineEnquiry} enquiry
|
|
249
|
+
* @param {boolean} hdr
|
|
250
|
+
* @param {GPUTextureFormat} format the canvas's
|
|
251
|
+
*/
|
|
252
|
+
enquire_pipelines(enquiry, hdr, format) {
|
|
253
|
+
enquiry.render.push(apply_shader(hdr).pipeline_for([format]));
|
|
254
|
+
enquiry.compute.push(shader_tonemap_lut_bake(this.operator).pipeline);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Record the tone mapping of a frame: any LUT work it needs first, then the pass writing `target`.
|
|
259
|
+
*
|
|
260
|
+
* @param {Object} options
|
|
261
|
+
* @param {FrameGraph} options.graph
|
|
262
|
+
* @param {number} options.input_color the scene colour, linear Rec.709
|
|
263
|
+
* @param {number} options.exposure the exposure multiplier, a uniform
|
|
264
|
+
* @param {boolean} options.hdr whether the output is HDR
|
|
265
|
+
* @param {number} options.target the texture to write
|
|
266
|
+
* @returns {number} `target`, written
|
|
267
|
+
*/
|
|
268
|
+
render({ graph, input_color, exposure, hdr, target }) {
|
|
269
|
+
assert.isBoolean(hdr, 'hdr');
|
|
270
|
+
|
|
271
|
+
const lut = hdr ? this.#hdr : this.#sdr;
|
|
272
|
+
const peak_nits = hdr ? this.display.peak_nits : PAPER_WHITE_NITS;
|
|
273
|
+
|
|
274
|
+
let bake = false;
|
|
275
|
+
|
|
276
|
+
if (!lut.user) {
|
|
277
|
+
this.#pack_grade();
|
|
278
|
+
bake = this.#bake_is_stale(lut, peak_nits);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (bake) {
|
|
282
|
+
// sized before it is imported, so the import describes the texture the bake writes
|
|
283
|
+
const resolution = this.lut_resolution;
|
|
284
|
+
|
|
285
|
+
this.#check_resolution(resolution);
|
|
286
|
+
lut.texture.resize(resolution, resolution, resolution);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const pending = this.#sdr_from_hdr_pending;
|
|
290
|
+
|
|
291
|
+
let gr_hdr = -1;
|
|
292
|
+
let gr_sdr = -1;
|
|
293
|
+
|
|
294
|
+
if (hdr || pending) {
|
|
295
|
+
gr_hdr = graph_import_texture(graph, this.#hdr.texture, "tonemap/HDR LUT");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (!hdr || pending) {
|
|
299
|
+
gr_sdr = graph_import_texture(graph, this.#sdr.texture, "tonemap/SDR LUT");
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (pending) {
|
|
303
|
+
// a pass writing an imported texture never culls, so this runs whichever output draws
|
|
304
|
+
const groups = Math.ceil(this.#sdr.texture.width / TONEMAP_LUT_BAKE_GROUP);
|
|
305
|
+
|
|
306
|
+
gr_sdr = graph_compute_pass({
|
|
307
|
+
graph,
|
|
308
|
+
shader: shader_tonemap_lut_sdr_from_hdr,
|
|
309
|
+
bindings: {
|
|
310
|
+
settings: { source_peak_nits: this.#hdr_graded_peak_nits },
|
|
311
|
+
hdr_lut: gr_hdr,
|
|
312
|
+
sdr_lut: gr_sdr,
|
|
313
|
+
},
|
|
314
|
+
group_count: [groups, groups, groups],
|
|
315
|
+
}).sdr_lut;
|
|
316
|
+
|
|
317
|
+
this.#sdr_from_hdr_pending = false;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let gr_lut = hdr ? gr_hdr : gr_sdr;
|
|
321
|
+
|
|
322
|
+
if (bake) {
|
|
323
|
+
gr_lut = this.#bake(graph, lut, peak_nits, gr_lut);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const [written] = graph_image_pass({
|
|
327
|
+
graph,
|
|
328
|
+
shader: apply_shader(hdr),
|
|
329
|
+
inputs: {
|
|
330
|
+
input_color,
|
|
331
|
+
exposure,
|
|
332
|
+
settings: this.display,
|
|
333
|
+
lut: gr_lut,
|
|
334
|
+
},
|
|
335
|
+
output: [target]
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
return written;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
destroy() {
|
|
342
|
+
this.#sdr.texture.destroy();
|
|
343
|
+
this.#hdr.texture.destroy();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* @param {ToneMapLut} lut
|
|
348
|
+
* @param {number} peak_nits
|
|
349
|
+
* @returns {boolean}
|
|
350
|
+
*/
|
|
351
|
+
#bake_is_stale(lut, peak_nits) {
|
|
352
|
+
return lut.baked_operator !== this.operator
|
|
353
|
+
|| lut.baked_resolution !== this.lut_resolution
|
|
354
|
+
|| lut.baked_peak_nits !== peak_nits
|
|
355
|
+
|| !same_words(lut.baked_grade, this.#grade_words);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#pack_grade() {
|
|
359
|
+
const data = this.grade.pack();
|
|
360
|
+
|
|
361
|
+
if (data !== this.#grade_data) {
|
|
362
|
+
this.#grade_data = data;
|
|
363
|
+
this.#grade_words = new Uint32Array(data.buffer, data.byteOffset, data.length);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @param {FrameGraph} graph
|
|
369
|
+
* @param {ToneMapLut} lut
|
|
370
|
+
* @param {number} peak_nits
|
|
371
|
+
* @param {number} gr_lut the LUT's texture, sized for {@link lut_resolution} and imported into `graph`
|
|
372
|
+
* @returns {number} the LUT, written
|
|
373
|
+
*/
|
|
374
|
+
#bake(graph, lut, peak_nits, gr_lut) {
|
|
375
|
+
const operator = this.operator;
|
|
376
|
+
const resolution = this.lut_resolution;
|
|
377
|
+
|
|
378
|
+
const grade = this.#grade_data;
|
|
379
|
+
const header_bytes = COLOR_GRADE_HEADER_FLOATS * 4;
|
|
380
|
+
|
|
381
|
+
const bindings = {
|
|
382
|
+
settings: { peak_nits },
|
|
383
|
+
lut: gr_lut,
|
|
384
|
+
grade: graph_import_raw_buffer({
|
|
385
|
+
graph,
|
|
386
|
+
value: grade.buffer,
|
|
387
|
+
offset: grade.byteOffset,
|
|
388
|
+
size: header_bytes,
|
|
389
|
+
label: "tonemap/grade",
|
|
390
|
+
usage: GPUBufferUsage.UNIFORM,
|
|
391
|
+
}),
|
|
392
|
+
grade_keys: graph_import_raw_buffer({
|
|
393
|
+
graph,
|
|
394
|
+
value: grade.buffer,
|
|
395
|
+
offset: grade.byteOffset + header_bytes,
|
|
396
|
+
size: grade.byteLength - header_bytes,
|
|
397
|
+
label: "tonemap/grade keys",
|
|
398
|
+
usage: GPUBufferUsage.STORAGE,
|
|
399
|
+
}),
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
operator.bind(graph, peak_nits, bindings);
|
|
403
|
+
|
|
404
|
+
const groups = Math.ceil(resolution / TONEMAP_LUT_BAKE_GROUP);
|
|
405
|
+
|
|
406
|
+
const written = graph_compute_pass({
|
|
407
|
+
graph,
|
|
408
|
+
shader: shader_tonemap_lut_bake(operator),
|
|
409
|
+
bindings,
|
|
410
|
+
group_count: [groups, groups, groups],
|
|
411
|
+
}).lut;
|
|
412
|
+
|
|
413
|
+
lut.baked_operator = operator;
|
|
414
|
+
lut.baked_resolution = resolution;
|
|
415
|
+
lut.baked_peak_nits = peak_nits;
|
|
416
|
+
|
|
417
|
+
if (lut.baked_grade.length !== this.#grade_words.length) {
|
|
418
|
+
lut.baked_grade = new Uint32Array(this.#grade_words.length);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
lut.baked_grade.set(this.#grade_words);
|
|
422
|
+
|
|
423
|
+
return written;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* @param {ToneMapLut} lut
|
|
428
|
+
* @param {number} resolution
|
|
429
|
+
* @param {Float32Array} data
|
|
430
|
+
*/
|
|
431
|
+
#upload(lut, resolution, data) {
|
|
432
|
+
this.#check_resolution(resolution);
|
|
433
|
+
assert.isInstanceOf(data, Float32Array, 'data');
|
|
434
|
+
assert.equal(data.length, resolution * resolution * resolution * 3, 'data.length !== resolution³ × 3');
|
|
435
|
+
|
|
436
|
+
const texel_count = resolution * resolution * resolution;
|
|
437
|
+
const texels = new Float16Array(texel_count * 4);
|
|
438
|
+
|
|
439
|
+
for (let i = 0; i < texel_count; i++) {
|
|
440
|
+
texels[i * 4] = data[i * 3];
|
|
441
|
+
texels[i * 4 + 1] = data[i * 3 + 1];
|
|
442
|
+
texels[i * 4 + 2] = data[i * 3 + 2];
|
|
443
|
+
texels[i * 4 + 3] = 1;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const texture = lut.texture;
|
|
447
|
+
|
|
448
|
+
texture.resize(resolution, resolution, resolution);
|
|
449
|
+
|
|
450
|
+
this.#device.queue.writeTexture(
|
|
451
|
+
{ texture: texture.gpu_texture },
|
|
452
|
+
texels,
|
|
453
|
+
{ bytesPerRow: resolution * 8, rowsPerImage: resolution },
|
|
454
|
+
[resolution, resolution, resolution]
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
lut.user = true;
|
|
458
|
+
lut.baked_operator = null;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* @param {number} resolution
|
|
463
|
+
*/
|
|
464
|
+
#check_resolution(resolution) {
|
|
465
|
+
assert.isNonNegativeInteger(resolution, 'resolution');
|
|
466
|
+
assert.greaterThanOrEqual(resolution, 2, 'resolution');
|
|
467
|
+
|
|
468
|
+
const limit = this.#device.limits.maxTextureDimension3D;
|
|
469
|
+
|
|
470
|
+
if (resolution > limit) {
|
|
471
|
+
throw new Error(`A tone-mapping LUT of ${resolution}³ exceeds the device's maxTextureDimension3D, ${limit}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What
|
|
2
|
+
* What the ACES tone-map operator binds as `aces2_tables`: two ACES 2.0 output transforms, each its parameters and
|
|
3
3
|
* gamut tables, both limited to Rec.709, the gamut of the SDR picture they expand.
|
|
4
4
|
*
|
|
5
|
-
* 1. An SDR display, 100 cd/m². The
|
|
5
|
+
* 1. An SDR display, 100 cd/m². The operator runs it backwards, from the SDR picture to the scene.
|
|
6
6
|
* 2. This display: the peak over the paper white, times 100 cd/m². A display at or under the paper white gets
|
|
7
|
-
* 100 cd/m², which the
|
|
7
|
+
* 100 cd/m², which the operator does not read.
|
|
8
8
|
*
|
|
9
9
|
* Both take SDR white for 100 cd/m², ACES 2.0's reference, so an SDR picture expanded for a display keeps SDR white
|
|
10
10
|
* where the paper white puts it.
|
|
11
11
|
*
|
|
12
|
-
* Building one transform takes 7 to 13 ms, so the tables are built on the first {@link update}
|
|
13
|
-
*
|
|
12
|
+
* Building one transform takes 7 to 13 ms, so the tables are built on the first {@link update}, and again only when
|
|
13
|
+
* the display's peak changes.
|
|
14
14
|
*/
|
|
15
15
|
export class TonemapAces2Tables {
|
|
16
16
|
/**
|
|
@@ -25,14 +25,6 @@ export class TonemapAces2Tables {
|
|
|
25
25
|
* @returns {boolean} whether {@link data} changed
|
|
26
26
|
*/
|
|
27
27
|
update(peak_nits: number): boolean;
|
|
28
|
-
/**
|
|
29
|
-
* The tables on the device, written if they changed since the last call.
|
|
30
|
-
*
|
|
31
|
-
* @param {GPUDevice} device
|
|
32
|
-
* @returns {GPUBuffer}
|
|
33
|
-
*/
|
|
34
|
-
gpu_buffer(device: GPUDevice): GPUBuffer;
|
|
35
|
-
destroy(): void;
|
|
36
28
|
#private;
|
|
37
29
|
}
|
|
38
30
|
//# sourceMappingURL=TonemapAces2Tables.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TonemapAces2Tables.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH;IACI;;;OAGG;IACH,MAFU,YAAY,CAE0B;
|
|
1
|
+
{"version":3,"file":"TonemapAces2Tables.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH;IACI;;;OAGG;IACH,MAFU,YAAY,CAE0B;IAIhD;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAqBnB;;CACJ"}
|