@woosh/meep-engine 3.63.3 → 3.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/package.json +1 -1
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts +14 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.d.ts.map +1 -0
- package/src/core/color/xyz/m3_chromatic_adaptation_bradford.js +51 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +2 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +51 -70
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +8 -64
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts +17 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_jacobi_rotate_in_place.js +64 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts +30 -0
- package/src/core/math/linalg/solve_box_constrained_qp.d.ts.map +1 -0
- package/src/core/math/linalg/solve_box_constrained_qp.js +205 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.d.ts +24 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.d.ts.map +1 -0
- package/src/engine/physics/constraint/soft_spring_coefficients.js +38 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +16 -8
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +54 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +192 -7
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +3 -5
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +3 -5
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts +183 -12
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +1046 -121
- package/src/shade/playground/tonemap_sdr/README.md +11 -8
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +2 -2
- package/src/shade/renderer/Renderer.d.ts +5 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +15 -88
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts +14 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.d.ts.map +1 -0
- package/src/shade/renderer/animation/chunk_animation_curve_evaluate_keys.js +62 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +158 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ColorGrade.js +337 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/SAMPLER_TONEMAP_LUT.js +15 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts +6 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_ACES.js +84 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts +10 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_GT7.js +25 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_NONE.js +20 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts +14 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/TONE_MAP_OPERATOR_PBR_NEUTRAL.js +30 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts +54 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapOperator.js +63 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +106 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/ToneMapper.js +474 -0
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +5 -13
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +5 -44
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts +7 -25
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -1
- package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.js +11 -51
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts +20 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/m3_white_balance_rec709.js +103 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_HDR_none.js → shader_tonemap_HDR_lut.js} +22 -18
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +9 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/{shader_tonemap_LDR_aces.js → shader_tonemap_LDR_lut.js} +24 -24
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts +23 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_bake.js +92 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts +15 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.d.ts.map +1 -0
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_lut_sdr_from_hdr.js +73 -0
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +62 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +140 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.js +65 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_bt2390_eetf.js +38 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_lut.js +41 -0
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -8
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
- package/src/shade/renderer/ShadeToneMappingMode.d.ts +0 -15
- package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +0 -1
- package/src/shade/renderer/ShadeToneMappingMode.js +0 -41
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.js +0 -79
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +0 -17
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +0 -101
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.js +0 -80
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts +0 -9
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.js +0 -71
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts +0 -10
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.js +0 -76
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts +0 -3
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_hdr_bt2390.js +0 -44
|
@@ -0,0 +1,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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
99
|
+
static "__#292@#execute_extract"(record: object, resources: FramePassResources, context: {
|
|
100
100
|
encoder: ShadeGPUCommandContext;
|
|
101
101
|
}): void;
|
|
102
|
-
static "__#
|
|
103
|
-
static "__#
|
|
104
|
-
static "__#
|
|
105
|
-
static "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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 "__#
|
|
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
|
package/src/shade/renderer/shader/chunk/color/oklab/chunk_oklab_compute_max_saturation.d.ts.map
ADDED
|
@@ -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"}
|