mirror of
https://github.com/wez/wezterm.git
synced 2024-12-18 19:01:36 +03:00
153497d01d
I dug out my pixelbook which has intel graphics and runs linux to try to make sense of this issue, but I'm baffled. It doesn't appear to NaN going in, but we end up with something weird happening if we don't fixup the alpha. Relevant entry to the discussion/background on this is: https://github.com/wez/wezterm/issues/1180#issuecomment-1496102764 I don't think it's worth sweating over this, so let's just suck it up. refs: https://github.com/wez/wezterm/issues/1180
162 lines
4.6 KiB
GLSL
162 lines
4.6 KiB
GLSL
// This is the Glyph fragment shader.
|
|
// It is responsible for laying down the glyph graphics on top of the other layers.
|
|
#extension GL_EXT_blend_func_extended: enable
|
|
precision highp float;
|
|
|
|
in float o_has_color;
|
|
in vec2 o_tex;
|
|
in vec3 o_hsv;
|
|
in vec4 o_fg_color;
|
|
in vec4 o_fg_color_alt;
|
|
in float o_fg_color_mix;
|
|
|
|
// The color + alpha
|
|
layout(location=0, index=0) out vec4 color;
|
|
// Individual alpha channels for RGBA in color, used for subpixel
|
|
// antialiasing blending
|
|
layout(location=0, index=1) out vec4 colorMask;
|
|
|
|
uniform vec3 foreground_text_hsb;
|
|
uniform sampler2D atlas_nearest_sampler;
|
|
uniform sampler2D atlas_linear_sampler;
|
|
uniform bool subpixel_aa;
|
|
uniform uint milliseconds;
|
|
|
|
struct ColorEase {
|
|
vec4 in_function;
|
|
vec4 out_function;
|
|
uint in_duration_ms;
|
|
uint out_duration_ms;
|
|
};
|
|
|
|
float evaluate_cubic_bezier(vec4 bezier, float x) {
|
|
return pow(1.0 - x, 3.0) * bezier[0]
|
|
+ 3.0 * pow(1.0 - x, 2.) * x * bezier[1]
|
|
+ 3.0 * (1.0 - x) * pow(x, 2.) * bezier[2]
|
|
+ pow(x, 3.) * bezier[3];
|
|
}
|
|
|
|
float colorease_intensity(ColorEase ease) {
|
|
uint total_duration = ease.in_duration_ms + ease.out_duration_ms;
|
|
uint elapsed = milliseconds % total_duration;
|
|
if (elapsed < ease.in_duration_ms) {
|
|
return evaluate_cubic_bezier(
|
|
ease.in_function,
|
|
float(elapsed) / float(ease.in_duration_ms)
|
|
);
|
|
}
|
|
return 1.0 - evaluate_cubic_bezier(
|
|
ease.out_function,
|
|
float(elapsed - ease.in_duration_ms) / float(ease.out_duration_ms)
|
|
);
|
|
}
|
|
|
|
uniform ColorEase cursor_blink;
|
|
uniform ColorEase blink;
|
|
uniform ColorEase rapid_blink;
|
|
|
|
vec3 rgb2hsv(vec3 c)
|
|
{
|
|
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
|
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
|
|
|
float d = q.x - min(q.w, q.y);
|
|
float e = 1.0e-10;
|
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
|
}
|
|
|
|
vec3 hsv2rgb(vec3 c)
|
|
{
|
|
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
}
|
|
|
|
const vec3 unit3 = vec3(1.0);
|
|
|
|
vec4 apply_hsv(vec4 c, vec3 transform)
|
|
{
|
|
if (transform == unit3) {
|
|
return c;
|
|
}
|
|
vec3 hsv = rgb2hsv(c.rgb) * transform;
|
|
return vec4(hsv2rgb(hsv).rgb, c.a);
|
|
}
|
|
|
|
/*
|
|
float to_srgb(float x) {
|
|
if (x <= 0.0031308) {
|
|
return 12.92 * x;
|
|
}
|
|
return 1.055 * pow(x, (1.0 / 2.4)) - 0.055;
|
|
}
|
|
|
|
vec3 to_srgb(vec3 c) {
|
|
return vec3(to_srgb(c.r), to_srgb(c.g), to_srgb(c.b));
|
|
}
|
|
|
|
vec4 to_srgb(vec4 v) {
|
|
return vec4(to_srgb(v.rgb), v.a);
|
|
}
|
|
*/
|
|
|
|
vec4 to_srgb(vec4 linearRGB)
|
|
{
|
|
bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308));
|
|
vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055);
|
|
vec3 lower = linearRGB.rgb * vec3(12.92);
|
|
|
|
return vec4(mix(higher, lower, cutoff), linearRGB.a);
|
|
}
|
|
|
|
void main() {
|
|
vec4 fg_color = mix(o_fg_color, o_fg_color_alt, o_fg_color_mix);
|
|
if (o_has_color == 3.0) {
|
|
// Solid color block
|
|
color = fg_color;
|
|
colorMask = vec4(1.0);
|
|
} else if (o_has_color == 2.0) {
|
|
// The window background attachment
|
|
color = texture(atlas_linear_sampler, o_tex);
|
|
// Apply window_background_image_opacity to the background image
|
|
if (subpixel_aa) {
|
|
colorMask = fg_color.aaaa;
|
|
} else {
|
|
color.a *= fg_color.a;
|
|
}
|
|
} else if (o_has_color == 1.0) {
|
|
// the texture is full color info (eg: color emoji glyph)
|
|
color = texture(atlas_nearest_sampler, o_tex);
|
|
// this is the alpha
|
|
colorMask = color.aaaa;
|
|
} else if (o_has_color == 4.0) {
|
|
// Grayscale poly quad for non-aa text render layers
|
|
colorMask = texture(atlas_nearest_sampler, o_tex);
|
|
color = fg_color;
|
|
// On Intel hardware/drivers, we need to recompute the alpha this way.
|
|
// We don't know why; it doesn't make sense.
|
|
// The inputs are already in range and work fine on other platforms.
|
|
// See discussion starting at:
|
|
// <https://github.com/wez/wezterm/issues/1180#issuecomment-1496102764>
|
|
// for the background.
|
|
color.a = mix(o_fg_color.a, o_fg_color_alt.a, clamp(o_fg_color_mix, 0.0, 1.0));
|
|
color.a *= colorMask.a;
|
|
} else if (o_has_color == 0.0) {
|
|
// the texture is the alpha channel/color mask
|
|
colorMask = texture(atlas_nearest_sampler, o_tex);
|
|
// and we need to tint with the fg_color
|
|
color = fg_color;
|
|
if (!subpixel_aa) {
|
|
color.a = colorMask.a;
|
|
}
|
|
color = apply_hsv(color, foreground_text_hsb);
|
|
}
|
|
|
|
color = apply_hsv(color, o_hsv);
|
|
|
|
// We MUST output SRGB and tell glium that we do that (outputs_srgb),
|
|
// otherwise something in glium over-gamma-corrects depending on the gl setup.
|
|
color = to_srgb(color);
|
|
}
|