From: Brendan Hansen Date: Sun, 9 May 2021 03:57:14 +0000 (-0500) Subject: slightly better font rendering; using 'em' units X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=88ca9cd1141272128d8ac0148bde30f948481bdd;p=tower.git slightly better font rendering; using 'em' units --- diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..c70f55d --- /dev/null +++ b/build.bat @@ -0,0 +1,10 @@ +@echo off + +set TARGET=site\tower.wasm +set ONYX_INSTALLATION_FOLDER=\dev\onyx + +copy "%ONYX_INSTALLATION_FOLDER%\bin\onyx-loader.js" .\site\js\onyx-loader.js >NUL +copy "%ONYX_INSTALLATION_FOLDER%\modules\webgl2\webgl2.js" .\site\js\webgl2.js >NUL +copy "%ONYX_INSTALLATION_FOLDER%\modules\js_events\js_events.js" .\site\js\js_events.js >NUL + +\dev\onyx\onyx -r js --use-post-mvp-features -V -o %TARGET% src\build.onyx -I %ONYX_INSTALLATION_FOLDER% diff --git a/src/font/bitmap_font.onyx b/src/font/bitmap_font.onyx index 1ec0cb5..8807862 100644 --- a/src/font/bitmap_font.onyx +++ b/src/font/bitmap_font.onyx @@ -30,10 +30,13 @@ use package core Bitmap_Font :: struct { font_texture : Bitmap_Font_Texture; + em: f32; // Width of 'M' + glyphs : map.Map(u32, Glyph); Glyph :: struct { x0, y0, x1, y1: f32; + w, h: f32; } get_glyph :: (use bmp: ^Bitmap_Font, char: u8) -> ^Glyph { @@ -49,10 +52,15 @@ Bitmap_Font_Texture :: struct { // NOTE: Assumes pixels are laid out in RGBA format. get_pixel :: (use texture: ^Bitmap_Font_Texture, x: u32, y: u32) -> u32 { - return (cast(u32) data[(y * width + x) * Components_Per_Pixel + 0] << 24) - | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 1] << 16) - | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 2] << 8) - | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 3] << 0); + return (cast(^u32) data.data)[y * width + x]; + + // SPEED: All of these values could be read simultaneously by treating the data + // array as a slice of u32, and then not multiplying by Components_Per_Pixel. + // + // return (cast(u32) data[(y * width + x) * Components_Per_Pixel + 0] << 24) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 1] << 16) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 2] << 8) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 3] << 0); } } @@ -66,7 +74,7 @@ bitmap_font_create :: (bft: Bitmap_Font_Texture, glyph_str: str) -> Bitmap_Font bmp: Bitmap_Font; bmp.font_texture = bft; - map.init(^bmp.glyphs, .{0,0,0,0}); + map.init(^bmp.glyphs, .{0,0,0,0,0,0}); success := bitmap_font_prepare_glyphs(^bmp, glyph_str); assert(success, "Failed to load glyphs out of font."); @@ -81,6 +89,8 @@ bitmap_font_prepare_glyphs :: (use bmp: ^Bitmap_Font, glyph_str: str) -> bool { g_x0, g_y0 = 0, 0; for glyph_char: glyph_str { + if g_y0 >= font_texture.height do return false; + // These will need to be converted to floating point when they are inserted into the glyph, // but it is easier to think about them as actual pixel coordinates when parsing the glyphs. x0, y0, x1, y1: u32; @@ -95,6 +105,8 @@ bitmap_font_prepare_glyphs :: (use bmp: ^Bitmap_Font, glyph_str: str) -> bool { y0 = cast(f32) y0 / ~~font_texture.height, x1 = cast(f32) x1 / ~~font_texture.width, y1 = cast(f32) y1 / ~~font_texture.height, + w = cast(f32) (x1 - x0) / ~~font_texture.width, + h = cast(f32) (y1 - y0) / ~~font_texture.height, }); g_x0 = x1 + 1; @@ -107,5 +119,13 @@ bitmap_font_prepare_glyphs :: (use bmp: ^Bitmap_Font, glyph_str: str) -> bool { } } + M_glyph := map.get_ptr(^glyphs, #char "M"); + if M_glyph != null { + em = M_glyph.w * ~~font_texture.width; + } else { + // ROBUSTNESS: If there is no 'M' in the character set, then just use 16. It will probably be very wrong. + em = 16; + } + return true; } diff --git a/src/res/font.data b/src/res/font.data index 96b8ec4..615eafb 100644 Binary files a/src/res/font.data and b/src/res/font.data differ diff --git a/src/res/font_2.data b/src/res/font_2.data new file mode 100644 index 0000000..85287d4 Binary files /dev/null and b/src/res/font_2.data differ diff --git a/src/tower.onyx b/src/tower.onyx index 35d0bd3..47a97a4 100644 --- a/src/tower.onyx +++ b/src/tower.onyx @@ -19,12 +19,15 @@ main :: (args: [] cstr) { init_font(); + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + start_loop :: () -> void #foreign "game" "start_loop" --- start_loop(); } init_font :: () { - font_data := #file_contents "src/res/font.data"; + font_data := #file_contents "src/res/font_2.data"; bft := bitmap_font.Bitmap_Font_Texture.{ data = font_data, @@ -32,7 +35,7 @@ init_font :: () { height = 256, }; - font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff"); + font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff:"); font_texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, font_texture); @@ -73,21 +76,37 @@ poll_events :: () { gl.setSize(event.resize.width, event.resize.height); gl.viewport(0, 0, event.resize.width, event.resize.height); + gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height); } } } +fps := 0; +fps_timer := 1.0f; +frames := 0 update :: (dt: f32) { + fps_timer -= dt; + frames += 1; + if fps_timer < 0 { + fps = frames; + frames = 0; + fps_timer = 1.0f; + } } draw :: () { gl.clearColor(0.1, 0.1, 0.1, 1); gl.clear(gl.COLOR_BUFFER_BIT); - gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height); + fps_buffer : [16] u8; + fps_str := conv.str_format("FPS: %i", ~~ fps_buffer, fps); + draw_text(fps_str, 0, 0, 32, .{0,1,0}); draw_text("Hello World", 100, 100, 128); - draw_text("something else...", 100, 230, 32); + draw_text("something else...", 100, 230, 32, .{1,0,0}); + + draw_text("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 100, 300, 16); + draw_text("abcdefghijklmnopqrstuvwxyz", 100, 340, 16); gfx.flush(); } @@ -96,11 +115,10 @@ draw :: () { -draw_text :: (text: str, x: f32, y: f32, size := 32.0f) { +draw_text :: (text: str, x: f32, y: f32, size := 32.0f, color := gfx.Color4.{1,1,1}) { gl.bindTexture(gl.TEXTURE_2D, font_texture); gfx.set_texture(0); - gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height); for char: text { glyph := font->get_glyph(char); @@ -110,13 +128,14 @@ draw_text :: (text: str, x: f32, y: f32, size := 32.0f) { assert(glyph != null, "NO NULL GLYPH"); } - gfx.textured_quad( + gfx.textured_rect( .{ x, y }, - .{ size, size }, + .{ glyph.w * size * font.em, glyph.h * size * font.em }, .{ glyph.x0, glyph.y0 }, - .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 }); + .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 }, + color = color); - x += size; + x += glyph.w * size * 16; } gfx.flush();