render/vulkan: normalize luminance range in bt.1886 formula

BT.1886 is different from other EOTFs in that the spec says that offset
b must be in electrical domain, so use the assumed display environment
from the specification as Lmin and Lmax then normalize bt.1886 to
produce optical luminance L in [0, 1]. See discussion at
https://gitlab.freedesktop.org/pq/color-and-hdr/-/merge_requests/63#note_3090016
This commit is contained in:
llyyr 2025-12-05 02:32:37 +05:30 committed by Simon Ser
parent a962d58727
commit bf9452433c
2 changed files with 12 additions and 6 deletions

View file

@ -49,11 +49,14 @@ vec3 linear_color_to_pq(vec3 color) {
} }
vec3 linear_color_to_bt1886(vec3 color) { vec3 linear_color_to_bt1886(vec3 color) {
float lb = pow(0.0001, 1.0 / 2.4); float Lmin = 0.01;
float lw = pow(1.0, 1.0 / 2.4); float Lmax = 100.0;
float lb = pow(Lmin, 1.0 / 2.4);
float lw = pow(Lmax, 1.0 / 2.4);
float a = pow(lw - lb, 2.4); float a = pow(lw - lb, 2.4);
float b = lb / (lw - lb); float b = lb / (lw - lb);
return pow(color / a, vec3(1.0 / 2.4)) - vec3(b); vec3 L = color * (Lmax - Lmin) + vec3(Lmin);
return pow(L / a, vec3(1.0 / 2.4)) - vec3(b);
} }
void main() { void main() {

View file

@ -47,11 +47,14 @@ vec3 pq_color_to_linear(vec3 color) {
} }
vec3 bt1886_color_to_linear(vec3 color) { vec3 bt1886_color_to_linear(vec3 color) {
float lb = pow(0.0001, 1.0 / 2.4); float Lmin = 0.01;
float lw = pow(1.0, 1.0 / 2.4); float Lmax = 100.0;
float lb = pow(Lmin, 1.0 / 2.4);
float lw = pow(Lmax, 1.0 / 2.4);
float a = pow(lw - lb, 2.4); float a = pow(lw - lb, 2.4);
float b = lb / (lw - lb); float b = lb / (lw - lb);
return a * pow(color + vec3(b), vec3(2.4)); vec3 L = a * pow(color + vec3(b), vec3(2.4));
return (L - Lmin) / (Lmax - Lmin);
} }
void main() { void main() {