From 107b03f9019ec79324e9ef23b5ec9f4aa7e04f75 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 29 Aug 2022 07:11:23 +0200 Subject: Refactor update/render functions to use the context --- src/main.c | 210 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 122 insertions(+), 88 deletions(-) diff --git a/src/main.c b/src/main.c index 543ef86..98b9764 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,8 @@ #include "shorthand.h" +#define TEXT_OVERLAY_SIZE 5 + // // Callbacks. // @@ -27,6 +29,13 @@ glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mod } } +// Letter for a the monospace text overlay layer. +struct Letter { + f32 x; + f32 y; + f32 idx; +}; + typedef struct Context { GLFWwindow *window; u32 gl_version_major; @@ -41,6 +50,20 @@ typedef struct Context { f64 elapsed; size_t n_frames; } frame_time; + + struct { + u32 program; + u32 tex_id; + u32 vao; + u32 vbo; + u32 ebo; + + struct Letter letters[2048]; + u32 cur_x; + u32 cur_y; + u32 n_chars; + u32 size; + } text_overlay; } Context; u32 @@ -133,53 +156,6 @@ init_context(Context *ctx) { void init_debug_overlay(Context *ctx) { - // TODO: Add debug text to context and initialize here - (void)ctx; -} - -void -setup_callbacks(Context *ctx) { - glfwSetErrorCallback(glfw_error_callback); - glfwSetKeyCallback(ctx->window, glfw_key_callback); -} - -void -update_frame_time(Context *ctx) { - // Measure frame times and fps. - f64 cur_time = glfwGetTime(); - f64 delta_time = cur_time - ctx->frame_time.prev; - ctx->frame_time.elapsed += delta_time; - ctx->frame_time.n_frames++; - if (ctx->frame_time.elapsed >= 1.0) { - f64 fps = 0; - fps = ctx->frame_time.n_frames / ctx->frame_time.elapsed; - ctx->frame_time.elapsed = 0; - ctx->frame_time.n_frames = 0; - - // Update title with timing data. - char title_buf[256 * 2]; - sprintf(title_buf, - "%s [%.2fms, %.2f FPS]", - ctx->win_title, delta_time * 1000, fps); - glfwSetWindowTitle(ctx->window, title_buf); - } - ctx->frame_time.prev = cur_time; -} - -void -update(Context *ctx) { - update_frame_time(ctx); -} - -void -render(Context *ctx) { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glfwGetFramebufferSize(ctx->window, &ctx->win_width, &ctx->win_height); - glViewport(0, 0, ctx->win_width, ctx->win_height); - - // TODO: Only need to be done once on the initialization function. // Prepare quad rendering. f32 vertices[] = { // position // tex_coords @@ -194,9 +170,8 @@ render(Context *ctx) { }; // Vertex array object. - u32 vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + glGenVertexArrays(1, &ctx->text_overlay.vao); + glBindVertexArray(ctx->text_overlay.vao); // Vertex buffer object setup. u32 vbo; @@ -208,33 +183,19 @@ render(Context *ctx) { glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)(2 * sizeof(f32))); - // NOTE: This should be a dynamic array of offsets and index into the - // texture atlas. - struct Letter { - f32 x; - f32 y; - f32 idx; - }; - struct Letter letters[] = { - {0, 0.0, 0}, - {1, 0.0, 1}, - {2, 0.0, 2}, - }; - u32 offset_vbo; - glGenBuffers(1, &offset_vbo); - glBindBuffer(GL_ARRAY_BUFFER, offset_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(letters), letters, GL_STATIC_DRAW); + glGenBuffers(1, &ctx->text_overlay.vbo); + glBindBuffer(GL_ARRAY_BUFFER, ctx->text_overlay.vbo); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*)0); glVertexAttribDivisor(2, 1); // Element buffer object setup. - u32 ebo; - glGenBuffers(1, &ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glGenBuffers(1, &ctx->text_overlay.ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ctx->text_overlay.ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Texture atlas. + // TODO: Full 256 ascii font. u8 texture[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, @@ -245,9 +206,8 @@ render(Context *ctx) { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - u32 tex_id; - glGenTextures(1, &tex_id); - glBindTexture(GL_TEXTURE_2D, tex_id); + glGenTextures(1, &ctx->text_overlay.tex_id); + glBindTexture(GL_TEXTURE_2D, ctx->text_overlay.tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 8 * 3, 8, 0, GL_RED, GL_UNSIGNED_BYTE, &texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -266,21 +226,24 @@ render(Context *ctx) { "layout (location = 1) in vec2 tex_coords;\n" "layout (location = 2) in vec3 offset;\n" "out vec2 tex;\n" -"void main() {\n" -// TODO: Uniforms -" float w = 800;\n" -" float h = 600;\n" -" float size = 5;\n" -" float N = 3;\n" +"uniform float w;\n" +"uniform float h;\n" +"uniform float size;\n" + +"void main() {\n" +" float N = 3;\n" // TODO: should be 256 for the full font. " float idx = offset.z;\n" " float m = 1.0 / N;\n" " float k = m * idx;\n" + // TODO: Only 8x8 monospace fonts for now " float font_w = 8;\n" " float font_h = 8;\n" + // NOTE: This makes sures that the fonts have the right size. " vec2 scalar = vec2(font_w / w, font_h / h) * size;\n" + " vec2 pos = tex_coords * scalar;\n" " pos += vec2(0.0, 1.0 - scalar.y);\n" " pos += scalar * offset.xy;\n" @@ -300,14 +263,87 @@ render(Context *ctx) { " frag = vec4(val, val, val, 1.0);\n" "}\n"; - u32 program = compile_program(ctx, vert_src, frag_src); + ctx->text_overlay.program = compile_program(ctx, vert_src, frag_src); + ctx->text_overlay.cur_x = 0; + ctx->text_overlay.cur_y = 0; + ctx->text_overlay.n_chars = 0; + ctx->text_overlay.size = TEXT_OVERLAY_SIZE; +} + +void +setup_callbacks(Context *ctx) { + glfwSetErrorCallback(glfw_error_callback); + glfwSetKeyCallback(ctx->window, glfw_key_callback); +} + +void +update_frame_time(Context *ctx) { + // Measure frame times and fps. + f64 cur_time = glfwGetTime(); + f64 delta_time = cur_time - ctx->frame_time.prev; + ctx->frame_time.elapsed += delta_time; + ctx->frame_time.n_frames++; + if (ctx->frame_time.elapsed >= 1.0) { + f64 fps = 0; + fps = ctx->frame_time.n_frames / ctx->frame_time.elapsed; + ctx->frame_time.elapsed = 0; + ctx->frame_time.n_frames = 0; + + // Update title with timing data. + char title_buf[256 * 2]; + sprintf(title_buf, + "%s [%.2fms, %.2f FPS]", + ctx->win_title, delta_time * 1000, fps); + glfwSetWindowTitle(ctx->window, title_buf); + } + ctx->frame_time.prev = cur_time; +} + +void +update_text(Context *ctx) { + // TODO: Test with the full font atlas and characters. + // TODO: add_text function for setting up letters[] based on a char* + n_chars. + ctx->text_overlay.letters[0].x = 0; + ctx->text_overlay.letters[0].y = 0; + ctx->text_overlay.letters[0].idx = 0; + ctx->text_overlay.letters[1].x = 1; + ctx->text_overlay.letters[1].y = 0; + ctx->text_overlay.letters[1].idx = 1; + ctx->text_overlay.letters[2].x = 2; + ctx->text_overlay.letters[2].y = 0; + ctx->text_overlay.letters[2].idx = 2; + ctx->text_overlay.n_chars = 3; + glBindBuffer(GL_ARRAY_BUFFER, ctx->text_overlay.vbo); + glBufferData(GL_ARRAY_BUFFER, + sizeof(struct Letter) * ctx->text_overlay.n_chars, + ctx->text_overlay.letters, + GL_STATIC_DRAW); +} + +void +update(Context *ctx) { + update_frame_time(ctx); + update_text(ctx); +} + +void +render(Context *ctx) { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glfwGetFramebufferSize(ctx->window, &ctx->win_width, &ctx->win_height); + glViewport(0, 0, ctx->win_width, ctx->win_height); + + glUseProgram(ctx->text_overlay.program); + glBindVertexArray(ctx->text_overlay.vao); + glBindTexture(GL_TEXTURE_2D, ctx->text_overlay.tex_id); - glUseProgram(program); - glBindVertexArray(vao); - glBindTexture(GL_TEXTURE_2D, tex_id); + // Update uniforms. + glUniform1f(glGetUniformLocation(ctx->text_overlay.program, "w"), ctx->win_width); + glUniform1f(glGetUniformLocation(ctx->text_overlay.program, "h"), ctx->win_height); + glUniform1f(glGetUniformLocation(ctx->text_overlay.program, "size"), ctx->text_overlay.size); - // TODO: How to pass the parameters for each box? - // NOTE: We want to render the text as a single draw call if possible. + // TODO: Which blend mode to use? // glEnable(GL_BLEND); // glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // // glBlendFunc(GL_ONE, GL_ONE); @@ -322,10 +358,8 @@ render(Context *ctx) { // // glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); // // glBlendEquation(GL_FUNC_ADD); // - // glBindTexture(GL_TEXTURE_2D, text_tex); // TODO: Bind the texture atlas. - // TODO: Send the number of instances as a uniform or see if you can query - // it from the GLSL for N. In this case N == 3. - glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, 3); + glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, + ctx->text_overlay.n_chars); // glDisable(GL_BLEND); glfwSwapBuffers(ctx->window); -- cgit v1.2.1