vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 6906d1aa493bb3da7630a7f61914060b8e1886a2
Parent: cc1eb1cf3113d81c8432531acf2eedb3463c68b5
Author: Randy Palamar
Date:   Mon, 18 Nov 2024 18:18:16 -0700

make all computations involving the glyph bitmap integer

I don't know why I thought this was OK in the fragment shader but
it is not. Glyphs were getting blurred when they shouldn't be.
This was especially noticeable on lower resolution displays.

Diffstat:
Mfrag_render.glsl | 32++++++++++++++++----------------
Mterminal.c | 4++--
Mtest.c | 2+-
Mutil.h | 12++++++------
Mvtgl.c | 14+++++++-------
5 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/frag_render.glsl b/frag_render.glsl @@ -16,10 +16,10 @@ layout(std430, binding = 0) readonly restrict buffer ssbo_cells { }; layout(std140, binding = 0) uniform parameters { - uvec2 cell_size; - uvec2 term_size_in_cells; - vec2 term_size_in_pixels; - vec2 top_left_margin; + ivec2 cell_size; + ivec2 term_size_in_cells; + ivec2 term_size_in_pixels; + ivec2 top_left_margin; uint margin_colour; float blink_parameter; @@ -42,21 +42,21 @@ layout(location = 3) uniform sampler2D u_bitmap_texture; #define ATTR_INVISIBLE (1u << 4u) #define ATTR_STRUCK (1u << 5u) -vec2 +ivec2 unpack_glyph_position(uint glyph_position) { - vec2 result; - result.x = glyph_position & 0xFFFFu; - result.y = glyph_position >> 16u; + ivec2 result; + result.x = int(glyph_position & 0xFFFFu); + result.y = int(glyph_position >> 16u); return result; } void main() { - vec2 pixel_coord = gl_FragCoord.xy - top_left_margin; + ivec2 pixel_coord = ivec2(gl_FragCoord.xy) - top_left_margin; - uvec2 cell_index = uvec2(pixel_coord / cell_size); - vec2 cell_pos = mod(pixel_coord, cell_size); + ivec2 cell_index = pixel_coord / cell_size; + ivec2 cell_pos = ivec2(mod(pixel_coord, cell_size)); vec3 result; if (pixel_coord.x > 0 && cell_index.x < term_size_in_cells.x && @@ -68,9 +68,6 @@ void main() vec3 fg = unpackUnorm4x8(cell.fg ^ reverse_video_mask).wzy; vec3 bg = unpackUnorm4x8(cell.bg ^ reverse_video_mask).wzy; - vec2 glyph_pos = unpack_glyph_position(cell.gpu_glyph) * cell_size; - vec2 tex_coord = (glyph_pos + cell_pos) / vec2(textureSize(u_bitmap_texture, 0)); - if ((attr & ATTR_FAINT) != 0) fg *= 0.5; if ((attr & ATTR_BLINK) != 0) fg = mix(bg, fg, 0.5 * (1 + sin(blink_parameter))); @@ -80,7 +77,8 @@ void main() bg = tmp; } - vec4 smp = texture(u_bitmap_texture, tex_coord); + ivec2 glyph_pos = unpack_glyph_position(cell.gpu_glyph) * cell_size; + vec4 smp = texelFetch(u_bitmap_texture, glyph_pos + cell_pos, 0); result = mix(bg, fg * smp.xyz, smp.a); if (((attr & ATTR_UNDERLINED) != 0) && @@ -96,7 +94,9 @@ void main() /* NOTE: set to true to see the glyph cache texture */ if (false) { - vec4 smp = texture(u_bitmap_texture, pixel_coord / term_size_in_pixels); + /* NOTE: needs to use texture() since the cache texture + * may be different size than the window size */ + vec4 smp = texture(u_bitmap_texture, gl_FragCoord.xy / vec2(term_size_in_pixels)); colour = smp; } else { colour = vec4(result, 1); diff --git a/terminal.c b/terminal.c @@ -8,8 +8,8 @@ static const u8 utf8overhangmask[32] = { #define SPLIT_LONG 4096L -static uv2 -initialize_framebuffer(Framebuffer *fb, uv2 term_size) +static iv2 +initialize_framebuffer(Framebuffer *fb, iv2 term_size) { size cell_memory_size = sizeof(Cell) * term_size.h * term_size.w; size rows_memory_size = sizeof(Row) * term_size.h; diff --git a/test.c b/test.c @@ -349,7 +349,7 @@ main(void) ALT_BACKLOG_LINES); /* TODO: should probably be some odd size */ - term.size = (uv2){.w = 80, .h = 24}; + term.size = (iv2){.w = 80, .h = 24}; term.views[0].fb.backing_store = memory_block_from_arena(&memory, 2 * MEGABYTE); term.views[1].fb.backing_store = memory_block_from_arena(&memory, 2 * MEGABYTE); initialize_framebuffer(&term.views[0].fb, term.size); diff --git a/util.h b/util.h @@ -296,11 +296,11 @@ enum shader_stages { }; typedef struct { - uv2 cell_size; - uv2 term_size_in_cells; - v2 term_size_in_pixels; + iv2 cell_size; + iv2 term_size_in_cells; + iv2 term_size_in_pixels; - v2 top_left_margin; + iv2 top_left_margin; u32 margin_colour; f32 blink_parameter; @@ -418,7 +418,7 @@ typedef struct { } FontDesc; typedef struct { - u32 h, w; + i32 h, w; i32 baseline; } FontInfo; @@ -564,7 +564,7 @@ typedef struct Term { iptr child; - uv2 size; + iv2 size; /* NOTE: scrolling region */ u32 top, bot; diff --git a/vtgl.c b/vtgl.c @@ -261,10 +261,10 @@ resize(Term *t, PlatformAPI *platform, iv2 window_size) ws.w -= 2 * g_term_margin.w; ws.h -= 2 * g_term_margin.h; - uv2 old_size = t->size; + iv2 old_size = t->size; v2 cs = get_cell_size(&t->fa); - t->size.w = (u32)(ws.w / cs.w); - t->size.h = (u32)(ws.h / cs.h); + t->size.w = (i32)(ws.w / cs.w); + t->size.h = (i32)(ws.h / cs.h); if (t->size.w > ARRAY_COUNT(t->tabs) * 32) { t->size.w = ARRAY_COUNT(t->tabs) * 32u; @@ -275,7 +275,7 @@ resize(Term *t, PlatformAPI *platform, iv2 window_size) t->error_stream.widx = 0; } - if (!equal_uv2(old_size, t->size)) { + if (!equal_iv2(old_size, t->size)) { t->size = initialize_framebuffer(&t->views[0].fb, t->size); initialize_framebuffer(&t->views[1].fb, t->size); gl->flags |= NEEDS_FULL_REFILL; @@ -292,12 +292,12 @@ resize(Term *t, PlatformAPI *platform, iv2 window_size) platform->set_terminal_size(t->child, t->size.h, t->size.w, ws.w, ws.h); ShaderParameters *sp = &gl->shader_parameters; - sp->cell_size = (uv2){.w = cs.w, .h = cs.h}; + sp->cell_size = (iv2){.w = cs.w, .h = cs.h}; sp->top_left_margin = g_term_margin; sp->margin_colour = g_colours.data[g_colours.bgidx].rgba; //sp->margin_colour = 0x7f003f00; - sp->term_size_in_pixels = v2_from_iv2(gl->window_size); + sp->term_size_in_pixels = gl->window_size; sp->term_size_in_cells = t->size; gl->flags &= ~NEEDS_RESIZE; @@ -1073,7 +1073,7 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize) .y = cs.y * requested_cells.y + 2 * g_term_margin.y, }; - t->size = (uv2){.x = 1, .y = 1}; + t->size = (iv2){.x = 1, .y = 1}; initialize_framebuffer(&t->views[0].fb, t->size); initialize_framebuffer(&t->views[1].fb, t->size);