From 920b350ac9de335395a1930ed39775902848e87c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 27 Apr 2023 18:27:46 +0200 Subject: [PATCH 1/3] feat: more exact sRGB approximation --- kitty/cell_fragment.glsl | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/kitty/cell_fragment.glsl b/kitty/cell_fragment.glsl index 976660290..183b1bc0d 100644 --- a/kitty/cell_fragment.glsl +++ b/kitty/cell_fragment.glsl @@ -37,6 +37,22 @@ in float colored_sprite; out vec4 final_color; // Util functions {{{ +float linear2srgb(float x) { + // Linear to sRGB conversion. + float lower = 12.92 * x; + float upper = 1.055 * pow(x, 1.0f / 2.4f) - 0.055f; + + return mix(lower, upper, step(0.0031308f, x)); +} + +float srgb2linear(float x) { + // sRGB to linear conversion + float lower = x / 12.92; + float upper = pow((x + 0.055f) / 1.055f, 2.4f); + + return mix(lower, upper, step(0.04045f, x)); +} + vec4 alpha_blend(vec4 over, vec4 under) { // Alpha blend two colors returning the resulting color pre-multiplied by its alpha // and its alpha. @@ -103,20 +119,9 @@ vec4 vec4_premul(vec4 rgba) { #ifdef NEEDS_FOREGROUND // sRGB luminance values const vec3 Y = vec3(0.2126, 0.7152, 0.0722); -const float gamma_factor = 2.2; // Scaling factor for the extra text-alpha adjustment for luminance-difference. const float text_gamma_scaling = 0.5; -float linear2srgb(float x) { - // Approximation of linear-to-sRGB conversion - return pow(x, 1.0 / gamma_factor); -} - -float srgb2linear(float x) { - // Approximation of sRGB-to-linear conversion - return pow(x, gamma_factor); -} - float clamp_to_unit_float(float x) { // Clamp value to suitable output range return clamp(x, 0.0f, 1.0f); From 289957ef1c1480922d954b9c45baa0614068d5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 27 Apr 2023 18:34:00 +0200 Subject: [PATCH 2/3] style: use ifdef to be consistent with the other cases --- kitty/cell_fragment.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kitty/cell_fragment.glsl b/kitty/cell_fragment.glsl index 183b1bc0d..70519439e 100644 --- a/kitty/cell_fragment.glsl +++ b/kitty/cell_fragment.glsl @@ -198,7 +198,7 @@ void main() { #endif #ifdef BACKGROUND -#if defined(TRANSPARENT) +#ifdef TRANSPARENT final_color = vec4_premul(background, bg_alpha); #else final_color = vec4(background, draw_bg); From 9f41183628eac83ad37a7d7dc7bd6626b62079cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 27 Apr 2023 18:35:06 +0200 Subject: [PATCH 3/3] fix: account for incorrect gamma-blending performed by compositor on transparent windows Fixes #6209 --- kitty/cell_fragment.glsl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kitty/cell_fragment.glsl b/kitty/cell_fragment.glsl index 70519439e..113b3c8c2 100644 --- a/kitty/cell_fragment.glsl +++ b/kitty/cell_fragment.glsl @@ -184,6 +184,12 @@ void main() { vec4 fg = calculate_foreground(background); #ifdef TRANSPARENT final_color = alpha_blend_premul(fg, vec4_premul(background, bg_alpha)); + + // Adjust the transparent alpha-channel to account for incorrect + // gamma-blending performed by the compositor (true for at least wlroots, + // picom, GNOME, MacOS). + // This is the last pass: + final_color.a = linear2srgb(final_color.a); #else final_color = alpha_blend_premul(fg, background); #endif @@ -207,6 +213,10 @@ void main() { #ifdef FOREGROUND final_color = calculate_foreground(); // pre-multiplied foreground + + // This is the last pass, adjust alpha to compensate for gamma-incorrect + // blending in compositor: + final_color.a = linear2srgb(final_color.a); #endif }