Explorar el Código

Factor out the Tile_Glyph renderer

rexim hace 4 años
padre
commit
74d8f39232
Se han modificado 6 ficheros con 265 adiciones y 214 borrados
  1. 1 1
      build.sh
  2. 0 0
      shaders/tile_glyph.frag
  3. 0 0
      shaders/tile_glyph.vert
  4. 20 213
      src/main.c
  5. 171 0
      src/tile_glyph.c
  6. 73 0
      src/tile_glyph.h

+ 1 - 1
build.sh

@@ -6,7 +6,7 @@ CC="${CXX:-cc}"
 PKGS="sdl2 glew"
 CFLAGS="-Wall -Wextra -std=c11 -pedantic -ggdb"
 LIBS=-lm
-SRC="src/main.c src/la.c src/editor.c src/sdl_extra.c src/file.c src/gl_extra.c"
+SRC="src/main.c src/la.c src/editor.c src/sdl_extra.c src/file.c src/gl_extra.c src/tile_glyph.c"
 
 if [ `uname` = "Darwin" ]; then
     CFLAGS+=" -framework OpenGL"

+ 0 - 0
shaders/font.frag → shaders/tile_glyph.frag


+ 0 - 0
shaders/font.vert → shaders/tile_glyph.vert


+ 20 - 213
src/main.c

@@ -18,19 +18,13 @@
 #include "./la.h"
 #include "./sdl_extra.h"
 #include "./gl_extra.h"
+#include "./tile_glyph.h"
 
 #define SCREEN_WIDTH 800
 #define SCREEN_HEIGHT 600
 #define FPS 60
 #define DELTA_TIME (1.0f / FPS)
 
-#define FONT_SCALE 5
-#define FONT_WIDTH 128
-#define FONT_HEIGHT 64
-#define FONT_COLS 18
-#define FONT_ROWS 7
-#define FONT_CHAR_WIDTH  (FONT_WIDTH  / FONT_COLS)
-#define FONT_CHAR_HEIGHT (FONT_HEIGHT / FONT_ROWS)
 
 Editor editor = {0};
 Vec2f camera_pos = {0};
@@ -66,99 +60,15 @@ void MessageCallback(GLenum source,
             type, severity, message);
 }
 
-typedef struct {
-    Vec2i tile;
-    int ch;
-    Vec4f fg_color;
-    Vec4f bg_color;
-} Tile_Glyph;
-
-typedef enum {
-    TILE_GLYPH_ATTR_TILE = 0,
-    TILE_GLYPH_ATTR_CH,
-    TILE_GLYPH_ATTR_FG_COLOR,
-    TILE_GLYPH_ATTR_BG_COLOR,
-    COUNT_TILE_GLYPH_ATTRS,
-} Tile_Glyph_Attr;
-
-typedef struct {
-    size_t offset;
-    GLint comps;
-    GLenum type;
-} Attr_Def;
-
-static const Attr_Def glyph_attr_defs[COUNT_TILE_GLYPH_ATTRS] = {
-    [TILE_GLYPH_ATTR_TILE]   = {
-        .offset = offsetof(Tile_Glyph, tile),
-        .comps = 2,
-        .type = GL_INT
-    },
-    [TILE_GLYPH_ATTR_CH]    = {
-        .offset = offsetof(Tile_Glyph, ch),
-        .comps = 1,
-        .type = GL_INT
-    },
-    [TILE_GLYPH_ATTR_FG_COLOR] = {
-        .offset = offsetof(Tile_Glyph, fg_color),
-        .comps = 4,
-        .type = GL_FLOAT
-    },
-    [TILE_GLYPH_ATTR_BG_COLOR] = {
-        .offset = offsetof(Tile_Glyph, bg_color),
-        .comps = 4,
-        .type = GL_FLOAT
-    },
-};
-static_assert(COUNT_TILE_GLYPH_ATTRS == 4, "The amount of glyph vertex attributes have changed");
-
-#define TILE_GLYPH_BUFFER_CAP (640 * 1024)
-
-Tile_Glyph tile_glyph_buffer[TILE_GLYPH_BUFFER_CAP];
-size_t tile_glyph_buffer_count = 0;
-
-void tile_glyph_buffer_clear(void)
-{
-    tile_glyph_buffer_count = 0;
-}
-
-void tile_glyph_buffer_push(Tile_Glyph glyph)
-{
-    assert(tile_glyph_buffer_count < TILE_GLYPH_BUFFER_CAP);
-    tile_glyph_buffer[tile_glyph_buffer_count++] = glyph;
-}
-
-void tile_glyph_buffer_sync(void)
-{
-    glBufferSubData(GL_ARRAY_BUFFER,
-                    0,
-                    tile_glyph_buffer_count * sizeof(Tile_Glyph),
-                    tile_glyph_buffer);
-}
-
-void gl_render_text_sized(const char *text, size_t text_size, Vec2i tile, Vec4f fg_color, Vec4f bg_color)
-{
-    for (size_t i = 0; i < text_size; ++i) {
-        tile_glyph_buffer_push((Tile_Glyph) {
-            .tile = vec2i_add(tile, vec2i((int) i, 0)),
-            .ch = text[i],
-            .fg_color = fg_color,
-            .bg_color = bg_color,
-        });
-    }
-}
-
-void gl_render_text(const char *text, Vec2i tile, Vec4f fg_color, Vec4f bg_color)
-{
-    gl_render_text_sized(text, strlen(text), tile, fg_color, bg_color);
-}
-
-void gl_render_cursor()
+void gl_render_cursor(Tile_Glyph_Buffer *tgb)
 {
     const char *c = editor_char_under_cursor(&editor);
     Vec2i tile = vec2i((int) editor.cursor_col, -(int) editor.cursor_row);
-    gl_render_text_sized(c ? c : " ", 1, tile, vec4fs(0.0f), vec4fs(1.0f));
+    tile_glyph_render_line_sized(tgb, c ? c : " ", 1, tile, vec4fs(0.0f), vec4fs(1.0f));
 }
 
+static Tile_Glyph_Buffer tgb = {0};
+
 // OPENGL
 int main(int argc, char **argv)
 {
@@ -223,113 +133,10 @@ int main(int argc, char **argv)
         fprintf(stderr, "WARNING! GLEW_ARB_debug_output is not available");
     }
 
-    GLint time_uniform;
-    GLint resolution_uniform;
-    GLint scale_uniform;
-    GLint camera_uniform;
-
-    // Initialize Shaders
-    {
-        GLuint vert_shader = 0;
-        if (!compile_shader_file("./shaders/font.vert", GL_VERTEX_SHADER, &vert_shader)) {
-            exit(1);
-        }
-        GLuint frag_shader = 0;
-        if (!compile_shader_file("./shaders/font.frag", GL_FRAGMENT_SHADER, &frag_shader)) {
-            exit(1);
-        }
-
-        GLuint program = 0;
-        if (!link_program(vert_shader, frag_shader, &program)) {
-            exit(1);
-        }
-
-        glUseProgram(program);
-
-        time_uniform = glGetUniformLocation(program, "time");
-        resolution_uniform = glGetUniformLocation(program, "resolution");
-        scale_uniform = glGetUniformLocation(program, "scale");
-        camera_uniform = glGetUniformLocation(program, "camera");
-
-        glUniform2f(scale_uniform, FONT_SCALE, FONT_SCALE);
-    }
-
-    // Init Font Texture
-    {
-        const char *font_file_path = "charmap-oldschool_white.png";
-        int width, height, n;
-        unsigned char *pixels = stbi_load(font_file_path, &width, &height, &n, STBI_rgb_alpha);
-        if (pixels == NULL) {
-            fprintf(stderr, "ERROR: could not load file %s: %s\n",
-                    file_path, stbi_failure_reason());
-            exit(1);
-        }
-
-        glActiveTexture(GL_TEXTURE0);
-
-        GLuint font_texture = 0;
-        glGenTextures(1, &font_texture);
-        glBindTexture(GL_TEXTURE_2D, font_texture);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-        glTexImage2D(GL_TEXTURE_2D,
-                     0,
-                     GL_RGBA,
-                     width,
-                     height,
-                     0,
-                     GL_RGBA,
-                     GL_UNSIGNED_BYTE,
-                     pixels);
-    }
-
-    // Init Buffers
-    {
-        GLuint vao = 0;
-        glGenVertexArrays(1, &vao);
-        glBindVertexArray(vao);
-
-        GLuint vbo = 0;
-        glGenBuffers(1, &vbo);
-        glBindBuffer(GL_ARRAY_BUFFER, vbo);
-        glBufferData(GL_ARRAY_BUFFER,
-                     sizeof(tile_glyph_buffer),
-                     tile_glyph_buffer,
-                     GL_DYNAMIC_DRAW);
-
-        for (Tile_Glyph_Attr attr = 0; attr < COUNT_TILE_GLYPH_ATTRS; ++attr) {
-            glEnableVertexAttribArray(attr);
-            switch (glyph_attr_defs[attr].type) {
-            case GL_FLOAT:
-                glVertexAttribPointer(
-                    attr,
-                    glyph_attr_defs[attr].comps,
-                    glyph_attr_defs[attr].type,
-                    GL_FALSE,
-                    sizeof(Tile_Glyph),
-                    (void*) glyph_attr_defs[attr].offset);
-                break;
-
-            case GL_INT:
-                glVertexAttribIPointer(
-                    attr,
-                    glyph_attr_defs[attr].comps,
-                    glyph_attr_defs[attr].type,
-                    sizeof(Tile_Glyph),
-                    (void*) glyph_attr_defs[attr].offset);
-                break;
-
-            default:
-                assert(false && "unreachable");
-                exit(1);
-            }
-            glVertexAttribDivisor(attr, 1);
-        }
-    }
+    tile_glyph_buffer_init(&tgb,
+                           "./charmap-oldschool_white.png",
+                           "./shaders/tile_glyph.vert",
+                           "./shaders/tile_glyph.frag");
 
     bool quit = false;
     while (!quit) {
@@ -435,33 +242,33 @@ int main(int argc, char **argv)
             SDL_GetWindowSize(window, &w, &h);
             // TODO(#19): update the viewport and the resolution only on actual window change
             glViewport(0, 0, w, h);
-            glUniform2f(resolution_uniform, (float) w, (float) h);
+            glUniform2f(tgb.resolution_uniform, (float) w, (float) h);
         }
 
-        tile_glyph_buffer_clear();
+        tile_glyph_buffer_clear(&tgb);
         {
             for (size_t row = 0; row < editor.size; ++row) {
                 const Line *line = editor.lines + row;
-                gl_render_text_sized(line->chars, line->size, vec2i(0, -(int)row), vec4fs(1.0f), vec4fs(0.0f));
+                tile_glyph_render_line_sized(&tgb, line->chars, line->size, vec2i(0, -(int)row), vec4fs(1.0f), vec4fs(0.0f));
             }
         }
-        tile_glyph_buffer_sync();
+        tile_glyph_buffer_sync(&tgb);
 
         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        glUniform1f(time_uniform, (float) SDL_GetTicks() / 1000.0f);
-        glUniform2f(camera_uniform, camera_pos.x, camera_pos.y);
+        glUniform1f(tgb.time_uniform, (float) SDL_GetTicks() / 1000.0f);
+        glUniform2f(tgb.camera_uniform, camera_pos.x, camera_pos.y);
 
-        glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, (GLsizei) tile_glyph_buffer_count);
+        tile_glyph_buffer_draw(&tgb);
 
-        tile_glyph_buffer_clear();
+        tile_glyph_buffer_clear(&tgb);
         {
-            gl_render_cursor();
+            gl_render_cursor(&tgb);
         }
-        tile_glyph_buffer_sync();
+        tile_glyph_buffer_sync(&tgb);
 
-        glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, (GLsizei) tile_glyph_buffer_count);
+        tile_glyph_buffer_draw(&tgb);
 
         SDL_GL_SwapWindow(window);
 

+ 171 - 0
src/tile_glyph.c

@@ -0,0 +1,171 @@
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include "./stb_image.h"
+#include "./tile_glyph.h"
+#include "./gl_extra.h"
+
+static const Attr_Def glyph_attr_defs[COUNT_TILE_GLYPH_ATTRS] = {
+    [TILE_GLYPH_ATTR_TILE]   = {
+        .offset = offsetof(Tile_Glyph, tile),
+        .comps = 2,
+        .type = GL_INT
+    },
+    [TILE_GLYPH_ATTR_CH]    = {
+        .offset = offsetof(Tile_Glyph, ch),
+        .comps = 1,
+        .type = GL_INT
+    },
+    [TILE_GLYPH_ATTR_FG_COLOR] = {
+        .offset = offsetof(Tile_Glyph, fg_color),
+        .comps = 4,
+        .type = GL_FLOAT
+    },
+    [TILE_GLYPH_ATTR_BG_COLOR] = {
+        .offset = offsetof(Tile_Glyph, bg_color),
+        .comps = 4,
+        .type = GL_FLOAT
+    },
+};
+static_assert(COUNT_TILE_GLYPH_ATTRS == 4, "The amount of glyph vertex attributes have changed");
+
+void tile_glyph_buffer_clear(Tile_Glyph_Buffer *tgb)
+{
+    tgb->glyphs_count = 0;
+}
+
+void tile_glyph_buffer_push(Tile_Glyph_Buffer *tgb, Tile_Glyph glyph)
+{
+    assert(tgb->glyphs_count < TILE_GLYPH_BUFFER_CAP);
+    tgb->glyphs[tgb->glyphs_count++] = glyph;
+}
+
+void tile_glyph_buffer_sync(Tile_Glyph_Buffer *tgb)
+{
+    glBufferSubData(GL_ARRAY_BUFFER,
+                    0,
+                    tgb->glyphs_count * sizeof(Tile_Glyph),
+                    tgb->glyphs);
+}
+
+void tile_glyph_render_line_sized(Tile_Glyph_Buffer *tgb, const char *text, size_t text_size, Vec2i tile, Vec4f fg_color, Vec4f bg_color)
+{
+    for (size_t i = 0; i < text_size; ++i) {
+        tile_glyph_buffer_push(tgb, (Tile_Glyph) {
+            .tile = vec2i_add(tile, vec2i((int) i, 0)),
+            .ch = text[i],
+            .fg_color = fg_color,
+            .bg_color = bg_color,
+        });
+    }
+}
+
+void tile_glyph_render_line(Tile_Glyph_Buffer *tgb, const char *text, Vec2i tile, Vec4f fg_color, Vec4f bg_color)
+{
+    tile_glyph_render_line_sized(tgb, text, strlen(text), tile, fg_color, bg_color);
+}
+
+void tile_glyph_buffer_init(Tile_Glyph_Buffer *tgb, const char *texture_file_path, const char *vert_file_path, const char *frag_file_path)
+{
+    // Init Vertex Attributes
+    {
+        glGenVertexArrays(1, &tgb->vao);
+        glBindVertexArray(tgb->vao);
+
+        glGenBuffers(1, &tgb->vbo);
+        glBindBuffer(GL_ARRAY_BUFFER, tgb->vbo);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(tgb->glyphs), tgb->glyphs, GL_DYNAMIC_DRAW);
+
+        for (Tile_Glyph_Attr attr = 0; attr < COUNT_TILE_GLYPH_ATTRS; ++attr) {
+            glEnableVertexAttribArray(attr);
+            switch (glyph_attr_defs[attr].type) {
+            case GL_FLOAT:
+                glVertexAttribPointer(
+                    attr,
+                    glyph_attr_defs[attr].comps,
+                    glyph_attr_defs[attr].type,
+                    GL_FALSE,
+                    sizeof(Tile_Glyph),
+                    (void*) glyph_attr_defs[attr].offset);
+                break;
+
+            case GL_INT:
+                glVertexAttribIPointer(
+                    attr,
+                    glyph_attr_defs[attr].comps,
+                    glyph_attr_defs[attr].type,
+                    sizeof(Tile_Glyph),
+                    (void*) glyph_attr_defs[attr].offset);
+                break;
+
+            default:
+                assert(false && "unreachable");
+                exit(1);
+            }
+            glVertexAttribDivisor(attr, 1);
+        }
+    }
+
+    // Init Shaders
+    {
+        GLuint vert_shader = 0;
+        if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &vert_shader)) {
+            exit(1);
+        }
+        GLuint frag_shader = 0;
+        if (!compile_shader_file(frag_file_path, GL_FRAGMENT_SHADER, &frag_shader)) {
+            exit(1);
+        }
+
+        GLuint program = 0;
+        if (!link_program(vert_shader, frag_shader, &program)) {
+            exit(1);
+        }
+
+        glUseProgram(program);
+
+        tgb->time_uniform = glGetUniformLocation(program, "time");
+        tgb->resolution_uniform = glGetUniformLocation(program, "resolution");
+        tgb->scale_uniform = glGetUniformLocation(program, "scale");
+        tgb->camera_uniform = glGetUniformLocation(program, "camera");
+
+        glUniform2f(tgb->scale_uniform, FONT_SCALE, FONT_SCALE);
+    }
+
+    // Init Texture
+    {
+        int width, height, n;
+        unsigned char *pixels = stbi_load(texture_file_path, &width, &height, &n, STBI_rgb_alpha);
+        if (pixels == NULL) {
+            fprintf(stderr, "ERROR: could not load file %s: %s\n",
+                    texture_file_path, stbi_failure_reason());
+            exit(1);
+        }
+
+        glActiveTexture(GL_TEXTURE0);
+        glGenTextures(1, &tgb->font_texture);
+        glBindTexture(GL_TEXTURE_2D, tgb->font_texture);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+        glTexImage2D(GL_TEXTURE_2D,
+                     0,
+                     GL_RGBA,
+                     width,
+                     height,
+                     0,
+                     GL_RGBA,
+                     GL_UNSIGNED_BYTE,
+                     pixels);
+
+        stbi_image_free(pixels);
+    }
+}
+
+void tile_glyph_buffer_draw(Tile_Glyph_Buffer *tgb)
+{
+    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, (GLsizei) tgb->glyphs_count);
+}

+ 73 - 0
src/tile_glyph.h

@@ -0,0 +1,73 @@
+#ifndef TILE_GLYPH_H_
+#define TILE_GLYPH_H_
+
+#include <stdlib.h>
+#include "./la.h"
+
+#define GLEW_STATIC
+#include <GL/glew.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <SDL2/SDL_opengl.h>
+
+#define FONT_SCALE 5
+#define FONT_WIDTH 128
+#define FONT_HEIGHT 64
+#define FONT_COLS 18
+#define FONT_ROWS 7
+#define FONT_CHAR_WIDTH  (FONT_WIDTH  / FONT_COLS)
+#define FONT_CHAR_HEIGHT (FONT_HEIGHT / FONT_ROWS)
+
+typedef struct {
+    Vec2i tile;
+    int ch;
+    Vec4f fg_color;
+    Vec4f bg_color;
+} Tile_Glyph;
+
+typedef enum {
+    TILE_GLYPH_ATTR_TILE = 0,
+    TILE_GLYPH_ATTR_CH,
+    TILE_GLYPH_ATTR_FG_COLOR,
+    TILE_GLYPH_ATTR_BG_COLOR,
+    COUNT_TILE_GLYPH_ATTRS,
+} Tile_Glyph_Attr;
+
+typedef struct {
+    size_t offset;
+    GLint comps;
+    GLenum type;
+} Attr_Def;
+
+#define TILE_GLYPH_BUFFER_CAP (640 * 1024)
+
+typedef struct {
+    GLuint vao;
+    GLuint vbo;
+
+    GLuint font_texture;
+
+    GLint time_uniform;
+    GLint resolution_uniform;
+    GLint scale_uniform;
+    GLint camera_uniform;
+
+    size_t glyphs_count;
+    Tile_Glyph glyphs[TILE_GLYPH_BUFFER_CAP];
+} Tile_Glyph_Buffer;
+
+void tile_glyph_buffer_init(Tile_Glyph_Buffer *buffer,
+                            const char *texture_file_path,
+                            const char *vert_file_path,
+                            const char *frag_file_path);
+
+void tile_glyph_buffer_clear(Tile_Glyph_Buffer *buffer);
+void tile_glyph_buffer_push(Tile_Glyph_Buffer *buffer, Tile_Glyph glyph);
+void tile_glyph_buffer_sync(Tile_Glyph_Buffer *buffer);
+
+void tile_glyph_render_line_sized(Tile_Glyph_Buffer *buffer, const char *text, size_t text_size, Vec2i tile, Vec4f fg_color, Vec4f bg_color);
+void tile_glyph_render_line(Tile_Glyph_Buffer *buffer, const char *text, Vec2i tile, Vec4f fg_color, Vec4f bg_color);
+
+void tile_glyph_buffer_draw(Tile_Glyph_Buffer *buffer);
+
+#endif // TILE_GLYPH_H_