1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-18 19:01:36 +03:00
wezterm/wezterm-gui/src/glyph-frag.glsl
Wez Furlong 153497d01d
admit defeat to intel shader weirdness
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
2023-04-05 15:07:22 -07:00

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);
}