mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-03 05:03:39 +02:00
Port the cell fragment shader
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
import utils;
|
||||
import hsluv;
|
||||
import alpha_blend;
|
||||
import linear2srgb;
|
||||
|
||||
#define NUM_COLORS 256
|
||||
|
||||
@@ -470,4 +472,98 @@ VertexOutput vertex_main(
|
||||
return vo;
|
||||
}
|
||||
|
||||
uniform Sampler2DArray sprites;
|
||||
// Scaling factor for the extra text-alpha adjustment for luminance-difference.
|
||||
static const float text_gamma_scaling = 0.5;
|
||||
|
||||
float clamp_to_unit_float(float x) {
|
||||
// Clamp value to suitable output range
|
||||
return clamp(x, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float4 foreground_contrast_new(float4 over, float3 under, float text_contrast, float text_gamma_adjustment) {
|
||||
float under_luminance = dot(under, Y);
|
||||
float over_lumininace = dot(over.rgb, Y);
|
||||
// Apply additional gamma-adjustment scaled by the luminance difference, the darker the foreground the more adjustment we apply.
|
||||
// A multiplicative contrast is also available to increase saturation.
|
||||
over.a = clamp_to_unit_float(lerp(over.a, pow(over.a, text_gamma_adjustment), (1 - over_lumininace + under_luminance) * text_gamma_scaling) * text_contrast);
|
||||
return over;
|
||||
}
|
||||
|
||||
float4 foreground_contrast_old(float4 over, float3 under) {
|
||||
// Simulation of gamma-incorrect blending
|
||||
float under_luminance = dot(under, Y);
|
||||
float over_lumininace = dot(over.rgb, Y);
|
||||
// This is the original gamma-incorrect rendering, it is the solution of the following equation:
|
||||
//
|
||||
// linear2srgb(over * overA2 + under * (1 - overA2)) = linear2srgb(over) * over.a + linear2srgb(under) * (1 - over.a)
|
||||
// ^ gamma correct blending with new alpha ^ gamma incorrect blending with old alpha
|
||||
over.a = clamp_to_unit_float((srgb2linear(linear2srgb(over_lumininace) * over.a + linear2srgb(under_luminance) * (1.0f - over.a)) - under_luminance) / (over_lumininace - under_luminance));
|
||||
return over;
|
||||
}
|
||||
|
||||
float4 foreground_contrast(float4 over, float3 under, float text_contrast, float text_gamma_adjustment) {
|
||||
if (TEXT_NEW_GAMMA) return foreground_contrast_new(over, under, text_contrast, text_gamma_adjustment);
|
||||
return foreground_contrast_old(over, under);
|
||||
}
|
||||
|
||||
float4 load_text_foreground_color(float3 sprite_pos, float colored_sprite, float3 cell_foreground) {
|
||||
// For colored sprites use the color from the sprite rather than the text foreground
|
||||
// Return non-premultiplied foreground color
|
||||
float4 text_fg = sprites.Sample(sprite_pos);
|
||||
return float4(lerp(cell_foreground, text_fg.xyz, colored_sprite), text_fg.w);
|
||||
}
|
||||
|
||||
float4 calculate_premul_foreground_from_sprites(
|
||||
float3 sprite_pos, float3 underline_pos, float3 cursor_pos, float3 strike_pos, uint underline_exclusion_pos,
|
||||
float4 text_fg, float3 decoration_fg, float4 cursor_color_premult,
|
||||
float effective_text_alpha,
|
||||
) {
|
||||
// Return premul foreground color from decorations (cursor, underline, strikethrough)
|
||||
int width, height, layer;
|
||||
sprites.GetDimensions(width, height, layer);
|
||||
float3 sz = float3(float(width), float(height), float(layer));
|
||||
|
||||
float underline_alpha = sprites.Sample(underline_pos).w;
|
||||
int3 fetch_coord = int3(int(sprite_pos.x * sz.x), int(underline_exclusion_pos), int(sprite_pos.z));
|
||||
float underline_exclusion = sprites[fetch_coord].w;
|
||||
|
||||
underline_alpha *= 1.0 - underline_exclusion;
|
||||
float strike_alpha = sprites.Sample(strike_pos).w;
|
||||
float cursor_alpha = sprites.Sample(cursor_pos).w;
|
||||
|
||||
float combined_alpha = min(text_fg.w + strike_alpha, 1.0);
|
||||
|
||||
float4 ans = alpha_blend(
|
||||
float4(text_fg.rgb, combined_alpha * effective_text_alpha),
|
||||
float4(decoration_fg, underline_alpha * effective_text_alpha)
|
||||
);
|
||||
|
||||
return lerp(ans, cursor_color_premult, cursor_alpha * cursor_color_premult.w);
|
||||
}
|
||||
|
||||
float4 adjust_foreground_contrast_with_background(float4 text_fg, float3 bg, float text_contrast, float text_gamma_adjustment) {
|
||||
return foreground_contrast(text_fg, bg, text_contrast, text_gamma_adjustment);
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragment_main(
|
||||
VertexOutput vo,
|
||||
uniform float text_contrast,
|
||||
uniform float text_gamma_adjustment,
|
||||
) : SV_Target {
|
||||
float4 ans_premul = 0;
|
||||
if (!ONLY_FOREGROUND) ans_premul = vo.effective_background_premul;
|
||||
|
||||
if (!ONLY_BACKGROUND) {
|
||||
// blend in the foreground color
|
||||
float4 text_fg = load_text_foreground_color(vo.sprite_pos, vo.colored_sprite, vo.cell_foreground);
|
||||
text_fg = adjust_foreground_contrast_with_background(text_fg, vo.background, text_contrast, text_gamma_adjustment);
|
||||
float4 text_fg_premul = calculate_premul_foreground_from_sprites(
|
||||
vo.sprite_pos, vo.underline_pos, vo.cursor_pos, vo.strike_pos, vo.underline_exclusion_pos,
|
||||
text_fg, vo.decoration_fg, vo.cursor_color_premult, vo.effective_text_alpha);
|
||||
if (ONLY_FOREGROUND) ans_premul = text_fg_premul;
|
||||
else ans_premul = alpha_blend_premul(text_fg_premul, ans_premul);
|
||||
}
|
||||
return ans_premul;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user