[vulkan] Use linear sampling for glyphs

This requires having padding around the glyphs to avoid texel leak, but
as the atlas is created at runtime, it's possible to get the padding in.
This commit is contained in:
Bill Currie 2022-11-20 03:59:01 +09:00
parent 4cbacc1149
commit 534d5367de
4 changed files with 48 additions and 14 deletions

View file

@ -102,7 +102,8 @@ R_FontLoad (QFile *font_file, int size)
FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT);
__auto_type g = font->face->glyph; __auto_type g = font->face->glyph;
pixels += g->bitmap.width * g->bitmap.rows; // include padding around the glyph to avoid texel leaks
pixels += (g->bitmap.width + 1) * (g->bitmap.rows + 1);
} }
pixels = sqrt (5 * pixels / 4); pixels = sqrt (5 * pixels / 4);
pixels = BITOP_RUP (pixels); pixels = BITOP_RUP (pixels);
@ -118,10 +119,15 @@ R_FontLoad (QFile *font_file, int size)
FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT);
__auto_type slot = font->face->glyph; __auto_type slot = font->face->glyph;
FT_Render_Glyph (slot, FT_RENDER_MODE_NORMAL); FT_Render_Glyph (slot, FT_RENDER_MODE_NORMAL);
int width = slot->bitmap.width; // add padding to create a buffer around the glyph to prevent texel
int height = slot->bitmap.rows; // leaks
int width = slot->bitmap.width + 1;
int height = slot->bitmap.rows + 1;
*rect = *R_ScrapAlloc (&font->scrap, width, height); *rect = *R_ScrapAlloc (&font->scrap, width, height);
*bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top }; *bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top };
// shrink the rect so as to NOT include the padding
rect->width -= 1;
rect->height -= 1;
copy_glyph (rect, slot, font); copy_glyph (rect, slot, font);
} }

View file

@ -474,6 +474,12 @@ bi_Draw_PrintBuffer (progs_t *pr, void *_res)
Draw_PrintBuffer (cbuff->buffer, str); Draw_PrintBuffer (cbuff->buffer, str);
} }
static void
bi_Draw_SetScale (progs_t *pr, void *_res)
{
Draw_SetScale (P_INT (pr, 0));
}
static const char * static const char *
bi_draw_get_key (const void *p, void *unused) bi_draw_get_key (const void *p, void *unused)
{ {
@ -540,6 +546,9 @@ static builtin_t builtins[] = {
bi(Draw_ScrollBuffer, 2, p(ptr), p(int)), bi(Draw_ScrollBuffer, 2, p(ptr), p(int)),
bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)), bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)),
bi(Draw_PrintBuffer, 2, p(ptr), p(string)), bi(Draw_PrintBuffer, 2, p(ptr), p(string)),
bi(Draw_SetScale, 1, p(int)),
{0} {0}
}; };

View file

@ -23,6 +23,23 @@
borderColor = float_transparent_black; borderColor = float_transparent_black;
unnormalizedCoordinates = false; unnormalizedCoordinates = false;
}; };
glyph = {
magFilter = linear;
minFilter = linear;
mipmapMode = linear;
addressModeU = clamp_to_edge;
addressModeV = clamp_to_edge;
addressModeW = clamp_to_edge;
mipLodBias = 0;
anisotropyEnable = false;
maxAnisotropy = 0;
compareEnable = false;
compareOp = always;
minLod = 0;
maxLod = 0;
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
palette_sampler = { palette_sampler = {
magFilter = nearest; magFilter = nearest;
minFilter = nearest; minFilter = nearest;

View file

@ -168,7 +168,8 @@ typedef struct drawfontset_s
DARRAY_TYPE (drawfont_t) drawfontset_t; DARRAY_TYPE (drawfont_t) drawfontset_t;
typedef struct drawctx_s { typedef struct drawctx_s {
VkSampler sampler; VkSampler pic_sampler;
VkSampler glyph_sampler;
scrap_t *scrap; scrap_t *scrap;
qfv_stagebuf_t *stage; qfv_stagebuf_t *stage;
qpic_t *crosshair; qpic_t *crosshair;
@ -576,7 +577,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
ctx->cmdpool); ctx->cmdpool);
dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba,
dctx->stage); dctx->stage);
dctx->sampler = Vulkan_CreateSampler (ctx, "quakepic"); dctx->pic_sampler = Vulkan_CreateSampler (ctx, "quakepic");
dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph");
draw_chars = W_GetLumpName ("conchars"); draw_chars = W_GetLumpName ("conchars");
if (draw_chars) { if (draw_chars) {
@ -623,7 +625,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool");
VkDescriptorImageInfo imageInfo = { VkDescriptorImageInfo imageInfo = {
dctx->sampler, dctx->pic_sampler,
QFV_ScrapImageView (dctx->scrap), QFV_ScrapImageView (dctx->scrap),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
}; };
@ -1369,20 +1371,20 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx)
float s = 1.0 / rfont->scrap.width; float s = 1.0 / rfont->scrap.width;
float t = 1.0 / rfont->scrap.height; float t = 1.0 / rfont->scrap.height;
verts[i * 4 + 0] = (glyphvert_t) { verts[i * 4 + 0] = (glyphvert_t) {
.offset = { x + 0, y + 0 }, .offset = { x, y },
.uv = {(u + 0.25) * s, (v + 0.25) * t }, .uv = { u * s, v * t },
}; };
verts[i * 4 + 1] = (glyphvert_t) { verts[i * 4 + 1] = (glyphvert_t) {
.offset = { x + 0, y + h }, .offset = { x, y + h },
.uv = {(u + 0.25) * s, (v + h - 0.25) * t }, .uv = { u * s, (v + h) * t },
}; };
verts[i * 4 + 2] = (glyphvert_t) { verts[i * 4 + 2] = (glyphvert_t) {
.offset = { x + w, y + 0 }, .offset = { x + w, y },
.uv = {(u + w - 0.25) * s, (v + 0.25) * t }, .uv = {(u + w) * s, v * t },
}; };
verts[i * 4 + 3] = (glyphvert_t) { verts[i * 4 + 3] = (glyphvert_t) {
.offset = { x + w, y + h }, .offset = { x + w, y + h },
.uv = {(u + w - 0.25) * s, (v + h - 0.25) * t }, .uv = {(u + w) * s, (v + h) * t },
}; };
} }
QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer,
@ -1403,7 +1405,7 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx)
__auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts); __auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts);
font->set = glyph_sets->a[0]; font->set = glyph_sets->a[0];
VkDescriptorImageInfo imageInfo = { VkDescriptorImageInfo imageInfo = {
dctx->sampler, dctx->glyph_sampler,
glyph_iview->image_view.view, glyph_iview->image_view.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
}; };