render font at proper scale (sorta)
parent
a02c4d2b0a
commit
62ec411a5d
|
@ -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;
|
||||
|
|
58
src/main.c
58
src/main.c
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue