@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
@@ -7,18 +7,18 @@ import {
7
7
  import { PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
8
8
 
9
9
  /**
10
- * What {@link shader_tonemap_HDR_aces} binds as `aces2_tables`: two ACES 2.0 output transforms, each its parameters and
10
+ * What the ACES tone-map operator binds as `aces2_tables`: two ACES 2.0 output transforms, each its parameters and
11
11
  * gamut tables, both limited to Rec.709, the gamut of the SDR picture they expand.
12
12
  *
13
- * 1. An SDR display, 100 cd/m². The pass runs it backwards, from the SDR picture to the scene.
13
+ * 1. An SDR display, 100 cd/m². The operator runs it backwards, from the SDR picture to the scene.
14
14
  * 2. This display: the peak over the paper white, times 100 cd/m². A display at or under the paper white gets
15
- * 100 cd/m², which the pass does not read.
15
+ * 100 cd/m², which the operator does not read.
16
16
  *
17
17
  * Both take SDR white for 100 cd/m², ACES 2.0's reference, so an SDR picture expanded for a display keeps SDR white
18
18
  * where the paper white puts it.
19
19
  *
20
- * Building one transform takes 7 to 13 ms, so the tables are built on the first {@link update} rather than with the
21
- * renderer, and again only when the display's peak changes.
20
+ * Building one transform takes 7 to 13 ms, so the tables are built on the first {@link update}, and again only when
21
+ * the display's peak changes.
22
22
  */
23
23
  export class TonemapAces2Tables {
24
24
  /**
@@ -29,13 +29,6 @@ export class TonemapAces2Tables {
29
29
 
30
30
  #peak_nits = NaN;
31
31
 
32
- /**
33
- * @type {GPUBuffer|null}
34
- */
35
- #buffer = null;
36
-
37
- #uploaded = false;
38
-
39
32
  /**
40
33
  * Build the tables for a display, if they are not built for it already.
41
34
  *
@@ -59,39 +52,7 @@ export class TonemapAces2Tables {
59
52
  aces2_transform_block_write(this.data, ACES2_BLOCK_FLOATS, 100 * headroom, ACES2_LIMITING_REC709);
60
53
 
61
54
  this.#peak_nits = peak_nits;
62
- this.#uploaded = false;
63
55
 
64
56
  return true;
65
57
  }
66
-
67
- /**
68
- * The tables on the device, written if they changed since the last call.
69
- *
70
- * @param {GPUDevice} device
71
- * @returns {GPUBuffer}
72
- */
73
- gpu_buffer(device) {
74
- if (this.#buffer === null) {
75
- this.#buffer = device.createBuffer({
76
- label: "tonemap/aces2 tables",
77
- size: this.data.byteLength,
78
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
79
- });
80
- this.#uploaded = false;
81
- }
82
-
83
- if (!this.#uploaded) {
84
- device.queue.writeBuffer(this.#buffer, 0, this.data);
85
- this.#uploaded = true;
86
- }
87
-
88
- return this.#buffer;
89
- }
90
-
91
- destroy() {
92
- if (this.#buffer !== null) {
93
- this.#buffer.destroy();
94
- this.#buffer = null;
95
- }
96
- }
97
58
  }
@@ -1,22 +1,18 @@
1
1
  /**
2
- * The immediate data every tonemap pass reads: the colour space the canvas actually shows, and the display's peak.
2
+ * What the tone mapper is told about the display: the colour space the canvas actually shows, and the display's peak.
3
3
  *
4
- * A pass's immediate struct names only the members it reads. The GT7 passes leave the operator in Rec.2020 and read
5
- * `display_from_rec2020_*`; the others work in Rec.709 and read `display_from_rec709_*`; only the HDR passes read
6
- * `peak_nits`. So one instance serves whichever pass is current.
4
+ * The apply passes read the matrix from linear Rec.2020, the LUT's output, to the canvas's linear primaries, as
5
+ * {@link TONEMAP_SETTINGS}. The peak is what an HDR LUT is baked for.
7
6
  *
8
- * Each matrix is three columns, not a `mat3x3f`: a `mat3x3f` pads each column to 16 bytes and the immediate
7
+ * The matrix is three columns, not a `mat3x3f`: a `mat3x3f` pads each column to 16 bytes and the immediate
9
8
  * serialiser writes its nine floats end to end.
10
9
  */
11
10
  export class TonemapDisplaySettings {
12
- display_from_rec709_c0: Float32Array;
13
- display_from_rec709_c1: Float32Array;
14
- display_from_rec709_c2: Float32Array;
15
11
  display_from_rec2020_c0: Float32Array;
16
12
  display_from_rec2020_c1: Float32Array;
17
13
  display_from_rec2020_c2: Float32Array;
18
14
  /**
19
- * The display's peak, cd/m². Read by the HDR passes only.
15
+ * The display's peak, cd/m². An HDR LUT is baked for it.
20
16
  * @type {number}
21
17
  */
22
18
  peak_nits: number;
@@ -29,22 +25,8 @@ export class TonemapDisplaySettings {
29
25
  set_canvas_color_space(color_space: PredefinedColorSpace | string): void;
30
26
  }
31
27
  /**
32
- * Immediate data of a pass that works in Rec.709. Filled by {@link TonemapDisplaySettings}.
28
+ * Immediate data of the tone mapper's apply passes. Filled by {@link TonemapDisplaySettings}.
33
29
  */
34
- export const TONEMAP_SETTINGS_REC709: WebGPUStruct;
35
- /**
36
- * Immediate data of a pass that works in Rec.709 and is told the display's peak. Filled by {@link
37
- * TonemapDisplaySettings}.
38
- */
39
- export const TONEMAP_SETTINGS_REC709_PEAK: WebGPUStruct;
40
- /**
41
- * Immediate data of a pass that works in Rec.2020. Filled by {@link TonemapDisplaySettings}.
42
- */
43
- export const TONEMAP_SETTINGS_REC2020: WebGPUStruct;
44
- /**
45
- * Immediate data of a pass that works in Rec.2020 and is told the display's peak. Filled by {@link
46
- * TonemapDisplaySettings}.
47
- */
48
- export const TONEMAP_SETTINGS_REC2020_PEAK: WebGPUStruct;
30
+ export const TONEMAP_SETTINGS: WebGPUStruct;
49
31
  import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
50
32
  //# sourceMappingURL=TonemapDisplaySettings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TonemapDisplaySettings.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js"],"names":[],"mappings":"AAiDA;;;;;;;;;GASG;AACH;IACI,qCAAqD;IACrD,qCAAqD;IACrD,qCAAqD;IAErD,sCAA8C;IAC9C,sCAA8C;IAC9C,sCAA8C;IAE9C;;;OAGG;IACH,WAFU,MAAM,CAEC;IAMjB;;;;;OAKG;IACH,oCAHW,oBAAoB,GAAC,MAAM,QAkBrC;CACJ;AAqBD;;GAEG;AACH,mDAAqF;AAErF;;;GAGG;AACH,wDAAmG;AAEnG;;GAEG;AACH,oDAAuF;AAEvF;;;GAGG;AACH,yDAAqG;6BAzIxE,mCAAmC"}
1
+ {"version":3,"file":"TonemapDisplaySettings.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js"],"names":[],"mappings":"AAiDA;;;;;;;;GAQG;AACH;IACI,sCAA8C;IAC9C,sCAA8C;IAC9C,sCAA8C;IAE9C;;;OAGG;IACH,WAFU,MAAM,CAEC;IAMjB;;;;;OAKG;IACH,oCAHW,oBAAoB,GAAC,MAAM,QAcrC;CACJ;AAED;;GAEG;AACH,4CAKG;6BAjG0B,mCAAmC"}
@@ -1,7 +1,7 @@
1
1
  import { m3_rgb_to_xyz_from_primaries } from "../../../../core/color/xyz/m3_rgb_to_xyz_from_primaries.js";
2
2
  import { m3_invert } from "../../../../core/geom/mat3/m3_invert.js";
3
3
  import { m3_multiply } from "../../../../core/geom/mat3/m3_multiply.js";
4
- import { f32, vec3f } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
4
+ import { vec3f } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
5
5
  import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
6
6
 
7
7
  // chromaticities of red, green and blue; every space here has a D65 white, so none needs chromatic adaptation
@@ -48,26 +48,21 @@ function write_columns(c0, c1, c2, from, to) {
48
48
  }
49
49
 
50
50
  /**
51
- * The immediate data every tonemap pass reads: the colour space the canvas actually shows, and the display's peak.
51
+ * What the tone mapper is told about the display: the colour space the canvas actually shows, and the display's peak.
52
52
  *
53
- * A pass's immediate struct names only the members it reads. The GT7 passes leave the operator in Rec.2020 and read
54
- * `display_from_rec2020_*`; the others work in Rec.709 and read `display_from_rec709_*`; only the HDR passes read
55
- * `peak_nits`. So one instance serves whichever pass is current.
53
+ * The apply passes read the matrix from linear Rec.2020, the LUT's output, to the canvas's linear primaries, as
54
+ * {@link TONEMAP_SETTINGS}. The peak is what an HDR LUT is baked for.
56
55
  *
57
- * Each matrix is three columns, not a `mat3x3f`: a `mat3x3f` pads each column to 16 bytes and the immediate
56
+ * The matrix is three columns, not a `mat3x3f`: a `mat3x3f` pads each column to 16 bytes and the immediate
58
57
  * serialiser writes its nine floats end to end.
59
58
  */
60
59
  export class TonemapDisplaySettings {
61
- display_from_rec709_c0 = new Float32Array([1, 0, 0]);
62
- display_from_rec709_c1 = new Float32Array([0, 1, 0]);
63
- display_from_rec709_c2 = new Float32Array([0, 0, 1]);
64
-
65
60
  display_from_rec2020_c0 = new Float32Array(3);
66
61
  display_from_rec2020_c1 = new Float32Array(3);
67
62
  display_from_rec2020_c2 = new Float32Array(3);
68
63
 
69
64
  /**
70
- * The display's peak, cd/m². Read by the HDR passes only.
65
+ * The display's peak, cd/m². An HDR LUT is baked for it.
71
66
  * @type {number}
72
67
  */
73
68
  peak_nits = 1000;
@@ -89,10 +84,6 @@ export class TonemapDisplaySettings {
89
84
  throw new Error(`Canvas colorSpace '${color_space}' is not one the tonemap passes can write`);
90
85
  }
91
86
 
92
- write_columns(
93
- this.display_from_rec709_c0, this.display_from_rec709_c1, this.display_from_rec709_c2,
94
- PRIMARIES_REC709, display
95
- );
96
87
  write_columns(
97
88
  this.display_from_rec2020_c0, this.display_from_rec2020_c1, this.display_from_rec2020_c2,
98
89
  PRIMARIES_REC2020, display
@@ -100,43 +91,12 @@ export class TonemapDisplaySettings {
100
91
  }
101
92
  }
102
93
 
103
- const display_from_rec709 = {
104
- /** column 0 of the matrix from linear Rec.709 to the canvas's linear primaries */
105
- display_from_rec709_c0: vec3f,
106
- display_from_rec709_c1: vec3f,
107
- display_from_rec709_c2: vec3f,
108
- };
109
-
110
- const display_from_rec2020 = {
94
+ /**
95
+ * Immediate data of the tone mapper's apply passes. Filled by {@link TonemapDisplaySettings}.
96
+ */
97
+ export const TONEMAP_SETTINGS = WebGPUStruct.from({
111
98
  /** column 0 of the matrix from linear Rec.2020 to the canvas's linear primaries */
112
99
  display_from_rec2020_c0: vec3f,
113
100
  display_from_rec2020_c1: vec3f,
114
101
  display_from_rec2020_c2: vec3f,
115
- };
116
-
117
- /**
118
- * The display's peak, cd/m². The paper white is not a setting: it is PAPER_WHITE_NITS on both outputs.
119
- */
120
- const peak = { peak_nits: f32 };
121
-
122
- /**
123
- * Immediate data of a pass that works in Rec.709. Filled by {@link TonemapDisplaySettings}.
124
- */
125
- export const TONEMAP_SETTINGS_REC709 = WebGPUStruct.from({ ...display_from_rec709 });
126
-
127
- /**
128
- * Immediate data of a pass that works in Rec.709 and is told the display's peak. Filled by {@link
129
- * TonemapDisplaySettings}.
130
- */
131
- export const TONEMAP_SETTINGS_REC709_PEAK = WebGPUStruct.from({ ...display_from_rec709, ...peak });
132
-
133
- /**
134
- * Immediate data of a pass that works in Rec.2020. Filled by {@link TonemapDisplaySettings}.
135
- */
136
- export const TONEMAP_SETTINGS_REC2020 = WebGPUStruct.from({ ...display_from_rec2020 });
137
-
138
- /**
139
- * Immediate data of a pass that works in Rec.2020 and is told the display's peak. Filled by {@link
140
- * TonemapDisplaySettings}.
141
- */
142
- export const TONEMAP_SETTINGS_REC2020_PEAK = WebGPUStruct.from({ ...display_from_rec2020, ...peak });
102
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Unreal's temperature white balance (`WhiteBalance` in `TonemapCommon.ush`, the default "White Balance" mode) on
3
+ * linear Rec.709, as a matrix. Light from a white at `temperature` K, moved along its isotherm by `tint`, becomes
4
+ * neutral: a lower temperature cools the picture.
5
+ *
6
+ * The source white is on the Planckian locus below 4000 K and on the CIE daylight locus from there, as Unreal's is,
7
+ * and the adaptation to D65 is Bradford. At 6500 K and no tint, where Unreal skips the stage, the matrix is the
8
+ * identity.
9
+ *
10
+ * @param {Float32Array|Float64Array|number[]} out 9 elements, row-major
11
+ * @param {number} temperature K
12
+ * @param {number} tint offset along the isotherm, in units of 0.05 in CIE 1960 uv; Unreal's range is -1 to 1
13
+ */
14
+ export function m3_white_balance_rec709(out: Float32Array | Float64Array | number[], temperature: number, tint: number): void;
15
+ /**
16
+ * The temperature white balance is neutral at these, and Unreal skips it there.
17
+ */
18
+ export const WHITE_BALANCE_NEUTRAL_TEMPERATURE: 6500;
19
+ export const WHITE_BALANCE_NEUTRAL_TINT: 0;
20
+ //# sourceMappingURL=m3_white_balance_rec709.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"m3_white_balance_rec709.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;GAYG;AACH,6CAJW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,eAClC,MAAM,QACN,MAAM,QAsDhB;AAxFD;;GAEG;AACH,qDAAsD;AACtD,2CAA4C"}
@@ -0,0 +1,103 @@
1
+ import { m3_chromatic_adaptation_bradford } from "../../../../core/color/xyz/m3_chromatic_adaptation_bradford.js";
2
+ import { m3_rgb_to_xyz_from_primaries } from "../../../../core/color/xyz/m3_rgb_to_xyz_from_primaries.js";
3
+ import { m3_invert } from "../../../../core/geom/mat3/m3_invert.js";
4
+ import { m3_multiply } from "../../../../core/geom/mat3/m3_multiply.js";
5
+
6
+ const D65_X = 0.3127;
7
+ const D65_Y = 0.3290;
8
+
9
+ const REC709_TO_XYZ = new Float64Array(9);
10
+ m3_rgb_to_xyz_from_primaries(REC709_TO_XYZ, [0.640, 0.330, 0.300, 0.600, 0.150, 0.060], D65_X, D65_Y);
11
+
12
+ const XYZ_TO_REC709 = new Float64Array(9);
13
+ m3_invert(XYZ_TO_REC709, REC709_TO_XYZ);
14
+
15
+ /**
16
+ * The temperature white balance is neutral at these, and Unreal skips it there.
17
+ */
18
+ export const WHITE_BALANCE_NEUTRAL_TEMPERATURE = 6500;
19
+ export const WHITE_BALANCE_NEUTRAL_TINT = 0;
20
+
21
+ /**
22
+ * Chromaticity of the Planckian locus at `temperature` K, Krystek's rational fit in CIE 1960 uv, as Unreal's
23
+ * `PlanckianLocusChromaticity`.
24
+ *
25
+ * @param {number[]} out [x, y]
26
+ * @param {number} temperature
27
+ */
28
+ function planckian_locus_uv(out, temperature) {
29
+ const t = temperature;
30
+ out[0] = (0.860117757 + 1.54118254e-4 * t + 1.28641212e-7 * t * t) / (1 + 8.42420235e-4 * t + 7.08145163e-7 * t * t);
31
+ out[1] = (0.317398726 + 4.22806245e-5 * t + 4.20481691e-8 * t * t) / (1 - 2.89741816e-5 * t + 1.61456053e-7 * t * t);
32
+ }
33
+
34
+ const scratch_uv = [0, 0];
35
+ const scratch_cat = new Float64Array(9);
36
+ const scratch_m = new Float64Array(9);
37
+
38
+ /**
39
+ * Unreal's temperature white balance (`WhiteBalance` in `TonemapCommon.ush`, the default "White Balance" mode) on
40
+ * linear Rec.709, as a matrix. Light from a white at `temperature` K, moved along its isotherm by `tint`, becomes
41
+ * neutral: a lower temperature cools the picture.
42
+ *
43
+ * The source white is on the Planckian locus below 4000 K and on the CIE daylight locus from there, as Unreal's is,
44
+ * and the adaptation to D65 is Bradford. At 6500 K and no tint, where Unreal skips the stage, the matrix is the
45
+ * identity.
46
+ *
47
+ * @param {Float32Array|Float64Array|number[]} out 9 elements, row-major
48
+ * @param {number} temperature K
49
+ * @param {number} tint offset along the isotherm, in units of 0.05 in CIE 1960 uv; Unreal's range is -1 to 1
50
+ */
51
+ export function m3_white_balance_rec709(out, temperature, tint) {
52
+ if (temperature === WHITE_BALANCE_NEUTRAL_TEMPERATURE && tint === WHITE_BALANCE_NEUTRAL_TINT) {
53
+ out.fill(0);
54
+ out[0] = 1;
55
+ out[4] = 1;
56
+ out[8] = 1;
57
+ return;
58
+ }
59
+
60
+ let x, y;
61
+
62
+ if (temperature < 4000) {
63
+ planckian_locus_uv(scratch_uv, temperature);
64
+ const [u, v] = scratch_uv;
65
+ const d = 2 * u - 8 * v + 4;
66
+ x = 3 * u / d;
67
+ y = 2 * v / d;
68
+ } else {
69
+ // the CIE daylight locus, with the temperature corrected for the revision of Planck's c2, so 6500 is D65
70
+ const t = temperature * 1.4388 / 1.438;
71
+ const r = 1 / t;
72
+
73
+ x = t <= 7000
74
+ ? 0.244063 + (0.09911e3 + (2.9678e6 - 4.6070e9 * r) * r) * r
75
+ : 0.237040 + (0.24748e3 + (1.9018e6 - 2.0064e9 * r) * r) * r;
76
+ y = -3 * x * x + 2.87 * x - 0.275;
77
+ }
78
+
79
+ {
80
+ // along the isotherm, the normal to the Planckian locus in uv, by the tint
81
+ const t = temperature;
82
+ planckian_locus_uv(scratch_uv, t);
83
+ const [u, v] = scratch_uv;
84
+
85
+ const ud = (-1.13758118e9 - 1.91615621e6 * t - 1.53177 * t * t) / ((1.41213984e6 + 1189.62 * t + t * t) ** 2);
86
+ const vd = (1.97471536e9 - 705674.0 * t - 308.607 * t * t) / ((6.19363586e6 - 179.456 * t + t * t) ** 2);
87
+ const length = Math.hypot(ud, vd);
88
+
89
+ const iu = u + vd / length * tint * 0.05;
90
+ const iv = v - ud / length * tint * 0.05;
91
+
92
+ const d0 = 2 * u - 8 * v + 4;
93
+ const d1 = 2 * iu - 8 * iv + 4;
94
+
95
+ x += 3 * iu / d1 - 3 * u / d0;
96
+ y += 2 * iv / d1 - 2 * v / d0;
97
+ }
98
+
99
+ m3_chromatic_adaptation_bradford(scratch_cat, x, y, D65_X, D65_Y);
100
+
101
+ m3_multiply(scratch_m, scratch_cat, REC709_TO_XYZ);
102
+ m3_multiply(out, XYZ_TO_REC709, scratch_m);
103
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The HDR output of {@link ToneMapper}: exposure, then the HDR LUT, written in the canvas's primaries, extended, where
3
+ * 1.0 is SDR white.
4
+ *
5
+ * @type {ImageShader}
6
+ */
7
+ export const shader_tonemap_HDR_lut: ImageShader;
8
+ import { ImageShader } from "../../shader/ImageShader.js";
9
+ //# sourceMappingURL=shader_tonemap_HDR_lut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_tonemap_HDR_lut.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.js"],"names":[],"mappings":"AAmDA;;;;;GAKG;AACH,qCAFU,WAAW,CAclB;4BAlEyB,6BAA6B"}
@@ -1,16 +1,21 @@
1
- import { F32_CONTAINER_STRUCT } from "../../shader/type/F32_CONTAINER_STRUCT.js";
2
- import { TONEMAP_SETTINGS_REC709 } from "./TonemapDisplaySettings.js";
3
1
  import { chunk_sRGBTransferOETF } from "../../shader/chunk/color/sRGB/chunk_sRGBTransferOETF.js";
2
+ import { chunk_tonemap_lut } from "../../shader/chunk/color/tonemap/chunk_tonemap_lut.js";
4
3
  import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
4
  import { ImageShader } from "../../shader/ImageShader.js";
6
5
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
6
  import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
7
+ import { F32_CONTAINER_STRUCT } from "../../shader/type/F32_CONTAINER_STRUCT.js";
8
+ import { SAMPLER_TONEMAP_LUT } from "./SAMPLER_TONEMAP_LUT.js";
9
+ import { TONEMAP_SETTINGS } from "./TonemapDisplaySettings.js";
8
10
 
9
11
  const resources = new ShaderResourceSetDescriptor();
10
- resources.setImmediate("settings", TONEMAP_SETTINGS_REC709);
12
+
13
+ resources.setImmediate("settings", TONEMAP_SETTINGS);
11
14
  resources.createGroup()
12
15
  .addTexture("input_color", "float")
13
16
  .addUniform("exposure", F32_CONTAINER_STRUCT)
17
+ .addTexture("lut", "float", "3d")
18
+ .addSampler("lut_sampler", "filtering", SAMPLER_TONEMAP_LUT)
14
19
 
15
20
  const body = CodeChunk.from(
16
21
  //language=WGSL
@@ -21,39 +26,38 @@ fn main(
21
26
  ) -> @location(0) vec4<f32> {
22
27
 
23
28
  // scene color in linear Rec. 709
24
- var color = textureLoad(input_color, vec2i(coord.xy), 0).rgb;
29
+ let color = textureLoad(input_color, vec2i(coord.xy), 0).rgb * exposure.value;
25
30
 
26
- color *= exposure.value;
31
+ let uvw = tonemap_lut_coordinate(color, f32(textureDimensions(lut).x));
32
+ let color_2020 = tonemap_lut_pq_decode(textureSampleLevel(lut, lut_sampler, uvw, 0.0).rgb);
27
33
 
28
- // no tone mapping: 1.0 is SDR white, and what lies above it is shown as far as the display reaches
34
+ // into the primaries the canvas reports it was configured with (Renderer#configure_context)
35
+ let color_display = mat3x3<f32>(
36
+ settings.display_from_rec2020_c0,
37
+ settings.display_from_rec2020_c1,
38
+ settings.display_from_rec2020_c2
39
+ ) * color_2020;
29
40
 
30
41
  // NOTE: no dithering, colorspace is wide
31
42
 
32
- // into the primaries the canvas reports it was configured with (Renderer#configure_context): Display P3, or
33
- // sRGB where the browser would not configure P3
34
- let color_display = mat3x3<f32>(
35
- settings.display_from_rec709_c0,
36
- settings.display_from_rec709_c1,
37
- settings.display_from_rec709_c2
38
- ) * color;
39
-
40
43
  // apply gamma. Note that gamma is the same for "Display P3" and "sRGB"
41
44
  return vec4(sRGBTransferOETF(color_display), 1.0);
42
45
  }
43
46
  `, [
47
+ chunk_tonemap_lut,
44
48
  chunk_sRGBTransferOETF,
45
49
  ]
46
50
  );
47
51
 
48
52
  /**
49
- * The HDR output with {@link ShadeToneMappingMode.NONE}: exposure and the canvas's primaries, extended, where 1.0 is
50
- * SDR white, and nothing in between.
53
+ * The HDR output of {@link ToneMapper}: exposure, then the HDR LUT, written in the canvas's primaries, extended, where
54
+ * 1.0 is SDR white.
51
55
  *
52
56
  * @type {ImageShader}
53
57
  */
54
- export const shader_tonemap_HDR_none = new ImageShader({
58
+ export const shader_tonemap_HDR_lut = new ImageShader({
55
59
  descriptor: ShaderDescriptor.from({
56
- label: "Tonemap/HDR/none",
60
+ label: "Tonemap/HDR",
57
61
  resources,
58
62
  body
59
63
  }),
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The SDR output of {@link ToneMapper}: exposure, then the SDR LUT, the canvas's primaries, the sRGB transfer curve
3
+ * and an 8-bit dither. The 8-bit target clips anything the LUT puts past SDR white.
4
+ *
5
+ * @type {ImageShader}
6
+ */
7
+ export const shader_tonemap_LDR_lut: ImageShader;
8
+ import { ImageShader } from "../../shader/ImageShader.js";
9
+ //# sourceMappingURL=shader_tonemap_LDR_lut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_tonemap_LDR_lut.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.js"],"names":[],"mappings":"AA0DA;;;;;GAKG;AACH,qCAFU,WAAW,CAclB;4BAtEyB,6BAA6B"}
@@ -1,7 +1,5 @@
1
- import { F32_CONTAINER_STRUCT } from "../../shader/type/F32_CONTAINER_STRUCT.js";
2
- import { TONEMAP_SETTINGS_REC709 } from "./TonemapDisplaySettings.js";
3
1
  import { chunk_sRGBTransferOETF } from "../../shader/chunk/color/sRGB/chunk_sRGBTransferOETF.js";
4
- import { chunk_tonemap_ue_filmic } from "../../shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.js";
2
+ import { chunk_tonemap_lut } from "../../shader/chunk/color/tonemap/chunk_tonemap_lut.js";
5
3
  import {
6
4
  chunk_dither_color_8bit_triangle_noise
7
5
  } from "../../shader/chunk/texture/dither/chunk_dither_color_8bit_triangle_noise.js";
@@ -9,12 +7,18 @@ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
9
7
  import { ImageShader } from "../../shader/ImageShader.js";
10
8
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
11
9
  import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
10
+ import { F32_CONTAINER_STRUCT } from "../../shader/type/F32_CONTAINER_STRUCT.js";
11
+ import { SAMPLER_TONEMAP_LUT } from "./SAMPLER_TONEMAP_LUT.js";
12
+ import { TONEMAP_SETTINGS } from "./TonemapDisplaySettings.js";
12
13
 
13
14
  const resources = new ShaderResourceSetDescriptor();
14
- resources.setImmediate("settings", TONEMAP_SETTINGS_REC709);
15
+
16
+ resources.setImmediate("settings", TONEMAP_SETTINGS);
15
17
  resources.createGroup()
16
18
  .addTexture("input_color", "float")
17
19
  .addUniform("exposure", F32_CONTAINER_STRUCT)
20
+ .addTexture("lut", "float", "3d")
21
+ .addSampler("lut_sampler", "filtering", SAMPLER_TONEMAP_LUT)
18
22
 
19
23
  const body = CodeChunk.from(
20
24
  //language=WGSL
@@ -25,46 +29,42 @@ fn main(
25
29
  ) -> @location(0) vec4<f32> {
26
30
 
27
31
  // scene color in linear Rec. 709
28
- var color = textureLoad(input_color, vec2i(coord.xy), 0).rgb;
29
-
30
- color *= exposure.value;
32
+ let color = textureLoad(input_color, vec2i(coord.xy), 0).rgb * exposure.value;
31
33
 
32
- // Unreal's default SDR rendering, in Rec.709 and within it
33
- color = tonemap_ue_filmic(color);
34
+ let uvw = tonemap_lut_coordinate(color, f32(textureDimensions(lut).x));
35
+ let color_2020 = tonemap_lut_pq_decode(textureSampleLevel(lut, lut_sampler, uvw, 0.0).rgb);
34
36
 
35
- // into the primaries the canvas reports it was configured with (Renderer#configure_context): Display P3, or
36
- // sRGB where the browser would not configure P3. A Rec.709 colour sits inside both.
37
+ // into the primaries the canvas reports it was configured with (Renderer#configure_context)
37
38
  let color_display = mat3x3<f32>(
38
- settings.display_from_rec709_c0,
39
- settings.display_from_rec709_c1,
40
- settings.display_from_rec709_c2
41
- ) * color;
39
+ settings.display_from_rec2020_c0,
40
+ settings.display_from_rec2020_c1,
41
+ settings.display_from_rec2020_c2
42
+ ) * color_2020;
42
43
 
43
44
  // apply gamma. Note that gamma is the same for "Display P3" and "sRGB"
44
- color = sRGBTransferOETF(color_display);
45
+ var color_gamma = sRGBTransferOETF(color_display);
45
46
 
46
47
  // apply dither to remove color banding
47
- color += dither_color_8bit_triangle_noise(coord.xy);
48
+ color_gamma += dither_color_8bit_triangle_noise(coord.xy);
48
49
 
49
- return vec4(color, 1.0);
50
+ return vec4(color_gamma, 1.0);
50
51
  }
51
52
  `, [
52
- chunk_tonemap_ue_filmic,
53
+ chunk_tonemap_lut,
53
54
  chunk_dither_color_8bit_triangle_noise,
54
55
  chunk_sRGBTransferOETF,
55
56
  ]
56
57
  );
57
58
 
58
59
  /**
59
- * The SDR output with {@link ShadeToneMappingMode.ACES}: exposure, Unreal Engine's default "Filmic" tone mapping, the
60
- * canvas's primaries, the sRGB transfer curve and an 8-bit dither. {@link shader_tonemap_HDR_aces} expands the same
61
- * picture into an HDR display's headroom.
60
+ * The SDR output of {@link ToneMapper}: exposure, then the SDR LUT, the canvas's primaries, the sRGB transfer curve
61
+ * and an 8-bit dither. The 8-bit target clips anything the LUT puts past SDR white.
62
62
  *
63
63
  * @type {ImageShader}
64
64
  */
65
- export const shader_tonemap_LDR_aces = new ImageShader({
65
+ export const shader_tonemap_LDR_lut = new ImageShader({
66
66
  descriptor: ShaderDescriptor.from({
67
- label: "Tonemap/LDR/aces",
67
+ label: "Tonemap/LDR",
68
68
  resources,
69
69
  body
70
70
  }),
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The compute shader that bakes `operator` into a LUT, `lut`, one texel a thread: the texel's PQ signal decoded to
3
+ * exposed scene colour, through the colour grade and the operator, and encoded again, as {@link chunk_tonemap_lut}
4
+ * describes. The grade is `grade`, a {@link COLOR_GRADE_STRUCT}, and `grade_keys`, its curves' keyframes; see
5
+ * `ColorGrade#pack`. Built on first use and kept for the operator.
6
+ *
7
+ * Dispatch `ceil(resolution / TONEMAP_LUT_BAKE_GROUP)` workgroups along each axis.
8
+ *
9
+ * @param {ToneMapOperator} operator
10
+ * @returns {ComputeShader}
11
+ */
12
+ export function shader_tonemap_lut_bake(operator: ToneMapOperator): ComputeShader;
13
+ /**
14
+ * Immediate data of a bake: the peak the operator is evaluated for, `PAPER_WHITE_NITS` for an SDR LUT.
15
+ */
16
+ export const TONEMAP_LUT_BAKE_SETTINGS: WebGPUStruct;
17
+ /**
18
+ * Edge of the cube of LUT texels one workgroup bakes.
19
+ */
20
+ export const TONEMAP_LUT_BAKE_GROUP: 4;
21
+ import { ComputeShader } from "../../shader/ComputeShader.js";
22
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
23
+ //# sourceMappingURL=shader_tonemap_lut_bake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_tonemap_lut_bake.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js"],"names":[],"mappings":"AA2BA;;;;;;;;;;GAUG;AACH,oEAFa,aAAa,CAuDzB;AA/ED;;GAEG;AACH,qDAA+E;AAE/E;;GAEG;AACH,uCAAwC;8BAfV,+BAA+B;6BAIhC,mCAAmC"}