From 0bdfa9e814ac869f5643023a33eafb1f0c34f582 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 29 Dec 2022 10:26:21 +0000 Subject: [PATCH] Text rendering culling --- source/engine/font.c | 64 +++++++++++++++++------------------- source/engine/mrbffi.c | 10 ++++-- source/engine/openglrender.c | 2 ++ source/engine/yugine.c | 23 ++++++++++--- source/engine/yugine.h | 2 ++ source/scripts/engine.scm | 1 + source/shaders/textfrag.glsl | 10 +++--- 7 files changed, 67 insertions(+), 45 deletions(-) diff --git a/source/engine/font.c b/source/engine/font.c index e97aad4..eb28ee6 100644 --- a/source/engine/font.c +++ b/source/engine/font.c @@ -14,12 +14,12 @@ #include #include "stb_rect_pack.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" static uint32_t VBO = 0; -static uint32_t VAO = 0; unsigned char ttf_buffer[1<<25]; -unsigned char temp_bitmap[512 * 512]; struct sFont *font; static struct shader *shader; @@ -29,22 +29,16 @@ void font_init(struct shader *textshader) { shader_use(shader); - // configure VAO/VBO for texture quads - glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); - glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, NULL, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); // Default font - font = MakeFont("teenytinypixels.ttf", 16); + //font = MakeFont("teenytinypixels.ttf", 30); + font = MakeFont("LessPerfectDOSVGA.ttf", 16); } void font_frame(struct window *w) { @@ -55,6 +49,8 @@ struct sFont *MakeFont(const char *fontfile, int height) { shader_use(shader); + int packsize = 128; + struct sFont *newfont = calloc(1, sizeof(struct sFont)); newfont->height = height; @@ -62,18 +58,17 @@ struct sFont *MakeFont(const char *fontfile, int height) snprintf(fontpath, 256, "fonts/%s", fontfile); fread(ttf_buffer, 1, 1<<25, fopen(fontpath, "rb")); - unsigned char *bitmap = malloc(1024*1024); + unsigned char *bitmap = malloc(packsize*packsize); stbtt_packedchar glyphs[95]; stbtt_pack_context pc; - stbtt_PackBegin(&pc, bitmap, 1024, 1024, 0, 1, NULL); - stbtt_PackSetOversampling(&pc, 1, 1); + stbtt_PackBegin(&pc, bitmap, packsize, packsize, 0, 1, NULL); stbtt_PackFontRange(&pc, ttf_buffer, 0, height, 32, 95, glyphs); stbtt_PackEnd(&pc); - + stbi_write_png("packedfont.png", packsize, packsize, 1, bitmap, sizeof(char)*packsize); stbtt_fontinfo fontinfo; if (!stbtt_InitFont(&fontinfo, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0))) { @@ -81,11 +76,11 @@ struct sFont *MakeFont(const char *fontfile, int height) } float scale = stbtt_ScaleForPixelHeight(&fontinfo, height); - //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &newfont->texID); glBindTexture(GL_TEXTURE_2D, newfont->texID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1024, 1024, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap); - glGenerateMipmap(GL_TEXTURE_2D); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, packsize, packsize, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap); + //glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -94,24 +89,23 @@ struct sFont *MakeFont(const char *fontfile, int height) for (unsigned char c = 32; c < 127; c++) { - //unsigned char *bitmap; - int advance, lsb, w, h, x0, y0; - stbtt_GetCodepointHMetrics(&fontinfo, c, &advance, &lsb); stbtt_packedchar glyph = glyphs[c-32]; - YughInfo("Packed char is at %d, %d, %d, %d", glyphs[c-32].x0, glyphs[c-32].y0, glyphs[c-32].x1, glyphs[c-32].y1); + YughInfo("Packed char %c is at %d, %d, %d, %d", c, glyphs[c-32].x0, glyphs[c-32].y0, glyphs[c-32].x1, glyphs[c-32].y1); + + YughInfo("Offsets are %f %f %f %f", glyph.xoff, glyph.yoff, glyph.xoff2, glyph.yoff2); struct glrect r; - r.s0 = glyph.x0 / (float)1024; - r.s1 = glyph.x1 / (float) 1024; - r.t0 = glyph.y0 / (float) 1024; - r.t1 = glyph.y1 / (float) 1024; - YughInfo("That is %f %f %f %f", r.s0, r.t0, r.s1, r.t1); - newfont->Characters[c].Advance = advance * scale; - newfont->Characters[c].Size[0] = glyphs[c-32].x1 - glyphs[c-32].x0; - newfont->Characters[c].Size[1] = glyphs[c-32].y1 - glyphs[c-32].y0; - newfont->Characters[c].Bearing[0] = x0; - newfont->Characters[c].Bearing[1] = y0*-1; + r.s0 = glyph.x0 / (float) packsize; + r.s1 = glyph.x1 / (float) packsize; + r.t0 = glyph.y0 / (float) packsize; + r.t1 = glyph.y1 / (float) packsize; + + newfont->Characters[c].Advance = glyph.xadvance; + newfont->Characters[c].Size[0] = glyph.x1 - glyph.x0; + newfont->Characters[c].Size[1] = glyph.y1 - glyph.y0; + newfont->Characters[c].Bearing[0] = glyph.xoff; + newfont->Characters[c].Bearing[1] = glyph.yoff2; newfont->Characters[c].rect = r; } @@ -126,7 +120,7 @@ void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct float h = c.Size[1] * scale; float xpos = cursor[0] + c.Bearing[0] * scale; - float ypos = cursor[1] + (c.Bearing[1] * scale) - h; + float ypos = cursor[1] - c.Bearing[1] * scale; float verts[4 * 4] = { xpos, ypos, c.rect.s0, c.rect.t1, @@ -135,6 +129,9 @@ void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct xpos + w, ypos + h, c.rect.s1, c.rect.t0 }; + if (verts[5] < 0 || verts[10] < 0 || verts[0] > window_i(0)->width || verts[1] > window_i(0)->height) + return; + glBufferSubData(GL_ARRAY_BUFFER, curchar*sizeof(verts), sizeof(verts), verts); curchar++; @@ -158,9 +155,10 @@ void renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, font->texID); - glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, len*16*sizeof(float), NULL, GL_STREAM_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); const unsigned char *line, *wordstart; line = (unsigned char*)text; diff --git a/source/engine/mrbffi.c b/source/engine/mrbffi.c index 7e2d0c1..8e87d67 100644 --- a/source/engine/mrbffi.c +++ b/source/engine/mrbffi.c @@ -77,7 +77,7 @@ s7_pointer s7_gui_text(s7_scheme *sc, s7_pointer args) { float size = s7_real(s7_caddr(args)); const float white[3] = {1.f, 1.f, 1.f}; - renderText(s, fpos, size, white, 200); + renderText(s, fpos, size, white, 1800); return s7_car(args); } @@ -138,7 +138,8 @@ s7_pointer s7_log(s7_scheme *sc, s7_pointer args) { s7_pointer s7_ui_rendertext(s7_scheme *sc, s7_pointer args) { const char *s = s7_string(s7_car(args)); s7_pointer s7pos = s7_cadr(args); - double pos[2] = { s7_vector_ref(sc, s7pos, 0), s7_vector_ref(sc, s7pos, 1) }; + cpVect cpos = s7tovec2(sc, s7_cadr(args)); + double pos[2] = { cpos.x, cpos.y }; double size = s7_real(s7_caddr(args)); double white[3] = {1.f, 1.f, 1.f}; @@ -247,6 +248,9 @@ s7_pointer s7_sys_cmd(s7_scheme *sc, s7_pointer args) { case 7: return s7_make_integer(sc, MakeGameobject()); + case 8: + return s7_make_integer(sc, frame_fps()); + } return args; @@ -346,7 +350,7 @@ s7_pointer s7_phys_cmd(s7_scheme *sc, s7_pointer args) { int cmd = s7_integer(s7_cadr(args)); s7_pointer env = s7_caddr(args); - if (go == -1) return; + if (go == -1) return s7_nil(sc); phys2d_add_handler_type(cmd, get_gameobject_from_id(go), env); } diff --git a/source/engine/openglrender.c b/source/engine/openglrender.c index 04268cb..54d34f3 100644 --- a/source/engine/openglrender.c +++ b/source/engine/openglrender.c @@ -94,6 +94,8 @@ void openglInit() glClearColor(editorClearColor[0], editorClearColor[1], editorClearColor[2], editorClearColor[3]); glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 0575919..86f32bd 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -44,7 +44,10 @@ static double lastTick; static float timescale = 1.f; -static double framems; +#define FPSBUF 10 +static double framems[FPSBUF]; +int framei = 0; +int fps; void seghandle(int sig) { #ifdef __linux__ @@ -172,7 +175,12 @@ int main(int argc, char **args) { double elapsed = glfwGetTime() - lastTick; deltaT = elapsed; lastTick = glfwGetTime(); + double wait = fmax(0, renderMS-elapsed); + input_poll(wait); + window_all_handle_events(); + framems[framei++] = elapsed; + if (framei == FPSBUF) framei = 0; timer_update(elapsed); @@ -194,14 +202,21 @@ int main(int argc, char **args) { window_renderall(); } - double wait = fmax(0, renderMS-elapsed); - input_poll(wait); - window_all_handle_events(); } return 0; } +int frame_fps() +{ + double fpsms = 0; + for (int i = 0; i < FPSBUF; i++) { + fpsms += framems[i]; + } + + return floor((float)FPSBUF / fpsms); +} + int sim_playing() { return sim_play; } int sim_paused() { return (!sim_play && gameobjects_saved()); } diff --git a/source/engine/yugine.h b/source/engine/yugine.h index 582b678..24bf081 100644 --- a/source/engine/yugine.h +++ b/source/engine/yugine.h @@ -9,5 +9,7 @@ void sim_stop(); void sim_step(); void set_timescale(float val); +int frame_fps(); + #endif \ No newline at end of file diff --git a/source/scripts/engine.scm b/source/scripts/engine.scm index be4da42..ebdb3e0 100644 --- a/source/scripts/engine.scm +++ b/source/scripts/engine.scm @@ -49,6 +49,7 @@ (define (load_level s) (gen_cmd 0 s)) (define (load_prefab s) (gen_cmd 1 s)) (define (newobject) (sys_cmd 7)) +(define (fps) (sys_cmd 8)) (define (quit) (sys_cmd 0)) (define (exit) (quit)) diff --git a/source/shaders/textfrag.glsl b/source/shaders/textfrag.glsl index 075fb66..3c93e00 100644 --- a/source/shaders/textfrag.glsl +++ b/source/shaders/textfrag.glsl @@ -7,9 +7,9 @@ uniform vec3 textColor; void main() { - vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); - color = vec4(textColor, 1.0) * sampled; - - if (color.a <= 0.1f) - discard; + //vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); + //color = vec4(textColor, 1.0) * sampled; + color = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); + //if (color.a <= 0.1f) + //discard; } \ No newline at end of file