render font at proper scale (sorta)

main
Patrick Cleavelin 2024-03-15 14:41:37 -05:00
parent a02c4d2b0a
commit 62ec411a5d
2 changed files with 50 additions and 19 deletions

View File

@ -15,17 +15,24 @@ struct VertexOutput {
@location(0) tex_coord: vec2<f32>,
}
struct Params {
screen_size: vec2<f32>,
}
fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
}
@group(0) @binding(1)
var<uniform> params: Params;
@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * input.size + input.target_position + vec2<f32>(0., input.y_offset+17), vec2<f32>(640., 480.));
var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2<f32>(0., (input.y_offset/2.0)+32), params.screen_size);
vertex_pos.y = -vertex_pos.y;
var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(256);
var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
out.position = vertex_pos;
out.tex_coord = atlas_position;

View File

@ -43,6 +43,10 @@ typedef struct {
float y_offset;
} GpuGlyph;
typedef struct {
float screen_size[2];
} GpuUniformParams;
typedef struct {
size_t size;
size_t capacity;
@ -101,7 +105,7 @@ void queue_text(String text, float position[2]) {
glyph.position[0] = x+position[0];
glyph.position[1] = position[1];
x += glyph.size[0];
x += glyph.size[0]/2;
push_u8array(&state.gpu_glyphs, &glyph, sizeof(GpuGlyph));
}
@ -112,6 +116,17 @@ void vertex_shader_loaded(const sfetch_response_t *response) {
if (response->fetched) {
state.scratch_shader_desc.vs.source = response->data.ptr;
state.scratch_shader_desc.vs.entry = "vs_main";
state.scratch_shader_desc.vs = (sg_shader_stage_desc) {
.source = response->data.ptr,
.entry = "vs_main",
.uniform_blocks[0] = {
.size = sizeof(GpuUniformParams),
.layout = SG_UNIFORMLAYOUT_NATIVE,
.uniforms = {
[0] = { .name = "screen_size", .type = SG_UNIFORMTYPE_FLOAT2 },
},
},
};
} else if (response->failed) {
fprintf(stderr, "failed to load vertex shader\n");
exit(1);
@ -189,37 +204,38 @@ void ed_init() {
sfetch_dowork();
}
uint8_t *font_bitmap = context_alloc(256*256 * sizeof(uint8_t));
const int font_bitmap_size = 1024;
const int rasterized_font_height = 64;
uint8_t *font_bitmap = context_alloc(font_bitmap_size*font_bitmap_size * sizeof(uint8_t));
state.gpu_ui_rects = new_u8array(sizeof(GpuUiRect) * 2000);
state.gpu_glyphs = new_u8array(sizeof(GpuGlyph) * 1024);
state.glyph_cache = new_u8array(sizeof(GpuGlyph) * 96);
state.glyph_cache = new_u8array(sizeof(GpuGlyph) * 97);
int ascent, descent, line_gap;
float scale = stbtt_ScaleForPixelHeight(&font, 32);
float scale = stbtt_ScaleForPixelHeight(&font, rasterized_font_height);
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
int xxx = 0;
for (size_t xx=0; xx < 16; ++xx) {
for (size_t yy=0; yy < 16; ++yy) {
font_bitmap[xx + yy * 256] = 0;
for (size_t xx=0; xx < rasterized_font_height/2; ++xx) {
for (size_t yy=0; yy < rasterized_font_height; ++yy) {
font_bitmap[xx + yy * font_bitmap_size] = 0;
}
}
// manually add glyph for SPACE
push_u8array(&state.glyph_cache, &(GpuGlyph){
.atlas_position = { 0 },
.size = { 16, 16 },
.size = { rasterized_font_height/4, rasterized_font_height },
.position = { 0 },
.y_offset = -16.0,
.y_offset = -rasterized_font_height,
}, 1 * sizeof(GpuGlyph));
int x = 16;
int x = rasterized_font_height/4;
int y = 0;
for (size_t i = 33; i < 33+96; ++i) {
int width,height, xoff,yoff;
uint8_t *bitmap = stbtt_GetCodepointBitmap(&font, scale, scale, (int)i, &width, &height, &xoff, &yoff);
if (x + width >= 256) {
if (x + width >= font_bitmap_size) {
x = 0;
y += (int)((float)(ascent - descent + line_gap)*scale);
}
@ -228,7 +244,7 @@ void ed_init() {
for (size_t xx=0; xx < width; ++xx) {
int yyy = y;
for (size_t yy=0; yy < height; ++yy) {
font_bitmap[xxx + yyy * 256] = bitmap[xx + yy * width];
font_bitmap[xxx + yyy * font_bitmap_size] = bitmap[xx + yy * width];
yyy += 1;
}
@ -252,12 +268,12 @@ void ed_init() {
.label = "glyph buffer"
});
state.text_atlas_sampler = sg_make_sampler(&(sg_sampler_desc) { .mag_filter = SG_FILTER_NEAREST });
state.text_atlas_sampler = sg_make_sampler(&(sg_sampler_desc) { .mag_filter = SG_FILTER_LINEAR });
state.text_atlas_image = sg_make_image(&(sg_image_desc) {
.width = 256,
.height = 256,
.width = font_bitmap_size,
.height = font_bitmap_size,
.pixel_format = SG_PIXELFORMAT_R8,
.data.subimage[0][0] = { .ptr = font_bitmap, .size = 256*256 * sizeof(uint8_t) },
.data.subimage[0][0] = { .ptr = font_bitmap, .size = font_bitmap_size*font_bitmap_size * sizeof(uint8_t) },
});
state.bind.fs.images[0] = state.text_atlas_image;
state.bind.fs.samplers[0] = state.text_atlas_sampler;
@ -298,10 +314,18 @@ void ed_frame() {
});
}
GpuUniformParams gpu_uniform_params = {
.screen_size = {
sapp_width(),
sapp_height()
},
};
sg_begin_pass(&(sg_pass) { .action = state.pass_action, .swapchain = sglue_swapchain() });
{
sg_apply_pipeline(state.pip);
sg_apply_bindings(&state.bind);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &(sg_range) { .ptr = &gpu_uniform_params, .size = sizeof(GpuUniformParams) });
sg_draw(0, 6, state.gpu_glyphs.size/sizeof(GpuGlyph));
}
sg_end_pass();