@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.
Files changed (139) 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/physics/constraint/soft_spring_coefficients.d.ts +24 -0
  18. package/src/engine/physics/constraint/soft_spring_coefficients.d.ts.map +1 -0
  19. package/src/engine/physics/constraint/soft_spring_coefficients.js +38 -0
  20. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  21. package/src/engine/physics/constraint/solve_constraints.js +16 -8
  22. package/src/engine/physics/ecs/PhysicsSystem.d.ts +54 -0
  23. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  24. package/src/engine/physics/ecs/PhysicsSystem.js +192 -7
  25. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  26. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +3 -5
  27. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  28. package/src/engine/physics/inertia/world_inverse_inertia.js +3 -5
  29. package/src/engine/physics/vehicle/RaycastVehicle.d.ts +183 -12
  30. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  31. package/src/engine/physics/vehicle/RaycastVehicle.js +1046 -121
  32. package/src/shade/playground/tonemap_sdr/README.md +11 -8
  33. package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +2 -2
  34. package/src/shade/renderer/Renderer.d.ts +5 -6
  35. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  36. package/src/shade/renderer/Renderer.js +15 -88
  37. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts +14 -0
  38. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts.map +1 -0
  39. package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.js +62 -0
  40. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +158 -0
  41. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -0
  42. package/src/shade/renderer/deferred/tonemap/ColorGrade.js +337 -0
  43. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts +9 -0
  44. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts.map +1 -0
  45. package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js +15 -0
  46. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts +6 -0
  47. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts.map +1 -0
  48. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js +84 -0
  49. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts +10 -0
  50. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts.map +1 -0
  51. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js +25 -0
  52. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts +9 -0
  53. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts.map +1 -0
  54. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js +20 -0
  55. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts +14 -0
  56. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map +1 -0
  57. package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js +30 -0
  58. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts +54 -0
  59. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts.map +1 -0
  60. package/src/shade/renderer/deferred/tonemap/ToneMapOperator.js +63 -0
  61. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +106 -0
  62. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -0
  63. package/src/shade/renderer/deferred/tonemap/ToneMapper.js +474 -0
  64. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +5 -13
  65. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -1
  66. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +5 -44
  67. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts +7 -25
  68. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -1
  69. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js +11 -51
  70. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts +20 -0
  71. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts.map +1 -0
  72. package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js +103 -0
  73. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +9 -0
  74. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -0
  75. package/src/shade/renderer/deferred/tonemap/{shader_tonemap_HDR_none.js → shader_tonemap_HDR_lut.js} +22 -18
  76. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +9 -0
  77. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -0
  78. package/src/shade/renderer/deferred/tonemap/{shader_tonemap_LDR_aces.js → shader_tonemap_LDR_lut.js} +24 -24
  79. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts +23 -0
  80. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts.map +1 -0
  81. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js +92 -0
  82. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts +15 -0
  83. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts.map +1 -0
  84. package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js +73 -0
  85. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  86. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  87. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  88. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  89. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  90. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
  91. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  92. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  93. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +22 -0
  94. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -0
  95. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +62 -0
  96. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +13 -0
  97. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -0
  98. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +140 -0
  99. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts +11 -0
  100. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map +1 -0
  101. package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js +65 -0
  102. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts +14 -0
  103. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts.map +1 -0
  104. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js +38 -0
  105. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts +16 -0
  106. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts.map +1 -0
  107. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.js +41 -0
  108. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  109. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -8
  110. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  111. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
  112. package/src/shade/renderer/ShadeToneMappingMode.d.ts +0 -15
  113. package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +0 -1
  114. package/src/shade/renderer/ShadeToneMappingMode.js +0 -41
  115. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts +0 -9
  116. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +0 -1
  117. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.js +0 -79
  118. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +0 -17
  119. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +0 -1
  120. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +0 -101
  121. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts +0 -9
  122. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +0 -1
  123. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts +0 -10
  124. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
  125. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.js +0 -80
  126. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts +0 -9
  127. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +0 -1
  128. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.js +0 -80
  129. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +0 -10
  130. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +0 -1
  131. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts +0 -9
  132. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +0 -1
  133. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.js +0 -71
  134. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts +0 -10
  135. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
  136. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.js +0 -76
  137. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts +0 -3
  138. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts.map +0 -1
  139. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.js +0 -44
@@ -0,0 +1,92 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { ANIMATION_CURVE_KEYFRAME_STRUCT } from "../../animation/ANIMATION_CURVE_KEYFRAME_STRUCT.js";
3
+ import { chunk_color_grade } from "../../shader/chunk/color/grade/chunk_color_grade.js";
4
+ import { chunk_tonemap_lut } from "../../shader/chunk/color/tonemap/chunk_tonemap_lut.js";
5
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
+ import { ComputeShader } from "../../shader/ComputeShader.js";
7
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
8
+ import { f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
9
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
10
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
11
+ import { COLOR_GRADE_STRUCT } from "./ColorGrade.js";
12
+
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.from({ peak_nits: f32 });
17
+
18
+ /**
19
+ * Edge of the cube of LUT texels one workgroup bakes.
20
+ */
21
+ export const TONEMAP_LUT_BAKE_GROUP = 4;
22
+
23
+ /**
24
+ * @type {WeakMap<ToneMapOperator, ComputeShader>}
25
+ */
26
+ const shaders = new WeakMap();
27
+
28
+ /**
29
+ * The compute shader that bakes `operator` into a LUT, `lut`, one texel a thread: the texel's PQ signal decoded to
30
+ * exposed scene colour, through the colour grade and the operator, and encoded again, as {@link chunk_tonemap_lut}
31
+ * describes. The grade is `grade`, a {@link COLOR_GRADE_STRUCT}, and `grade_keys`, its curves' keyframes; see
32
+ * `ColorGrade#pack`. Built on first use and kept for the operator.
33
+ *
34
+ * Dispatch `ceil(resolution / TONEMAP_LUT_BAKE_GROUP)` workgroups along each axis.
35
+ *
36
+ * @param {ToneMapOperator} operator
37
+ * @returns {ComputeShader}
38
+ */
39
+ export function shader_tonemap_lut_bake(operator) {
40
+ assert.defined(operator, 'operator');
41
+
42
+ let shader = shaders.get(operator);
43
+
44
+ if (shader !== undefined) {
45
+ return shader;
46
+ }
47
+
48
+ const resources = new ShaderResourceSetDescriptor();
49
+
50
+ resources.setImmediate("settings", TONEMAP_LUT_BAKE_SETTINGS);
51
+
52
+ const group = resources.createGroup()
53
+ .addStorageTexture("lut", "rgba16float", "3d", "write-only")
54
+ .addUniform("grade", COLOR_GRADE_STRUCT)
55
+ .addStorageBuffer("grade_keys", WebGPUArray.from(ANIMATION_CURVE_KEYFRAME_STRUCT));
56
+
57
+ operator.declare(group);
58
+
59
+ const body = CodeChunk.from(
60
+ //language=WGSL
61
+ `
62
+ @compute @workgroup_size(${TONEMAP_LUT_BAKE_GROUP}, ${TONEMAP_LUT_BAKE_GROUP}, ${TONEMAP_LUT_BAKE_GROUP})
63
+ fn main(@builtin(global_invocation_id) texel: vec3<u32>) {
64
+ let size = textureDimensions(lut);
65
+
66
+ if (any(texel >= size)) {
67
+ return;
68
+ }
69
+
70
+ let scene = tonemap_lut_pq_decode(vec3<f32>(texel) / vec3<f32>(size - 1u));
71
+
72
+ let display = tone_map_operator(color_grade(scene, grade, &grade_keys), settings.peak_nits);
73
+
74
+ textureStore(lut, texel, vec4<f32>(tonemap_lut_pq_encode(display), 1.0));
75
+ }
76
+ `, [
77
+ chunk_tonemap_lut,
78
+ chunk_color_grade,
79
+ operator.chunk,
80
+ ]
81
+ );
82
+
83
+ shader = ComputeShader.from({
84
+ label: `Tonemap/LUT bake/${operator.label}`,
85
+ body,
86
+ resources,
87
+ });
88
+
89
+ shaders.set(operator, shader);
90
+
91
+ return shader;
92
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Immediate data of {@link shader_tonemap_lut_sdr_from_hdr}: the peak the HDR LUT was graded for, cd/m².
3
+ */
4
+ export const TONEMAP_LUT_SDR_FROM_HDR_SETTINGS: WebGPUStruct;
5
+ /**
6
+ * An SDR LUT from an HDR one of the same resolution: each texel through the BT.2390 EETF, from the HDR LUT's graded
7
+ * peak down to the paper white. The EETF maps the brightest channel's signal and the three channels scale by the
8
+ * same ratio of light, so the hue holds and no channel passes SDR white. Below the EETF's knee a texel is unchanged.
9
+ *
10
+ * @type {ComputeShader}
11
+ */
12
+ export const shader_tonemap_lut_sdr_from_hdr: ComputeShader;
13
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
14
+ import { ComputeShader } from "../../shader/ComputeShader.js";
15
+ //# sourceMappingURL=shader_tonemap_lut_sdr_from_hdr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_tonemap_lut_sdr_from_hdr.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js"],"names":[],"mappings":"AAUA;;GAEG;AACH,6DAA8F;AAgD9F;;;;;;GAMG;AACH,8CAFU,aAAa,CAMpB;6BAjE0B,mCAAmC;8BAHlC,+BAA+B"}
@@ -0,0 +1,73 @@
1
+ import { chunk_bt2390_eetf } from "../../shader/chunk/color/tonemap/chunk_bt2390_eetf.js";
2
+ import { chunk_PAPER_WHITE_NITS } from "../../shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js";
3
+ import { chunk_tonemap_lut } from "../../shader/chunk/color/tonemap/chunk_tonemap_lut.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../shader/ComputeShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
8
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
9
+ import { TONEMAP_LUT_BAKE_GROUP } from "./shader_tonemap_lut_bake.js";
10
+
11
+ /**
12
+ * Immediate data of {@link shader_tonemap_lut_sdr_from_hdr}: the peak the HDR LUT was graded for, cd/m².
13
+ */
14
+ export const TONEMAP_LUT_SDR_FROM_HDR_SETTINGS = WebGPUStruct.from({ source_peak_nits: f32 });
15
+
16
+ const resources = new ShaderResourceSetDescriptor();
17
+
18
+ resources.setImmediate("settings", TONEMAP_LUT_SDR_FROM_HDR_SETTINGS);
19
+ resources.createGroup()
20
+ .addTexture("hdr_lut", "unfilterable-float", "3d")
21
+ .addStorageTexture("sdr_lut", "rgba16float", "3d", "write-only");
22
+
23
+ const body = CodeChunk.from(
24
+ //language=WGSL
25
+ `
26
+ @compute @workgroup_size(${TONEMAP_LUT_BAKE_GROUP}, ${TONEMAP_LUT_BAKE_GROUP}, ${TONEMAP_LUT_BAKE_GROUP})
27
+ fn main(@builtin(global_invocation_id) texel: vec3<u32>) {
28
+ let size = textureDimensions(sdr_lut);
29
+
30
+ if (any(texel >= size)) {
31
+ return;
32
+ }
33
+
34
+ let signal = textureLoad(hdr_lut, texel, 0).rgb;
35
+
36
+ // the brightest channel's signal; the other two follow it by the same ratio of light, which keeps the hue
37
+ let brightest = max(signal.r, max(signal.g, signal.b));
38
+
39
+ let source_peak = tonemap_lut_pq_encode(vec3<f32>(settings.source_peak_nits / PAPER_WHITE_NITS)).x;
40
+ let target_peak = tonemap_lut_pq_encode(vec3<f32>(1.0)).x;
41
+
42
+ let mapped = bt2390_eetf(brightest, source_peak, target_peak);
43
+
44
+ let light = tonemap_lut_pq_decode(signal);
45
+ let before = tonemap_lut_pq_decode(vec3<f32>(brightest)).x;
46
+ let after = tonemap_lut_pq_decode(vec3<f32>(mapped)).x;
47
+
48
+ var scale = 1.0;
49
+ if (before > 0.0) {
50
+ scale = after / before;
51
+ }
52
+
53
+ textureStore(sdr_lut, texel, vec4<f32>(tonemap_lut_pq_encode(light * scale), 1.0));
54
+ }
55
+ `, [
56
+ chunk_tonemap_lut,
57
+ chunk_bt2390_eetf,
58
+ chunk_PAPER_WHITE_NITS,
59
+ ]
60
+ );
61
+
62
+ /**
63
+ * An SDR LUT from an HDR one of the same resolution: each texel through the BT.2390 EETF, from the HDR LUT's graded
64
+ * peak down to the paper white. The EETF maps the brightest channel's signal and the three channels scale by the
65
+ * same ratio of light, so the hue holds and no channel passes SDR white. Below the EETF's knee a texel is unchanged.
66
+ *
67
+ * @type {ComputeShader}
68
+ */
69
+ export const shader_tonemap_lut_sdr_from_hdr = ComputeShader.from({
70
+ label: "Tonemap/LUT SDR from HDR",
71
+ body,
72
+ resources,
73
+ });
@@ -143,7 +143,7 @@ export class GPUFluidCascade {
143
143
  * @param {*} _resources
144
144
  * @param {{encoder: ShadeGPUCommandContext}} context
145
145
  */
146
- static "__#286@#execute_restrict"(record: object, _resources: any, context: {
146
+ static "__#289@#execute_restrict"(record: object, _resources: any, context: {
147
147
  encoder: ShadeGPUCommandContext;
148
148
  }): void;
149
149
  /**
@@ -151,7 +151,7 @@ export class GPUFluidCascade {
151
151
  * @param {*} _resources
152
152
  * @param {{encoder: ShadeGPUCommandContext}} context
153
153
  */
154
- static "__#286@#execute_fill"(record: object, _resources: any, context: {
154
+ static "__#289@#execute_fill"(record: object, _resources: any, context: {
155
155
  encoder: ShadeGPUCommandContext;
156
156
  }): void;
157
157
  /**
@@ -159,7 +159,7 @@ export class GPUFluidCascade {
159
159
  * @param {import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
160
160
  * @param {{encoder: ShadeGPUCommandContext}} context
161
161
  */
162
- static "__#286@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
162
+ static "__#289@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
163
163
  encoder: ShadeGPUCommandContext;
164
164
  }): void;
165
165
  /**
@@ -63,7 +63,7 @@ export class GPUFluidCascadeStack {
63
63
  * @param {*} _resources
64
64
  * @param {{encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
65
65
  */
66
- static "__#288@#execute_publish"(pass: object, _resources: any, context: {
66
+ static "__#291@#execute_publish"(pass: object, _resources: any, context: {
67
67
  encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
68
68
  }): void;
69
69
  /**
@@ -90,19 +90,19 @@ export class GPUFluidForcing {
90
90
  * @param {number} clear_size bytes cleared from 0 when the pool reuses the buffer
91
91
  * @returns {BufferResourceDescriptor}
92
92
  */
93
- static "__#289@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
93
+ static "__#292@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
94
94
  /**
95
95
  * @param {object} record
96
96
  * @param {FramePassResources} resources
97
97
  * @param {{encoder: ShadeGPUCommandContext}} context
98
98
  */
99
- static "__#289@#execute_extract"(record: object, resources: FramePassResources, context: {
99
+ static "__#292@#execute_extract"(record: object, resources: FramePassResources, context: {
100
100
  encoder: ShadeGPUCommandContext;
101
101
  }): void;
102
- static "__#289@#execute_clear"(record: any, _resources: any, context: any): void;
103
- static "__#289@#execute_query"(record: any, resources: any, context: any): void;
104
- static "__#289@#execute_command"(record: any, resources: any, context: any): void;
105
- static "__#289@#execute_apply"(record: any, resources: any, context: any): void;
102
+ static "__#292@#execute_clear"(record: any, _resources: any, context: any): void;
103
+ static "__#292@#execute_query"(record: any, resources: any, context: any): void;
104
+ static "__#292@#execute_command"(record: any, resources: any, context: any): void;
105
+ static "__#292@#execute_apply"(record: any, resources: any, context: any): void;
106
106
  /**
107
107
  * @param {object} options
108
108
  * @param {GPUDevice} options.device
@@ -41,7 +41,7 @@ export class GPUFluidPressureSolve {
41
41
  * @param {*} _resources
42
42
  * @param {{encoder: ShadeGPUCommandContext}} context
43
43
  */
44
- static "__#285@#execute"(data: {
44
+ static "__#288@#execute"(data: {
45
45
  solve: GPUFluidPressureSolve;
46
46
  arm: number;
47
47
  count: number;
@@ -49,7 +49,7 @@ export class GPUFluidQueries {
49
49
  * @param {import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
50
50
  * @param {{encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
51
51
  */
52
- static "__#290@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
52
+ static "__#293@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
53
53
  encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
54
54
  }): void;
55
55
  /**
@@ -34,7 +34,7 @@ export class GPUProbeClipmapGI {
34
34
  * @param {ProbeClipmapSettings} settings
35
35
  * @returns {boolean} whether it is what the settings' world cache describes, in their frustum's windows
36
36
  */
37
- static "__#211@#world_cache_built_for"(world_cache: GPUProbeClipmap, settings: ProbeClipmapSettings): boolean;
37
+ static "__#214@#world_cache_built_for"(world_cache: GPUProbeClipmap, settings: ProbeClipmapSettings): boolean;
38
38
  /**
39
39
  * @param {GraphicsContext} graphics
40
40
  */
@@ -13,7 +13,7 @@ export class TinyGltf {
13
13
  * @readonly
14
14
  * @type {TextureFormat}
15
15
  */
16
- static readonly "__#309@#UNCOMPRESSED_TARGET": TextureFormat;
16
+ static readonly "__#312@#UNCOMPRESSED_TARGET": TextureFormat;
17
17
  /**
18
18
  * @param {AssetManager} assetManager
19
19
  * @param {AssetRequestScope} [scope]
@@ -51,7 +51,7 @@ export class NSS {
51
51
  * @returns {number}
52
52
  */
53
53
  static recommended_jitter_sequence_size(upscale_ratio: number): number;
54
- static "__#217@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
54
+ static "__#220@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
55
55
  /**
56
56
  * @param {GraphicsContext} graphics
57
57
  */
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Linear Rec.709 (D65) to AP1 (ACES white), Bradford-adapted, as Unreal's `WorkingColorSpace.ToAP1` for an sRGB
3
+ * working space. Row-major.
4
+ * @type {Float64Array}
5
+ */
6
+ export const M3_REC709_TO_AP1: Float64Array;
7
+ /**
8
+ * The inverse of {@link M3_REC709_TO_AP1}. Row-major.
9
+ * @type {Float64Array}
10
+ */
11
+ export const M3_AP1_TO_REC709: Float64Array;
12
+ /**
13
+ * - `CRM_FROM_REC709_TO_AP1` and `CRM_FROM_AP1_TO_REC709`: {@link M3_REC709_TO_AP1} and its inverse.
14
+ * - `AP1_LUMINANCE`: AP1's contribution of each channel to Y, the row Unreal calls `AP1_RGB2Y`.
15
+ *
16
+ * Derived from the two spaces' chromaticities, so neither matrix is a rounded transcription of the other.
17
+ *
18
+ * @type {CodeChunk}
19
+ */
20
+ export const chunk_CRM_REC709_AP1: CodeChunk;
21
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
22
+ //# sourceMappingURL=chunk_CRM_REC709_AP1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_CRM_REC709_AP1.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,+BAFU,YAAY,CAE8B;AAIpD;;;GAGG;AACH,+BAFU,YAAY,CAE8B;AAYpD;;;;;;;GAOG;AACH,mCAFU,SAAS,CASjB;0BAzDwB,gCAAgC"}
@@ -0,0 +1,62 @@
1
+ import { m3_chromatic_adaptation_bradford } from "../../../../../../core/color/xyz/m3_chromatic_adaptation_bradford.js";
2
+ import { m3_rgb_to_xyz_from_primaries } from "../../../../../../core/color/xyz/m3_rgb_to_xyz_from_primaries.js";
3
+ import { m3_invert } from "../../../../../../core/geom/mat3/m3_invert.js";
4
+ import { m3_multiply } from "../../../../../../core/geom/mat3/m3_multiply.js";
5
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
6
+
7
+ const REC709_TO_XYZ = new Float64Array(9);
8
+ m3_rgb_to_xyz_from_primaries(REC709_TO_XYZ, [0.640, 0.330, 0.300, 0.600, 0.150, 0.060], 0.3127, 0.3290);
9
+
10
+ // ACES AP1 (ACEScg) primaries and the ACES white, S-2014-004
11
+ const AP1_WHITE_X = 0.32168;
12
+ const AP1_WHITE_Y = 0.33767;
13
+ const AP1_TO_XYZ = new Float64Array(9);
14
+ m3_rgb_to_xyz_from_primaries(AP1_TO_XYZ, [0.713, 0.293, 0.165, 0.830, 0.128, 0.044], AP1_WHITE_X, AP1_WHITE_Y);
15
+
16
+ const XYZ_TO_AP1 = new Float64Array(9);
17
+ m3_invert(XYZ_TO_AP1, AP1_TO_XYZ);
18
+
19
+ const D65_TO_ACES_WHITE = new Float64Array(9);
20
+ m3_chromatic_adaptation_bradford(D65_TO_ACES_WHITE, 0.3127, 0.3290, AP1_WHITE_X, AP1_WHITE_Y);
21
+
22
+ /**
23
+ * Linear Rec.709 (D65) to AP1 (ACES white), Bradford-adapted, as Unreal's `WorkingColorSpace.ToAP1` for an sRGB
24
+ * working space. Row-major.
25
+ * @type {Float64Array}
26
+ */
27
+ export const M3_REC709_TO_AP1 = new Float64Array(9);
28
+ m3_multiply(M3_REC709_TO_AP1, D65_TO_ACES_WHITE, REC709_TO_XYZ);
29
+ m3_multiply(M3_REC709_TO_AP1, XYZ_TO_AP1, M3_REC709_TO_AP1);
30
+
31
+ /**
32
+ * The inverse of {@link M3_REC709_TO_AP1}. Row-major.
33
+ * @type {Float64Array}
34
+ */
35
+ export const M3_AP1_TO_REC709 = new Float64Array(9);
36
+ m3_invert(M3_AP1_TO_REC709, M3_REC709_TO_AP1);
37
+
38
+ /**
39
+ * @param {Float64Array} m row-major
40
+ * @returns {string} a WGSL `mat3x3<f32>` constructor, column by column
41
+ */
42
+ function wgsl_mat3(m) {
43
+ const column = c => `vec3<f32>(${m[c]}, ${m[3 + c]}, ${m[6 + c]})`;
44
+ return `mat3x3<f32>(${column(0)}, ${column(1)}, ${column(2)})`;
45
+ }
46
+
47
+ /**
48
+ * - `CRM_FROM_REC709_TO_AP1` and `CRM_FROM_AP1_TO_REC709`: {@link M3_REC709_TO_AP1} and its inverse.
49
+ * - `AP1_LUMINANCE`: AP1's contribution of each channel to Y, the row Unreal calls `AP1_RGB2Y`.
50
+ *
51
+ * Derived from the two spaces' chromaticities, so neither matrix is a rounded transcription of the other.
52
+ *
53
+ * @type {CodeChunk}
54
+ */
55
+ export const chunk_CRM_REC709_AP1 = CodeChunk.from(
56
+ //language=WGSL
57
+ `
58
+ const CRM_FROM_REC709_TO_AP1 = ${wgsl_mat3(M3_REC709_TO_AP1)};
59
+ const CRM_FROM_AP1_TO_REC709 = ${wgsl_mat3(M3_AP1_TO_REC709)};
60
+ const AP1_LUMINANCE = vec3<f32>(${AP1_TO_XYZ[3]}, ${AP1_TO_XYZ[4]}, ${AP1_TO_XYZ[5]});
61
+ `
62
+ );
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `color_grade(scene, grade, keys)`: exposed scene-linear Rec.709 through a {@link ColorGrade}, white balance, then
3
+ * primaries, then hue curves, to Rec.709 again, not negative. `grade` is the grade's {@link COLOR_GRADE_STRUCT} and
4
+ * `keys` the curves' keyframes. See `ColorGrade` for what each stage does.
5
+ *
6
+ * Also defines each stage on its own: `color_grade_primaries(ap1, grade)` and
7
+ * `color_grade_hue_curves(color, counts, keys)`.
8
+ *
9
+ * @type {CodeChunk}
10
+ */
11
+ export const chunk_color_grade: CodeChunk;
12
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
13
+ //# sourceMappingURL=chunk_color_grade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_color_grade.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,gCAFU,SAAS,CA0HjB;0BAxIwB,gCAAgC"}
@@ -0,0 +1,140 @@
1
+ import { ANIMATION_CURVE_KEYFRAME_STRUCT } from "../../../../animation/ANIMATION_CURVE_KEYFRAME_STRUCT.js";
2
+ import { chunk_animation_curve_evaluate_keys } from "../../../../animation/chunk_animation_curve_evaluate_keys.js";
3
+ import { COLOR_GRADE_STRUCT } from "../../../../deferred/tonemap/ColorGrade.js";
4
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
5
+ import { chunk_CRM_REC709_AP1 } from "../conversion/chunk_CRM_REC709_AP1.js";
6
+ import { chunk_linear_srgb_to_oklab } from "../oklab/chunk_linear_srgb_to_oklab.js";
7
+ import { chunk_oklab_compute_max_saturation } from "../oklab/chunk_oklab_compute_max_saturation.js";
8
+ import { chunk_oklab_to_linear_srgb } from "../oklab/chunk_oklab_to_linear_srgb.js";
9
+
10
+ /**
11
+ * `color_grade(scene, grade, keys)`: exposed scene-linear Rec.709 through a {@link ColorGrade}, white balance, then
12
+ * primaries, then hue curves, to Rec.709 again, not negative. `grade` is the grade's {@link COLOR_GRADE_STRUCT} and
13
+ * `keys` the curves' keyframes. See `ColorGrade` for what each stage does.
14
+ *
15
+ * Also defines each stage on its own: `color_grade_primaries(ap1, grade)` and
16
+ * `color_grade_hue_curves(color, counts, keys)`.
17
+ *
18
+ * @type {CodeChunk}
19
+ */
20
+ export const chunk_color_grade = CodeChunk.from(
21
+ //language=WGSL
22
+ `
23
+ // Unreal's ColorCorrect: one zone's grade, in AP1
24
+ fn color_grade_correct(
25
+ color: vec3<f32>,
26
+ saturation: vec3<f32>,
27
+ contrast: vec3<f32>,
28
+ gamma: vec3<f32>,
29
+ gain: vec3<f32>,
30
+ offset: vec3<f32>,
31
+ ) -> vec3<f32> {
32
+ let luma = dot(color, AP1_LUMINANCE);
33
+
34
+ var c = max(vec3<f32>(0.0), mix(vec3<f32>(luma), color, saturation));
35
+ c = pow(c * (1.0 / 0.18), contrast) * 0.18;
36
+ c = pow(c, 1.0 / gamma);
37
+
38
+ return c * gain + offset;
39
+ }
40
+
41
+ // Unreal's ColorCorrectAll: the three zones, blended by luma
42
+ fn color_grade_primaries(ap1: vec3<f32>, grade: ${COLOR_GRADE_STRUCT.wgsl_ref}) -> vec3<f32> {
43
+ let luma = dot(ap1, AP1_LUMINANCE);
44
+
45
+ let shadows = color_grade_correct(
46
+ ap1,
47
+ grade.shadows_saturation.xyz, grade.shadows_contrast.xyz, grade.shadows_gamma.xyz,
48
+ grade.shadows_gain.xyz, grade.shadows_offset.xyz,
49
+ );
50
+ let midtones = color_grade_correct(
51
+ ap1,
52
+ grade.midtones_saturation.xyz, grade.midtones_contrast.xyz, grade.midtones_gamma.xyz,
53
+ grade.midtones_gain.xyz, grade.midtones_offset.xyz,
54
+ );
55
+ let highlights = color_grade_correct(
56
+ ap1,
57
+ grade.highlights_saturation.xyz, grade.highlights_contrast.xyz, grade.highlights_gamma.xyz,
58
+ grade.highlights_gain.xyz, grade.highlights_offset.xyz,
59
+ );
60
+
61
+ let weight_shadows = 1.0 - smoothstep(0.0, grade.zone_bounds.x, luma);
62
+ let weight_highlights = smoothstep(grade.zone_bounds.y, grade.zone_bounds.z, luma);
63
+ let weight_midtones = 1.0 - weight_shadows - weight_highlights;
64
+
65
+ return shadows * weight_shadows + midtones * weight_midtones + highlights * weight_highlights;
66
+ }
67
+
68
+ // hue shift, chroma scale and lightness against OkLCh hue; counts.xyz are the three curves' keys, in that order
69
+ fn color_grade_hue_curves(
70
+ color: vec3<f32>,
71
+ counts: vec4<u32>,
72
+ keys: ptr<storage, array<${ANIMATION_CURVE_KEYFRAME_STRUCT.wgsl_ref}>, read>,
73
+ ) -> vec3<f32> {
74
+ if (all(counts.xyz == vec3<u32>(0u))) {
75
+ return color;
76
+ }
77
+
78
+ let lab = linear_srgb_to_oklab(color);
79
+ let chroma = length(lab.yz);
80
+
81
+ // a grey has no hue, and every edit below leaves it where it is
82
+ if (chroma <= 0.0 || lab.x <= 0.0) {
83
+ return color;
84
+ }
85
+
86
+ let direction = lab.yz / chroma;
87
+ let hue_signed = degrees(atan2(direction.y, direction.x));
88
+ let hue = select(hue_signed, hue_signed + 360.0, hue_signed < 0.0);
89
+
90
+ var shift = 0.0;
91
+ var scale = 1.0;
92
+ var stops = 0.0;
93
+
94
+ if (counts.x > 0u) {
95
+ shift = animation_curve_evaluate_keys(keys, 0u, counts.x, hue);
96
+ }
97
+ if (counts.y > 0u) {
98
+ scale = animation_curve_evaluate_keys(keys, counts.x, counts.y, hue);
99
+ }
100
+ if (counts.z > 0u) {
101
+ stops = animation_curve_evaluate_keys(keys, counts.x + counts.y, counts.z, hue);
102
+ }
103
+
104
+ // saturation relative to the Rec.709 gamut's edge at this hue: 0 for a grey, 1 on the edge
105
+ let relative = min(chroma / lab.x / oklab_compute_max_saturation(direction.x, direction.y), 1.0);
106
+
107
+ let angle = radians(shift);
108
+ let rotated = vec2<f32>(
109
+ direction.x * cos(angle) - direction.y * sin(angle),
110
+ direction.x * sin(angle) + direction.y * cos(angle),
111
+ );
112
+
113
+ // Oklab is the cube root of a linear map, so scaling L, a and b by cbrt(2^k) scales the light by exactly 2^k
114
+ let exposure = exp2(stops * relative / 3.0);
115
+
116
+ return oklab_to_linear_srgb(vec3<f32>(lab.x, rotated * (chroma * scale)) * exposure);
117
+ }
118
+
119
+ fn color_grade(
120
+ scene: vec3<f32>,
121
+ grade: ${COLOR_GRADE_STRUCT.wgsl_ref},
122
+ keys: ptr<storage, array<${ANIMATION_CURVE_KEYFRAME_STRUCT.wgsl_ref}>, read>,
123
+ ) -> vec3<f32> {
124
+ let white_balance = mat3x3<f32>(grade.white_balance_c0.xyz, grade.white_balance_c1.xyz, grade.white_balance_c2.xyz);
125
+
126
+ let ap1 = color_grade_primaries(CRM_FROM_REC709_TO_AP1 * (white_balance * scene), grade);
127
+
128
+ let graded = max(CRM_FROM_AP1_TO_REC709 * ap1, vec3<f32>(0.0));
129
+
130
+ return max(color_grade_hue_curves(graded, grade.curve_counts, keys), vec3<f32>(0.0));
131
+ }
132
+ `, [
133
+ COLOR_GRADE_STRUCT.declaration_chunk,
134
+ chunk_animation_curve_evaluate_keys,
135
+ chunk_CRM_REC709_AP1,
136
+ chunk_linear_srgb_to_oklab,
137
+ chunk_oklab_to_linear_srgb,
138
+ chunk_oklab_compute_max_saturation,
139
+ ]
140
+ );
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `oklab_compute_max_saturation(a, b)`: the largest saturation S = C / L in linear sRGB (Rec.709) at the hue of the
3
+ * unit Oklab direction (a, b), where the first channel reaches zero. Ottosson's polynomial and one Halley step; the
4
+ * WGSL twin of `core/color/oklab/compute_max_saturation.js`.
5
+ *
6
+ * @see https://bottosson.github.io/posts/gamutclipping/
7
+ * @type {CodeChunk}
8
+ */
9
+ export const chunk_oklab_compute_max_saturation: CodeChunk;
10
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
11
+ //# sourceMappingURL=chunk_oklab_compute_max_saturation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_oklab_compute_max_saturation.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,iDAFU,SAAS,CAwDjB;0BAhEwB,gCAAgC"}
@@ -0,0 +1,65 @@
1
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * `oklab_compute_max_saturation(a, b)`: the largest saturation S = C / L in linear sRGB (Rec.709) at the hue of the
5
+ * unit Oklab direction (a, b), where the first channel reaches zero. Ottosson's polynomial and one Halley step; the
6
+ * WGSL twin of `core/color/oklab/compute_max_saturation.js`.
7
+ *
8
+ * @see https://bottosson.github.io/posts/gamutclipping/
9
+ * @type {CodeChunk}
10
+ */
11
+ export const chunk_oklab_compute_max_saturation = CodeChunk.from(
12
+ //language=WGSL
13
+ `
14
+ fn oklab_compute_max_saturation(a: f32, b: f32) -> f32 {
15
+ // the channel that reaches zero first selects the coefficients
16
+ var k0: f32; var k1: f32; var k2: f32; var k3: f32; var k4: f32;
17
+ var wl: f32; var wm: f32; var ws: f32;
18
+
19
+ if (-1.88170328 * a - 0.80936493 * b > 1.0) {
20
+ // red
21
+ k0 = 1.19086277; k1 = 1.76576728; k2 = 0.59662641; k3 = 0.75515197; k4 = 0.56771245;
22
+ wl = 4.0767416621; wm = -3.3077115913; ws = 0.2309699292;
23
+ } else if (1.81444104 * a - 1.19445276 * b > 1.0) {
24
+ // green
25
+ k0 = 0.73956515; k1 = -0.45954404; k2 = 0.08285427; k3 = 0.12541070; k4 = 0.14503204;
26
+ wl = -1.2684380046; wm = 2.6097574011; ws = -0.3413193965;
27
+ } else {
28
+ // blue
29
+ k0 = 1.35733652; k1 = -0.00915799; k2 = -1.15130210; k3 = -0.50559606; k4 = 0.00692167;
30
+ wl = -0.0041960863; wm = -0.7034186147; ws = 1.7076147010;
31
+ }
32
+
33
+ var s = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
34
+
35
+ let k_l = 0.3963377774 * a + 0.2158037573 * b;
36
+ let k_m = -0.1055613458 * a - 0.0638541728 * b;
37
+ let k_s = -0.0894841775 * a - 1.2914855480 * b;
38
+
39
+ let l_ = 1.0 + s * k_l;
40
+ let m_ = 1.0 + s * k_m;
41
+ let s_ = 1.0 + s * k_s;
42
+
43
+ let l = l_ * l_ * l_;
44
+ let m = m_ * m_ * m_;
45
+ let s3 = s_ * s_ * s_;
46
+
47
+ let l_ds = 3.0 * k_l * l_ * l_;
48
+ let m_ds = 3.0 * k_m * m_ * m_;
49
+ let s_ds = 3.0 * k_s * s_ * s_;
50
+
51
+ let l_ds2 = 6.0 * k_l * k_l * l_;
52
+ let m_ds2 = 6.0 * k_m * k_m * m_;
53
+ let s_ds2 = 6.0 * k_s * k_s * s_;
54
+
55
+ let f = wl * l + wm * m + ws * s3;
56
+ let f1 = wl * l_ds + wm * m_ds + ws * s_ds;
57
+ let f2 = wl * l_ds2 + wm * m_ds2 + ws * s_ds2;
58
+
59
+ // one Halley step
60
+ s = s - f * f1 / (f1 * f1 - 0.5 * f * f2);
61
+
62
+ return s;
63
+ }
64
+ `
65
+ );
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The EETF of ITU-R BT.2390 (§5.4.1): maps a PQ signal mastered for a display reaching `source_peak` onto one
3
+ * reaching `target_peak`, all three PQ signals, with black at zero on both.
4
+ *
5
+ * The signal is first normalised to the source's range. Up to the knee, KS = 1.5 × maxLum − 0.5, it passes
6
+ * through; past it, a Hermite spline carries it to maxLum, the target's peak in the same normalisation, which the
7
+ * source's peak reaches with zero slope. The spline meets the identity at the knee with slope 1. A signal past
8
+ * `source_peak` is held at it. A target at or above the source passes every signal through.
9
+ *
10
+ * @type {CodeChunk}
11
+ */
12
+ export const chunk_bt2390_eetf: CodeChunk;
13
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
14
+ //# sourceMappingURL=chunk_bt2390_eetf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_bt2390_eetf.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,gCAFU,SAAS,CA0BjB;0BArCwB,gCAAgC"}