@woosh/meep-engine 3.63.3 → 3.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/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/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/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/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,337 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { Vector4 } from "../../../../core/geom/Vector4.js";
|
|
3
|
+
import { AnimationCurve } from "../../../../engine/animation/curve/AnimationCurve.js";
|
|
4
|
+
import { vec4f, vec4u } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
5
|
+
import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
|
|
6
|
+
import { m3_white_balance_rec709, WHITE_BALANCE_NEUTRAL_TEMPERATURE, WHITE_BALANCE_NEUTRAL_TINT } from "./m3_white_balance_rec709.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The grade as the bake reads it, a uniform. Every field is 16 bytes, in this order, never packed: field i is at byte
|
|
10
|
+
* 16 · i, which is how {@link ColorGrade#pack} writes it.
|
|
11
|
+
*
|
|
12
|
+
* - `white_balance_c0..c2`: the white-balance matrix on linear Rec.709, by column.
|
|
13
|
+
* - per zone, `{zone}_saturation`, `_contrast`, `_gamma`, `_gain`, `_offset`: the zone's values with the global ones
|
|
14
|
+
* folded in and each vector's fourth component applied to the first three, as Unreal's `ColorCorrectAll` combines
|
|
15
|
+
* them.
|
|
16
|
+
* - `zone_bounds`: `shadows_max`, `highlights_min`, `highlights_max`.
|
|
17
|
+
* - `curve_counts`: the keys of the hue, saturation and lightness curves. They follow the uniform in `grade_keys`, in
|
|
18
|
+
* that order.
|
|
19
|
+
*/
|
|
20
|
+
export const COLOR_GRADE_STRUCT = WebGPUStruct.from({
|
|
21
|
+
white_balance_c0: vec4f,
|
|
22
|
+
white_balance_c1: vec4f,
|
|
23
|
+
white_balance_c2: vec4f,
|
|
24
|
+
|
|
25
|
+
shadows_saturation: vec4f,
|
|
26
|
+
shadows_contrast: vec4f,
|
|
27
|
+
shadows_gamma: vec4f,
|
|
28
|
+
shadows_gain: vec4f,
|
|
29
|
+
shadows_offset: vec4f,
|
|
30
|
+
|
|
31
|
+
midtones_saturation: vec4f,
|
|
32
|
+
midtones_contrast: vec4f,
|
|
33
|
+
midtones_gamma: vec4f,
|
|
34
|
+
midtones_gain: vec4f,
|
|
35
|
+
midtones_offset: vec4f,
|
|
36
|
+
|
|
37
|
+
highlights_saturation: vec4f,
|
|
38
|
+
highlights_contrast: vec4f,
|
|
39
|
+
highlights_gamma: vec4f,
|
|
40
|
+
highlights_gain: vec4f,
|
|
41
|
+
highlights_offset: vec4f,
|
|
42
|
+
|
|
43
|
+
zone_bounds: vec4f,
|
|
44
|
+
curve_counts: vec4u,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Floats of {@link COLOR_GRADE_STRUCT} at the head of {@link ColorGrade#pack}'s data.
|
|
49
|
+
* @type {number}
|
|
50
|
+
*/
|
|
51
|
+
export const COLOR_GRADE_HEADER_FLOATS = 80;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Floats of one keyframe in `grade_keys`: time, value, in tangent, out tangent.
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
export const COLOR_GRADE_KEY_FLOATS = 4;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* One zone of Unreal's primary grade: shadows, midtones, highlights, or all of them. Each vector is RGB and a master
|
|
61
|
+
* value that scales (or, for the offset, adds to) all three.
|
|
62
|
+
*/
|
|
63
|
+
export class ColorGradeZone {
|
|
64
|
+
/**
|
|
65
|
+
* Blend between the luma and the colour; 0 is grey, 1 leaves it.
|
|
66
|
+
* @readonly
|
|
67
|
+
* @type {Vector4}
|
|
68
|
+
*/
|
|
69
|
+
saturation = new Vector4(1, 1, 1, 1);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Power about 0.18.
|
|
73
|
+
* @readonly
|
|
74
|
+
* @type {Vector4}
|
|
75
|
+
*/
|
|
76
|
+
contrast = new Vector4(1, 1, 1, 1);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The colour is raised to 1 / gamma.
|
|
80
|
+
* @readonly
|
|
81
|
+
* @type {Vector4}
|
|
82
|
+
*/
|
|
83
|
+
gamma = new Vector4(1, 1, 1, 1);
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @readonly
|
|
87
|
+
* @type {Vector4}
|
|
88
|
+
*/
|
|
89
|
+
gain = new Vector4(1, 1, 1, 1);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Added last.
|
|
93
|
+
* @readonly
|
|
94
|
+
* @type {Vector4}
|
|
95
|
+
*/
|
|
96
|
+
offset = new Vector4(0, 0, 0, 0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const scratch_m3 = new Float64Array(9);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {Float32Array} out
|
|
103
|
+
* @param {number} at float index
|
|
104
|
+
* @param {Vector4} zone
|
|
105
|
+
* @param {Vector4} global
|
|
106
|
+
*/
|
|
107
|
+
function write_product(out, at, zone, global) {
|
|
108
|
+
const master = zone[3] * global[3];
|
|
109
|
+
|
|
110
|
+
out[at] = zone[0] * global[0] * master;
|
|
111
|
+
out[at + 1] = zone[1] * global[1] * master;
|
|
112
|
+
out[at + 2] = zone[2] * global[2] * master;
|
|
113
|
+
out[at + 3] = 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {Float32Array} out
|
|
118
|
+
* @param {number} at float index
|
|
119
|
+
* @param {Vector4} zone
|
|
120
|
+
* @param {Vector4} global
|
|
121
|
+
*/
|
|
122
|
+
function write_sum(out, at, zone, global) {
|
|
123
|
+
const master = zone[3] + global[3];
|
|
124
|
+
|
|
125
|
+
out[at] = zone[0] + global[0] + master;
|
|
126
|
+
out[at + 1] = zone[1] + global[1] + master;
|
|
127
|
+
out[at + 2] = zone[2] + global[2] + master;
|
|
128
|
+
out[at + 3] = 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Float32Array} out
|
|
133
|
+
* @param {number} at float index
|
|
134
|
+
* @param {ColorGradeZone} zone
|
|
135
|
+
* @param {ColorGradeZone} global
|
|
136
|
+
*/
|
|
137
|
+
function write_zone(out, at, zone, global) {
|
|
138
|
+
write_product(out, at, zone.saturation, global.saturation);
|
|
139
|
+
write_product(out, at + 4, zone.contrast, global.contrast);
|
|
140
|
+
write_product(out, at + 8, zone.gamma, global.gamma);
|
|
141
|
+
write_product(out, at + 12, zone.gain, global.gain);
|
|
142
|
+
write_sum(out, at + 16, zone.offset, global.offset);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @param {Float32Array} out
|
|
147
|
+
* @param {number} at float index
|
|
148
|
+
* @param {AnimationCurve} curve
|
|
149
|
+
* @returns {number} the float index after the curve's keys
|
|
150
|
+
*/
|
|
151
|
+
function write_keys(out, at, curve) {
|
|
152
|
+
const keys = curve.keys;
|
|
153
|
+
const count = keys.length;
|
|
154
|
+
|
|
155
|
+
for (let i = 0; i < count; i++) {
|
|
156
|
+
const key = keys[i];
|
|
157
|
+
|
|
158
|
+
out[at] = key.time;
|
|
159
|
+
out[at + 1] = key.value;
|
|
160
|
+
out[at + 2] = key.inTangent;
|
|
161
|
+
out[at + 3] = key.outTangent;
|
|
162
|
+
|
|
163
|
+
at += COLOR_GRADE_KEY_FLOATS;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return at;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* A colour grade on the exposed scene colour, ahead of the tone-mapping operator, baked into the tone mapper's LUTs.
|
|
171
|
+
* Neutral as constructed. In order:
|
|
172
|
+
*
|
|
173
|
+
* 1. **White balance**, Unreal's temperature white balance on linear Rec.709; see `m3_white_balance_rec709`.
|
|
174
|
+
* 2. **Primaries**, Unreal's `ColorCorrectAll` in AP1: saturation, contrast, gamma, gain and offset for {@link global},
|
|
175
|
+
* {@link shadows}, {@link midtones} and {@link highlights}, the zones blended by AP1 luma between
|
|
176
|
+
* {@link shadows_max}, {@link highlights_min} and {@link highlights_max}. Values from an Unreal project's post-process
|
|
177
|
+
* settings give the same result. The colour is clamped at zero in Rec.709 after it, as the operator takes it.
|
|
178
|
+
* 3. **Hue curves**, in OkLCh. Each curve's time is the colour's OkLCh hue in degrees, 0 to 360, and is evaluated as
|
|
179
|
+
* {@link AnimationCurve#evaluate} would; a curve with no keys does nothing. The curve holds its end keys' values
|
|
180
|
+
* outside them, so for a seamless circle key 0 and 360 with the same value and tangent.
|
|
181
|
+
* - {@link hue_shift}: degrees added to the hue.
|
|
182
|
+
* - {@link hue_saturation}: a multiplier on the chroma.
|
|
183
|
+
* - {@link hue_lightness}: stops of exposure, the light multiplied by 2^stops at the same chromaticity, weighted by
|
|
184
|
+
* the colour's saturation relative to the most saturated Rec.709 colour of its hue. A grey never moves, and a
|
|
185
|
+
* colour on the gamut's edge takes the full value.
|
|
186
|
+
* All three are read at the colour's hue before any of them applies.
|
|
187
|
+
*
|
|
188
|
+
* Read by the tone mapper every frame; any change bakes the LUTs again. A LUT the user supplies is not graded.
|
|
189
|
+
*/
|
|
190
|
+
export class ColorGrade {
|
|
191
|
+
/**
|
|
192
|
+
* Colour temperature of the white the grade makes neutral, K. 6500 does nothing.
|
|
193
|
+
* @type {number}
|
|
194
|
+
*/
|
|
195
|
+
white_temperature = WHITE_BALANCE_NEUTRAL_TEMPERATURE;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Offset of that white along its isotherm, -1 to 1 as in Unreal. 0 does nothing.
|
|
199
|
+
* @type {number}
|
|
200
|
+
*/
|
|
201
|
+
white_tint = WHITE_BALANCE_NEUTRAL_TINT;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Applies in every zone, under the zone's own values.
|
|
205
|
+
* @readonly
|
|
206
|
+
* @type {ColorGradeZone}
|
|
207
|
+
*/
|
|
208
|
+
global = new ColorGradeZone();
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @readonly
|
|
212
|
+
* @type {ColorGradeZone}
|
|
213
|
+
*/
|
|
214
|
+
shadows = new ColorGradeZone();
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @readonly
|
|
218
|
+
* @type {ColorGradeZone}
|
|
219
|
+
*/
|
|
220
|
+
midtones = new ColorGradeZone();
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @readonly
|
|
224
|
+
* @type {ColorGradeZone}
|
|
225
|
+
*/
|
|
226
|
+
highlights = new ColorGradeZone();
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* AP1 luma at which the shadows' weight reaches 0. Unreal's default.
|
|
230
|
+
* @type {number}
|
|
231
|
+
*/
|
|
232
|
+
shadows_max = 0.09;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* AP1 luma at which the highlights' weight starts to rise from 0. Unreal's default.
|
|
236
|
+
* @type {number}
|
|
237
|
+
*/
|
|
238
|
+
highlights_min = 0.5;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* AP1 luma at which the highlights' weight reaches 1. Unreal's default.
|
|
242
|
+
* @type {number}
|
|
243
|
+
*/
|
|
244
|
+
highlights_max = 1;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Degrees added to the OkLCh hue, against the hue in degrees.
|
|
248
|
+
* @readonly
|
|
249
|
+
* @type {AnimationCurve}
|
|
250
|
+
*/
|
|
251
|
+
hue_shift = new AnimationCurve();
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Multiplier on the OkLCh chroma, against the hue in degrees.
|
|
255
|
+
* @readonly
|
|
256
|
+
* @type {AnimationCurve}
|
|
257
|
+
*/
|
|
258
|
+
hue_saturation = new AnimationCurve();
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Stops of exposure, against the hue in degrees.
|
|
262
|
+
* @readonly
|
|
263
|
+
* @type {AnimationCurve}
|
|
264
|
+
*/
|
|
265
|
+
hue_lightness = new AnimationCurve();
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @type {Float32Array}
|
|
269
|
+
*/
|
|
270
|
+
#data = new Float32Array(COLOR_GRADE_HEADER_FLOATS + COLOR_GRADE_KEY_FLOATS);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* {@link #data}'s words, for the curve counts.
|
|
274
|
+
* @type {Uint32Array}
|
|
275
|
+
*/
|
|
276
|
+
#words = new Uint32Array(this.#data.buffer);
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* The grade as the bake reads it: {@link COLOR_GRADE_STRUCT}, then the three curves' keys, each
|
|
280
|
+
* {@link COLOR_GRADE_KEY_FLOATS} floats, with room for one key when there are none. The array is reused while the
|
|
281
|
+
* key count stays the same.
|
|
282
|
+
*
|
|
283
|
+
* @returns {Float32Array}
|
|
284
|
+
*/
|
|
285
|
+
pack() {
|
|
286
|
+
assert.isNumber(this.white_temperature, 'white_temperature');
|
|
287
|
+
assert.greaterThan(this.white_temperature, 0, 'white_temperature');
|
|
288
|
+
assert.isNumber(this.white_tint, 'white_tint');
|
|
289
|
+
|
|
290
|
+
const hue_count = this.hue_shift.keys.length;
|
|
291
|
+
const saturation_count = this.hue_saturation.keys.length;
|
|
292
|
+
const lightness_count = this.hue_lightness.keys.length;
|
|
293
|
+
|
|
294
|
+
const length = COLOR_GRADE_HEADER_FLOATS
|
|
295
|
+
+ COLOR_GRADE_KEY_FLOATS * Math.max(1, hue_count + saturation_count + lightness_count);
|
|
296
|
+
|
|
297
|
+
if (this.#data.length !== length) {
|
|
298
|
+
this.#data = new Float32Array(length);
|
|
299
|
+
this.#words = new Uint32Array(this.#data.buffer);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const out = this.#data;
|
|
303
|
+
|
|
304
|
+
m3_white_balance_rec709(scratch_m3, this.white_temperature, this.white_tint);
|
|
305
|
+
|
|
306
|
+
for (let column = 0; column < 3; column++) {
|
|
307
|
+
out[column * 4] = scratch_m3[column];
|
|
308
|
+
out[column * 4 + 1] = scratch_m3[3 + column];
|
|
309
|
+
out[column * 4 + 2] = scratch_m3[6 + column];
|
|
310
|
+
out[column * 4 + 3] = 0;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
write_zone(out, 12, this.shadows, this.global);
|
|
314
|
+
write_zone(out, 32, this.midtones, this.global);
|
|
315
|
+
write_zone(out, 52, this.highlights, this.global);
|
|
316
|
+
|
|
317
|
+
out[72] = this.shadows_max;
|
|
318
|
+
out[73] = this.highlights_min;
|
|
319
|
+
out[74] = this.highlights_max;
|
|
320
|
+
out[75] = 0;
|
|
321
|
+
|
|
322
|
+
const words = this.#words;
|
|
323
|
+
words[76] = hue_count;
|
|
324
|
+
words[77] = saturation_count;
|
|
325
|
+
words[78] = lightness_count;
|
|
326
|
+
words[79] = 0;
|
|
327
|
+
|
|
328
|
+
let at = COLOR_GRADE_HEADER_FLOATS;
|
|
329
|
+
at = write_keys(out, at, this.hue_shift);
|
|
330
|
+
at = write_keys(out, at, this.hue_saturation);
|
|
331
|
+
at = write_keys(out, at, this.hue_lightness);
|
|
332
|
+
|
|
333
|
+
out.fill(0, at);
|
|
334
|
+
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trilinear over a tone-mapping LUT. Clamp-to-edge, so a coordinate on the outer texel centres reads that texel
|
|
3
|
+
* alone; the LUT has no mips.
|
|
4
|
+
*
|
|
5
|
+
* @type {Readonly<SamplerDescriptor>}
|
|
6
|
+
*/
|
|
7
|
+
export const SAMPLER_TONEMAP_LUT: Readonly<SamplerDescriptor>;
|
|
8
|
+
import { SamplerDescriptor } from "../../../descriptor/texture/SamplerDescriptor.js";
|
|
9
|
+
//# sourceMappingURL=SAMPLER_TONEMAP_LUT.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SAMPLER_TONEMAP_LUT.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,kCAFU,SAAS,iBAAiB,CAAC,CAQjC;kCAd8B,kDAAkD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SamplerDescriptor } from "../../../descriptor/texture/SamplerDescriptor.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trilinear over a tone-mapping LUT. Clamp-to-edge, so a coordinate on the outer texel centres reads that texel
|
|
5
|
+
* alone; the LUT has no mips.
|
|
6
|
+
*
|
|
7
|
+
* @type {Readonly<SamplerDescriptor>}
|
|
8
|
+
*/
|
|
9
|
+
export const SAMPLER_TONEMAP_LUT = Object.freeze(SamplerDescriptor.from({
|
|
10
|
+
magFilter: "linear",
|
|
11
|
+
minFilter: "linear",
|
|
12
|
+
addressModeU: "clamp-to-edge",
|
|
13
|
+
addressModeV: "clamp-to-edge",
|
|
14
|
+
addressModeW: "clamp-to-edge",
|
|
15
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TONE_MAP_OPERATOR_ACES.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js"],"names":[],"mappings":"AAgFA;;GAEG;AACH,qCAFU,eAAe,CAEuC;gCAzEhC,sBAAsB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { chunk_CRM_FROM_REC709_TO_REC2020 } from "../../shader/chunk/color/conversion/chunk_CRM_FROM_REC709_TO_REC2020.js";
|
|
2
|
+
import { ACES2_BLOCK_FLOATS } from "../../shader/chunk/color/tonemap/aces/aces2_transform_block.js";
|
|
3
|
+
import { chunk_aces2_output_transform } from "../../shader/chunk/color/tonemap/aces/chunk_aces2_output_transform.js";
|
|
4
|
+
import { chunk_tonemap_ue_filmic } from "../../shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.js";
|
|
5
|
+
import { chunk_PAPER_WHITE_NITS, PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
|
|
6
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
7
|
+
import { graph_import_raw_buffer } from "../../shader/graph/graph_import_raw_buffer.js";
|
|
8
|
+
import { f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
9
|
+
import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
|
|
10
|
+
import { TonemapAces2Tables } from "./TonemapAces2Tables.js";
|
|
11
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
12
|
+
|
|
13
|
+
const chunk = CodeChunk.from(
|
|
14
|
+
//language=WGSL
|
|
15
|
+
`
|
|
16
|
+
const ACES2_SDR_BLOCK: u32 = 0u;
|
|
17
|
+
const ACES2_DISPLAY_BLOCK: u32 = ${ACES2_BLOCK_FLOATS}u;
|
|
18
|
+
|
|
19
|
+
fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32> {
|
|
20
|
+
// the SDR picture first, which is what Unreal 5.8 does with Filmic on any display
|
|
21
|
+
var picture = tonemap_ue_filmic(scene);
|
|
22
|
+
|
|
23
|
+
if (peak_nits > PAPER_WHITE_NITS) {
|
|
24
|
+
// back to the scene through ACES 2.0 at SDR white, then out again through ACES 2.0 at the display's peak over
|
|
25
|
+
// the paper white. Both transforms take SDR white for 100 cd/m² and both are limited to Rec.709, the SDR
|
|
26
|
+
// picture's own gamut, so as the headroom shrinks to none the picture becomes the SDR one.
|
|
27
|
+
picture = aces2_forward(ACES2_DISPLAY_BLOCK, aces2_inverse(ACES2_SDR_BLOCK, picture));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return CRM_FROM_REC709_TO_REC2020 * picture;
|
|
31
|
+
}
|
|
32
|
+
`, [
|
|
33
|
+
chunk_tonemap_ue_filmic,
|
|
34
|
+
chunk_aces2_output_transform,
|
|
35
|
+
chunk_CRM_FROM_REC709_TO_REC2020,
|
|
36
|
+
chunk_PAPER_WHITE_NITS,
|
|
37
|
+
]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Unreal Engine's default look, the tone mapper's default too.
|
|
42
|
+
*
|
|
43
|
+
* - **SDR** is UE's "Filmic" tone mapper at its default settings, the ACES-derived curve every Unreal title ships with
|
|
44
|
+
* unless it chose otherwise.
|
|
45
|
+
* - **HDR** is what Unreal 5.8 does with the same method: the SDR picture, taken back to the scene through the inverse
|
|
46
|
+
* ACES 2.0 output transform for an SDR display, and rendered again with the ACES 2.0 output transform for the
|
|
47
|
+
* display's headroom, both limited to Rec.709. A display at or under the paper white shows the SDR picture.
|
|
48
|
+
*
|
|
49
|
+
* An exposed 0.18 shows at 0.18 of SDR white, with a mid-tone contrast of 1.36 against GT7's 1.05. On HDR the picture
|
|
50
|
+
* expands into the headroom and mid-grey rises with it, by ACES 2.0's design: 0.26 of SDR white at 1000 cd/m².
|
|
51
|
+
*
|
|
52
|
+
* Binds `aces2_tables`, the two transforms' parameters and gamut tables, built by {@link TonemapAces2Tables} for the
|
|
53
|
+
* peak of each HDR bake.
|
|
54
|
+
*/
|
|
55
|
+
class ToneMapOperatorAces extends ToneMapOperator {
|
|
56
|
+
#tables = new TonemapAces2Tables();
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
super("aces", chunk);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare(group) {
|
|
63
|
+
group.addStorageBuffer("aces2_tables", WebGPUArray.from(f32));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
bind(graph, peak_nits, bindings) {
|
|
67
|
+
// an SDR bake never reads the tables, so they are not built for it
|
|
68
|
+
if (peak_nits > PAPER_WHITE_NITS) {
|
|
69
|
+
this.#tables.update(peak_nits);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
bindings.aces2_tables = graph_import_raw_buffer({
|
|
73
|
+
graph,
|
|
74
|
+
value: this.#tables.data.buffer,
|
|
75
|
+
label: "tonemap/aces2 tables",
|
|
76
|
+
usage: GPUBufferUsage.STORAGE,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @type {ToneMapOperator}
|
|
83
|
+
*/
|
|
84
|
+
export const TONE_MAP_OPERATOR_ACES = new ToneMapOperatorAces();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GT7 tone mapping (Polyphony Digital, SIGGRAPH 2025), in its own Rec.2020. An exposed 1.0 shows at the paper white
|
|
3
|
+
* on every display. On SDR the peak is the paper white, the curve's SDR mode, which clips there; HDR rolls off to the
|
|
4
|
+
* display's peak.
|
|
5
|
+
*
|
|
6
|
+
* @type {ToneMapOperator}
|
|
7
|
+
*/
|
|
8
|
+
export const TONE_MAP_OPERATOR_GT7: ToneMapOperator;
|
|
9
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
10
|
+
//# sourceMappingURL=TONE_MAP_OPERATOR_GT7.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TONE_MAP_OPERATOR_GT7.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,oCAFU,eAAe,CAatB;gCApB6B,sBAAsB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { chunk_CRM_FROM_REC709_TO_REC2020 } from "../../shader/chunk/color/conversion/chunk_CRM_FROM_REC709_TO_REC2020.js";
|
|
2
|
+
import { chunk_PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
|
|
3
|
+
import { chunk_tonemap_gt7 } from "../../shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.js";
|
|
4
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
5
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* GT7 tone mapping (Polyphony Digital, SIGGRAPH 2025), in its own Rec.2020. An exposed 1.0 shows at the paper white
|
|
9
|
+
* on every display. On SDR the peak is the paper white, the curve's SDR mode, which clips there; HDR rolls off to the
|
|
10
|
+
* display's peak.
|
|
11
|
+
*
|
|
12
|
+
* @type {ToneMapOperator}
|
|
13
|
+
*/
|
|
14
|
+
export const TONE_MAP_OPERATOR_GT7 = new ToneMapOperator("gt7", CodeChunk.from(
|
|
15
|
+
//language=WGSL
|
|
16
|
+
`
|
|
17
|
+
fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32> {
|
|
18
|
+
return tonemap_gt7_rec2020(CRM_FROM_REC709_TO_REC2020 * scene, peak_nits, PAPER_WHITE_NITS);
|
|
19
|
+
}
|
|
20
|
+
`, [
|
|
21
|
+
chunk_tonemap_gt7,
|
|
22
|
+
chunk_CRM_FROM_REC709_TO_REC2020,
|
|
23
|
+
chunk_PAPER_WHITE_NITS,
|
|
24
|
+
]
|
|
25
|
+
));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No tone mapping: the exposed colour as it is, with 1.0 at the paper white. An SDR output clips everything above
|
|
3
|
+
* it, and an HDR output shows it as far as the display reaches.
|
|
4
|
+
*
|
|
5
|
+
* @type {ToneMapOperator}
|
|
6
|
+
*/
|
|
7
|
+
export const TONE_MAP_OPERATOR_NONE: ToneMapOperator;
|
|
8
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
9
|
+
//# sourceMappingURL=TONE_MAP_OPERATOR_NONE.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TONE_MAP_OPERATOR_NONE.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,qCAFU,eAAe,CAWtB;gCAjB6B,sBAAsB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { chunk_CRM_FROM_REC709_TO_REC2020 } from "../../shader/chunk/color/conversion/chunk_CRM_FROM_REC709_TO_REC2020.js";
|
|
2
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
3
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* No tone mapping: the exposed colour as it is, with 1.0 at the paper white. An SDR output clips everything above
|
|
7
|
+
* it, and an HDR output shows it as far as the display reaches.
|
|
8
|
+
*
|
|
9
|
+
* @type {ToneMapOperator}
|
|
10
|
+
*/
|
|
11
|
+
export const TONE_MAP_OPERATOR_NONE = new ToneMapOperator("none", CodeChunk.from(
|
|
12
|
+
//language=WGSL
|
|
13
|
+
`
|
|
14
|
+
fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32> {
|
|
15
|
+
return CRM_FROM_REC709_TO_REC2020 * scene;
|
|
16
|
+
}
|
|
17
|
+
`, [
|
|
18
|
+
chunk_CRM_FROM_REC709_TO_REC2020,
|
|
19
|
+
]
|
|
20
|
+
));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Khronos PBR Neutral (Lalish, 2024). Base colours under 0.8 come out as they are, less a 0.04 Fresnel offset, and
|
|
3
|
+
* hues never shift: made for showing products. SDR is the specification, which rolls highlights off to SDR white
|
|
4
|
+
* and toward white. HDR puts the display's peak over the paper white in place of the specification's 1, so
|
|
5
|
+
* everything below the compression start looks the same on both outputs; a display under the paper white gets the
|
|
6
|
+
* SDR form.
|
|
7
|
+
*
|
|
8
|
+
* An exposed 0.18 shows at 0.14 of SDR white, where GT7 shows it at 0.179.
|
|
9
|
+
*
|
|
10
|
+
* @type {ToneMapOperator}
|
|
11
|
+
*/
|
|
12
|
+
export const TONE_MAP_OPERATOR_PBR_NEUTRAL: ToneMapOperator;
|
|
13
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
14
|
+
//# sourceMappingURL=TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,4CAFU,eAAe,CActB;gCAzB6B,sBAAsB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { chunk_CRM_FROM_REC709_TO_REC2020 } from "../../shader/chunk/color/conversion/chunk_CRM_FROM_REC709_TO_REC2020.js";
|
|
2
|
+
import { chunk_PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
|
|
3
|
+
import { chunk_tonemap_khronos_pbr } from "../../shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.js";
|
|
4
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
5
|
+
import { ToneMapOperator } from "./ToneMapOperator.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Khronos PBR Neutral (Lalish, 2024). Base colours under 0.8 come out as they are, less a 0.04 Fresnel offset, and
|
|
9
|
+
* hues never shift: made for showing products. SDR is the specification, which rolls highlights off to SDR white
|
|
10
|
+
* and toward white. HDR puts the display's peak over the paper white in place of the specification's 1, so
|
|
11
|
+
* everything below the compression start looks the same on both outputs; a display under the paper white gets the
|
|
12
|
+
* SDR form.
|
|
13
|
+
*
|
|
14
|
+
* An exposed 0.18 shows at 0.14 of SDR white, where GT7 shows it at 0.179.
|
|
15
|
+
*
|
|
16
|
+
* @type {ToneMapOperator}
|
|
17
|
+
*/
|
|
18
|
+
export const TONE_MAP_OPERATOR_PBR_NEUTRAL = new ToneMapOperator("pbr neutral", CodeChunk.from(
|
|
19
|
+
//language=WGSL
|
|
20
|
+
`
|
|
21
|
+
fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32> {
|
|
22
|
+
let peak = max(peak_nits / PAPER_WHITE_NITS, 1.0);
|
|
23
|
+
return CRM_FROM_REC709_TO_REC2020 * tonemap_khronos_pbr(max(scene, vec3<f32>(0.0)), peak);
|
|
24
|
+
}
|
|
25
|
+
`, [
|
|
26
|
+
chunk_tonemap_khronos_pbr,
|
|
27
|
+
chunk_CRM_FROM_REC709_TO_REC2020,
|
|
28
|
+
chunk_PAPER_WHITE_NITS,
|
|
29
|
+
]
|
|
30
|
+
));
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("../../shader/compiler/CodeChunk.js").CodeChunk} CodeChunk
|
|
3
|
+
* @typedef {import("../../shader/resource/ShaderResourceGroupDescriptor.js").ShaderResourceGroupDescriptor} ShaderResourceGroupDescriptor
|
|
4
|
+
* @typedef {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* A tone-mapping function, in WGSL, that {@link ToneMapper} bakes into its LUTs.
|
|
8
|
+
*
|
|
9
|
+
* {@link chunk} defines
|
|
10
|
+
*
|
|
11
|
+
* fn tone_map_operator(scene: vec3<f32>, peak_nits: f32) -> vec3<f32>
|
|
12
|
+
*
|
|
13
|
+
* - `scene`: exposed linear Rec.709, 1 at the paper white. Not negative; the LUT's encoding clamps at zero.
|
|
14
|
+
* - `peak_nits`: the display's peak in cd/m². An SDR display is `PAPER_WHITE_NITS`.
|
|
15
|
+
* - returns linear Rec.2020 display light, 1 at the paper white (`PAPER_WHITE_NITS`).
|
|
16
|
+
*
|
|
17
|
+
* An operator whose chunk reads bindings of its own adds them in {@link declare} and supplies them in {@link bind}.
|
|
18
|
+
* The chunk is linked once into its bake shader, so its text must not change after first use.
|
|
19
|
+
*/
|
|
20
|
+
export class ToneMapOperator {
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} label
|
|
23
|
+
* @param {CodeChunk} chunk defines `tone_map_operator`, see the class
|
|
24
|
+
*/
|
|
25
|
+
constructor(label: string, chunk: CodeChunk);
|
|
26
|
+
/**
|
|
27
|
+
* @readonly
|
|
28
|
+
* @type {string}
|
|
29
|
+
*/
|
|
30
|
+
readonly label: string;
|
|
31
|
+
/**
|
|
32
|
+
* @readonly
|
|
33
|
+
* @type {CodeChunk}
|
|
34
|
+
*/
|
|
35
|
+
readonly chunk: CodeChunk;
|
|
36
|
+
/**
|
|
37
|
+
* Add the bindings {@link chunk} reads to the bake shader's group. None by default.
|
|
38
|
+
*
|
|
39
|
+
* @param {ShaderResourceGroupDescriptor} group
|
|
40
|
+
*/
|
|
41
|
+
declare(group: ShaderResourceGroupDescriptor): void;
|
|
42
|
+
/**
|
|
43
|
+
* Supply the bindings {@link declare} added, for a bake at `peak_nits`. None by default.
|
|
44
|
+
*
|
|
45
|
+
* @param {FrameGraph} graph the frame the bake is recorded into
|
|
46
|
+
* @param {number} peak_nits
|
|
47
|
+
* @param {Object} bindings the bake pass's bindings, to add to by name
|
|
48
|
+
*/
|
|
49
|
+
bind(graph: FrameGraph, peak_nits: number, bindings: any): void;
|
|
50
|
+
}
|
|
51
|
+
export type CodeChunk = import("../../shader/compiler/CodeChunk.js").CodeChunk;
|
|
52
|
+
export type ShaderResourceGroupDescriptor = import("../../shader/resource/ShaderResourceGroupDescriptor.js").ShaderResourceGroupDescriptor;
|
|
53
|
+
export type FrameGraph = import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
54
|
+
//# sourceMappingURL=ToneMapOperator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToneMapOperator.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/ToneMapOperator.js"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AACH;IACI;;;OAGG;IACH,mBAHW,MAAM,SACN,SAAS,EAkBnB;IAXG;;;OAGG;IACH,gBAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,gBAFU,SAAS,CAED;IAGtB;;;;OAIG;IACH,eAFW,6BAA6B,QAGvC;IAED;;;;;;OAMG;IACH,YAJW,UAAU,aACV,MAAM,uBAIhB;CACJ;wBA3DY,OAAO,oCAAoC,EAAE,SAAS;4CACtD,OAAO,wDAAwD,EAAE,6BAA6B;yBAC9F,OAAO,8DAA8D,EAAE,UAAU"}
|