beamterm-core 1.0.0

Platform-agnostic OpenGL terminal renderer using glow
Documentation
// uniforms
uniform mediump sampler2DArray u_sampler;
layout(std140) uniform FragUbo {
    vec2 u_padding_frac;             // padding as fraction of cell size
    float u_underline_pos;           // underline position (0.0 = top, 1.0 = bottom)
    float u_underline_thickness;     // underline thickness as fraction of cell height
    float u_strikethrough_pos;       // strikethrough position (0.0 = top, 1.0 = bottom)
    float u_strikethrough_thickness; // strikethrough thickness as fraction of cell height
    uint u_emoji_bit;        // static atlas: 12, dynamic atlas: 15
    float u_bg_alpha;        // background cell opacity (0.0 = transparent, 1.0 = opaque)
};

flat in uint v_glyph_index;
flat in vec3 v_fg_color;
flat in vec3 v_bg_color;
in vec2 v_tex_coord;

out vec4 FragColor;

float horizontal_line(vec2 tex_coord, float center, float thickness) {
    return 1.0 - smoothstep(0.0, thickness, abs(tex_coord.y - center));
}

void main() {
    uint glyph_index = v_glyph_index;

    // texture position from sequential index (32 glyphs per layer)
    uint layer = (glyph_index & 0x1FFFu) >> 5u;
    uint pos_in_layer = glyph_index & 0x1Fu;

    // apply strikethrough or underline if the glyph has either bit set
    float line_alpha = max(
        horizontal_line(v_tex_coord, u_underline_pos, u_underline_thickness) * float((glyph_index >> 13u) & 0x1u),
        horizontal_line(v_tex_coord, u_strikethrough_pos, u_strikethrough_thickness) * float((glyph_index >> 14u) & 0x1u)
    );

    vec2 inner_tex_coord = v_tex_coord * (1.0 - 2.0 * u_padding_frac) + u_padding_frac;
    vec3 tex_coord = vec3(
        inner_tex_coord.x + 0.001,
        (float(pos_in_layer) + inner_tex_coord.y + 0.001) * 0.03125, // 0.03125 == 1/32
        float(layer)
    );

    // the base foreground color is used for normal glyphs and underlines/strikethroughs
    vec3 base_fg = v_fg_color;

    vec4 glyph = texture(u_sampler, tex_coord);

    // 0.0 for normal glyphs, 1.0 for emojis
    float emoji_factor = float((glyph_index >> u_emoji_bit) & 0x1u);

    // color for normal glyphs are taken from the packed data;
    // emoji colors are sampled from the texture directly
    vec3 fg = mix(base_fg, glyph.rgb, emoji_factor);

    // if we're drawing a line, blend it with the base foreground color.
    // this allows us to do strikethroughs and underlines on emojis with
    // the same color as the base foreground.
    fg = mix(fg, base_fg, line_alpha);

    float a = max(glyph.a, line_alpha);
    vec3 bg = v_bg_color;

    float cell_alpha = mix(u_bg_alpha, 1.0, a);
    FragColor = vec4(mix(bg, fg, a), cell_alpha);
}