diff --git a/shaders/vertex.wgsl b/shaders/vertex.wgsl index 8425b90..b6ce346 100644 --- a/shaders/vertex.wgsl +++ b/shaders/vertex.wgsl @@ -15,17 +15,24 @@ struct VertexOutput { @location(0) tex_coord: vec2, } +struct Params { + screen_size: vec2, +} + fn to_device_position(position: vec2, size: vec2) -> vec4 { return vec4((((position / size) * 2.) - 1.), 1., 1.); } +@group(0) @binding(1) +var 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(0., input.y_offset+17), vec2(640., 480.)); + var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2(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(256); + var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2(1024); out.position = vertex_pos; out.tex_coord = atlas_position; diff --git a/src/main.c b/src/main.c index 869d626..4508a7d 100644 --- a/src/main.c +++ b/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();