dotfiles/mpv/shaders/hdr-toys/gamut-mapping/jedypod.glsl
2025-05-26 00:03:04 +10:00

88 lines
1.9 KiB
GLSL

// https://github.com/jedypod/gamut-compress
// https://github.com/ampas/aces-dev/blob/dev/transforms/ctl/lmt/LMT.Academy.ReferenceGamutCompress.ctl
//!PARAM cyan_limit
//!TYPE float
//!MINIMUM 1.01
//!MAXIMUM 2.0
1.216
//!PARAM magenta_limit
//!TYPE float
//!MINIMUM 1.01
//!MAXIMUM 2.0
1.035
//!PARAM yellow_limit
//!TYPE float
//!MINIMUM 1.01
//!MAXIMUM 2.0
1.076
//!PARAM cyan_threshold
//!TYPE float
//!MINIMUM 0.0
//!MAXIMUM 1.0
0.998
//!PARAM magenta_threshold
//!TYPE float
//!MINIMUM 0.0
//!MAXIMUM 1.0
0.940
//!PARAM yellow_threshold
//!TYPE float
//!MINIMUM 0.0
//!MAXIMUM 1.0
0.977
//!HOOK OUTPUT
//!BIND HOOKED
//!DESC gamut mapping (jedypod)
// Parabolic compression function
// https://www.desmos.com/calculator/khowxlu6xh
float parabolic(float x, float t0, float x0, float y0) {
float s = (y0 - t0) / sqrt(x0 - y0);
float ox = t0 - s * s / 4.0;
float oy = t0 - s * sqrt(s * s / 4.0);
return (x < t0 ? x : s * sqrt(x - ox) + oy);
}
vec3 gamut_compress(vec3 rgb) {
// Achromatic axis
float ac = max(max(rgb.r, rgb.g), rgb.b);
// Inverse RGB Ratios: distance from achromatic axis
vec3 d = ac == 0.0 ? vec3(0.0) : (ac - rgb) / abs(ac);
// Compressed distance
vec3 cd = vec3(
parabolic(d.x, cyan_threshold, cyan_limit, 1.0),
parabolic(d.y, magenta_threshold, magenta_limit, 1.0),
parabolic(d.z, yellow_threshold, yellow_limit, 1.0)
);
// Inverse RGB Ratios to RGB
vec3 crgb = ac - cd * abs(ac);
return crgb;
}
vec3 BT2020_to_BT709(vec3 color) {
return color * mat3(
1.66049100210843540, -0.58764113878854950, -0.072849863319884740,
-0.12455047452159074, 1.13289989712595960, -0.008349422604369515,
-0.01815076335490526, -0.10057889800800737, 1.118729661362913000
);
}
vec4 hook() {
vec4 color = HOOKED_tex(HOOKED_pos);
color.rgb = BT2020_to_BT709(color.rgb);
color.rgb = gamut_compress(color.rgb);
return color;
}