@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.
Files changed (190) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/package.json +1 -1
  3. package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts +14 -0
  4. package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts.map +1 -0
  5. package/src/core/color/xyz/m3_chromatic_adaptation_bradford.js +51 -0
  6. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +2 -1
  7. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -1
  8. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +51 -70
  9. package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -1
  10. package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +8 -64
  11. package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts +17 -0
  12. package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts.map +1 -0
  13. package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.js +64 -0
  14. package/src/core/math/linalg/solve_box_constrained_qp.d.ts +30 -0
  15. package/src/core/math/linalg/solve_box_constrained_qp.d.ts.map +1 -0
  16. package/src/core/math/linalg/solve_box_constrained_qp.js +205 -0
  17. package/src/engine/graphics/texture/sampler/exr_to_sampler2d.d.ts +27 -0
  18. package/src/engine/graphics/texture/sampler/exr_to_sampler2d.d.ts.map +1 -0
  19. package/src/engine/graphics/texture/sampler/exr_to_sampler2d.js +91 -0
  20. package/src/engine/graphics/texture/sampler/sampler2d_to_exr.d.ts +23 -0
  21. package/src/engine/graphics/texture/sampler/sampler2d_to_exr.d.ts.map +1 -0
  22. package/src/engine/graphics/texture/sampler/sampler2d_to_exr.js +64 -0
  23. package/src/engine/physics/constraint/soft_spring_coefficients.d.ts +24 -0
  24. package/src/engine/physics/constraint/soft_spring_coefficients.d.ts.map +1 -0
  25. package/src/engine/physics/constraint/soft_spring_coefficients.js +38 -0
  26. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  27. package/src/engine/physics/constraint/solve_constraints.js +16 -8
  28. package/src/engine/physics/ecs/PhysicsSystem.d.ts +54 -0
  29. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  30. package/src/engine/physics/ecs/PhysicsSystem.js +192 -7
  31. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  32. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +3 -5
  33. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  34. package/src/engine/physics/inertia/world_inverse_inertia.js +3 -5
  35. package/src/engine/physics/vehicle/RaycastVehicle.d.ts +183 -12
  36. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  37. package/src/engine/physics/vehicle/RaycastVehicle.js +1046 -121
  38. package/src/format/image/exr/ExrCompression.d.ts +22 -0
  39. package/src/format/image/exr/ExrCompression.d.ts.map +1 -0
  40. package/src/format/image/exr/ExrCompression.js +27 -0
  41. package/src/format/image/exr/ExrImage.d.ts +32 -0
  42. package/src/format/image/exr/ExrImage.d.ts.map +1 -0
  43. package/src/format/image/exr/ExrImage.js +32 -0
  44. package/src/format/image/exr/ExrPixelType.d.ts +13 -0
  45. package/src/format/image/exr/ExrPixelType.d.ts.map +1 -0
  46. package/src/format/image/exr/ExrPixelType.js +18 -0
  47. package/src/format/image/exr/exr_compare_names.d.ts +16 -0
  48. package/src/format/image/exr/exr_compare_names.d.ts.map +1 -0
  49. package/src/format/image/exr/exr_compare_names.js +25 -0
  50. package/src/format/image/exr/exr_constants.d.ts +49 -0
  51. package/src/format/image/exr/exr_constants.d.ts.map +1 -0
  52. package/src/format/image/exr/exr_constants.js +56 -0
  53. package/src/format/image/exr/exr_read.d.ts +32 -0
  54. package/src/format/image/exr/exr_read.d.ts.map +1 -0
  55. package/src/format/image/exr/exr_read.js +531 -0
  56. package/src/format/image/exr/exr_sample_bits.d.ts +16 -0
  57. package/src/format/image/exr/exr_sample_bits.d.ts.map +1 -0
  58. package/src/format/image/exr/exr_sample_bits.js +21 -0
  59. package/src/format/image/exr/exr_scanlines_per_chunk.d.ts +17 -0
  60. package/src/format/image/exr/exr_scanlines_per_chunk.d.ts.map +1 -0
  61. package/src/format/image/exr/exr_scanlines_per_chunk.js +31 -0
  62. package/src/format/image/exr/exr_write.d.ts +27 -0
  63. package/src/format/image/exr/exr_write.d.ts.map +1 -0
  64. package/src/format/image/exr/exr_write.js +378 -0
  65. package/src/shade/playground/probe_clipmap/index.html +5 -0
  66. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  67. package/src/shade/playground/probe_clipmap/main.js +34 -1
  68. package/src/shade/playground/tonemap_sdr/README.md +11 -8
  69. package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +2 -2
  70. package/src/shade/renderer/Renderer.d.ts +5 -6
  71. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  72. package/src/shade/renderer/Renderer.js +15 -88
  73. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts +14 -0
  74. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts.map +1 -0
  75. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.js +62 -0
  76. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +158 -0
  77. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -0
  78. package/src/shade/renderer/deferred/tonemap/ColorGrade.js +337 -0
  79. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts +9 -0
  80. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts.map +1 -0
  81. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js +15 -0
  82. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts +6 -0
  83. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts.map +1 -0
  84. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js +84 -0
  85. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts +10 -0
  86. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts.map +1 -0
  87. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js +25 -0
  88. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts +9 -0
  89. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts.map +1 -0
  90. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js +20 -0
  91. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts +14 -0
  92. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map +1 -0
  93. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js +30 -0
  94. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts +54 -0
  95. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts.map +1 -0
  96. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.js +63 -0
  97. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +106 -0
  98. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -0
  99. package/src/shade/renderer/deferred/tonemap/ToneMapper.js +474 -0
  100. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +5 -13
  101. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -1
  102. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +5 -44
  103. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts +7 -25
  104. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -1
  105. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js +11 -51
  106. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts +20 -0
  107. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts.map +1 -0
  108. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js +103 -0
  109. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +9 -0
  110. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -0
  111. package/src/shade/renderer/deferred/tonemap/{shader_tonemap_HDR_none.js → shader_tonemap_HDR_lut.js} +22 -18
  112. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +9 -0
  113. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -0
  114. package/src/shade/renderer/deferred/tonemap/{shader_tonemap_LDR_aces.js → shader_tonemap_LDR_lut.js} +24 -24
  115. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts +23 -0
  116. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts.map +1 -0
  117. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js +92 -0
  118. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts +15 -0
  119. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts.map +1 -0
  120. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js +73 -0
  121. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  122. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  123. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  124. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  125. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  126. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +3 -15
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +4 -17
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +3 -3
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +15 -13
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +7 -3
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +28 -17
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +18 -18
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +44 -48
  139. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  140. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  141. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +22 -0
  142. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -0
  143. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +62 -0
  144. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +13 -0
  145. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -0
  146. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +140 -0
  147. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts +11 -0
  148. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map +1 -0
  149. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js +65 -0
  150. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts +14 -0
  151. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts.map +1 -0
  152. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js +38 -0
  153. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts +16 -0
  154. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts.map +1 -0
  155. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.js +41 -0
  156. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +8 -0
  157. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
  158. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +21 -3
  159. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  160. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -8
  161. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  162. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
  163. package/src/shade/renderer/ShadeToneMappingMode.d.ts +0 -15
  164. package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +0 -1
  165. package/src/shade/renderer/ShadeToneMappingMode.js +0 -41
  166. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts +0 -9
  167. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +0 -1
  168. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.js +0 -79
  169. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +0 -17
  170. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +0 -1
  171. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +0 -101
  172. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts +0 -9
  173. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +0 -1
  174. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts +0 -10
  175. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
  176. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.js +0 -80
  177. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts +0 -9
  178. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +0 -1
  179. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.js +0 -80
  180. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +0 -10
  181. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +0 -1
  182. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts +0 -9
  183. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +0 -1
  184. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.js +0 -71
  185. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts +0 -10
  186. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
  187. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.js +0 -76
  188. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts +0 -3
  189. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts.map +0 -1
  190. 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,6 @@
1
+ /**
2
+ * @type {ToneMapOperator}
3
+ */
4
+ export const TONE_MAP_OPERATOR_ACES: ToneMapOperator;
5
+ import { ToneMapOperator } from "./ToneMapOperator.js";
6
+ //# sourceMappingURL=TONE_MAP_OPERATOR_ACES.d.ts.map
@@ -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"}