Browse Source

Merge pull request #33 from tsoding/zoom

Zoom
Alexey Kutepov 4 years ago
parent
commit
c7fb61a9e5

+ 1 - 1
build.sh

@@ -6,7 +6,7 @@ CC="${CXX:-cc}"
 PKGS="sdl2 glew freetype2"
 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/tile_glyph.c src/free_glyph.c src/cursor_renderer.c"
+SRC="src/main.c src/la.c src/editor.c src/sdl_extra.c src/file.c src/gl_extra.c src/free_glyph.c src/cursor_renderer.c src/uniforms.c"
 
 if [ `uname` = "Darwin" ]; then
     CFLAGS+=" -framework OpenGL"

BIN
charmap-oldschool_white.png


+ 8 - 0
shaders/camera.vert

@@ -0,0 +1,8 @@
+uniform vec2 resolution;
+uniform float camera_scale;
+uniform vec2 camera_pos;
+
+vec2 camera_project(vec2 point)
+{
+    return 2.0 * (point - camera_pos) * camera_scale / resolution;
+}

+ 6 - 9
shaders/cursor.vert

@@ -1,23 +1,20 @@
 #version 330 core
 
 uniform vec2 resolution;
-uniform vec2 camera;
-uniform vec2 pos;
-uniform float height;
+uniform vec2 cursor_pos;
+uniform float cursor_height;
 
 #define WIDTH 5.0
 
 out vec2 uv;
 
-vec2 project_point(vec2 point)
-{
-    return 2.0 * (point - camera) / resolution;
-}
+vec2 camera_project(vec2 point);
 
 void main() {
-    uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));
+    uv = vec2(float(gl_VertexID & 1),
+              float((gl_VertexID >> 1) & 1));
     gl_Position = vec4(
-        project_point(uv * vec2(WIDTH, height) + pos),
+        camera_project(uv * vec2(WIDTH, cursor_height) + cursor_pos),
         0.0,
         1.0);
 }

+ 2 - 5
shaders/free_glyph.vert

@@ -1,7 +1,7 @@
 #version 330 core
 
 uniform vec2 resolution;
-uniform vec2 camera;
+uniform float time;
 
 layout(location = 0) in vec2 pos;
 layout(location = 1) in vec2 size;
@@ -16,10 +16,7 @@ out vec2 glyph_uv_size;
 out vec4 glyph_fg_color;
 out vec4 glyph_bg_color;
 
-vec2 camera_project(vec2 point)
-{
-    return 2.0 * (point - camera) / resolution;
-}
+vec2 camera_project(vec2 point);
 
 void main() {
     uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));

+ 0 - 51
shaders/tile_glyph.frag

@@ -1,51 +0,0 @@
-#version 330 core
-
-#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)
-#define FONT_CHAR_WIDTH_UV  (float(FONT_CHAR_WIDTH) / float(FONT_WIDTH))
-#define FONT_CHAR_HEIGHT_UV (float(FONT_CHAR_HEIGHT) / float(FONT_HEIGHT))
-
-#define ASCII_DISPLAY_LOW 32
-#define ASCII_DISPLAY_HIGH 126
-
-uniform sampler2D font;
-uniform float time;
-uniform vec2 resolution;
-
-in vec2 uv;
-flat in int glyph_ch;
-in vec4 glyph_fg_color;
-in vec4 glyph_bg_color;
-
-float map01(float x)
-{
-    return (x + 1) / 2.0;
-}
-
-vec3 hsl2rgb(vec3 c) {
-    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0);
-    return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
-}
-
-void main() {
-    int ch = glyph_ch;
-    if (!(ASCII_DISPLAY_LOW <= ch && ch <= ASCII_DISPLAY_HIGH)) {
-        ch = 63;
-    }
-
-    int index = ch - 32;
-    float x = float(index % FONT_COLS) * FONT_CHAR_WIDTH_UV;
-    float y = float(index / FONT_COLS) * FONT_CHAR_HEIGHT_UV;
-    vec2 pos = vec2(x, y + FONT_CHAR_HEIGHT_UV);
-    vec2 size = vec2(FONT_CHAR_WIDTH_UV, -FONT_CHAR_HEIGHT_UV);
-    vec2 t = pos + size * uv;
-
-    vec4 tc = texture(font, t);
-    vec2 frag_uv = gl_FragCoord.xy / resolution;
-    vec4 rainbow = vec4(hsl2rgb(vec3((time + frag_uv.x + frag_uv.y), 0.5, 0.5)), 1.0);
-    gl_FragColor = glyph_bg_color * (1.0 - tc.x) + tc.x * glyph_fg_color * rainbow;
-}

+ 0 - 40
shaders/tile_glyph.vert

@@ -1,40 +0,0 @@
-#version 330 core
-
-#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)
-
-uniform vec2 resolution;
-uniform vec2 scale;
-uniform float time;
-uniform vec2 camera;
-
-layout(location = 0) in ivec2 tile;
-layout(location = 1) in int ch;
-layout(location = 2) in vec4 fg_color;
-layout(location = 3) in vec4 bg_color;
-
-out vec2 uv;
-flat out int glyph_ch;
-out vec4 glyph_fg_color;
-out vec4 glyph_bg_color;
-
-vec2 project_point(vec2 point)
-{
-    return 2.0 * (point - camera) / resolution;
-}
-
-void main() {
-    uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));
-    vec2 char_size = vec2(float(FONT_CHAR_WIDTH), float(FONT_CHAR_HEIGHT));
-    vec2 pos = tile * char_size * scale;
-
-    gl_Position = vec4(project_point(uv * char_size * scale + pos), 0.0, 1.0);
-    glyph_ch = ch;
-
-    glyph_fg_color = fg_color;
-    glyph_bg_color = bg_color;
-}

+ 12 - 13
src/cursor_renderer.c

@@ -8,27 +8,26 @@ void cursor_renderer_init(Cursor_Renderer *cr,
 {
     // Init Shaders
     {
-        GLuint vert_shader = 0;
-        if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &vert_shader)) {
+        GLuint shaders[3] = {0};
+
+        if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &shaders[0])) {
+            exit(1);
+        }
+        if (!compile_shader_file(frag_file_path, GL_FRAGMENT_SHADER, &shaders[1])) {
             exit(1);
         }
-        GLuint frag_shader = 0;
-        if (!compile_shader_file(frag_file_path, GL_FRAGMENT_SHADER, &frag_shader)) {
+        if (!compile_shader_file("./shaders/camera.vert", GL_VERTEX_SHADER, &shaders[2])) {
             exit(1);
         }
 
-        if (!link_program(vert_shader, frag_shader, &cr->program)) {
+        cr->program = glCreateProgram();
+        attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), cr->program);
+        if (!link_program(cr->program, __FILE__, __LINE__)) {
             exit(1);
         }
 
         glUseProgram(cr->program);
-
-        cr->time_uniform = glGetUniformLocation(cr->program, "time");
-        cr->resolution_uniform = glGetUniformLocation(cr->program, "resolution");
-        cr->camera_uniform = glGetUniformLocation(cr->program, "camera");
-        cr->pos_uniform = glGetUniformLocation(cr->program, "pos");
-        cr->height_uniform = glGetUniformLocation(cr->program, "height");
-        cr->last_stroke_uniform = glGetUniformLocation(cr->program, "last_stroke");
+        get_uniform_location(cr->program, cr->uniforms);
     }
 }
 
@@ -39,7 +38,7 @@ void cursor_renderer_use(const Cursor_Renderer *cr)
 
 void cursor_renderer_move_to(const Cursor_Renderer *cr, Vec2f pos)
 {
-    glUniform2f(cr->pos_uniform, pos.x, pos.y);
+    glUniform2f(cr->uniforms[UNIFORM_SLOT_CURSOR_POS], pos.x, pos.y);
 }
 
 void cursor_renderer_draw()

+ 2 - 6
src/cursor_renderer.h

@@ -8,16 +8,12 @@
 #include <SDL2/SDL_opengl.h>
 
 #include "./la.h"
+#include "./uniforms.h"
 
 typedef struct {
     GLuint program;
 
-    GLint time_uniform;
-    GLint resolution_uniform;
-    GLint camera_uniform;
-    GLint pos_uniform;
-    GLint height_uniform;
-    GLint last_stroke_uniform;
+    GLint uniforms[COUNT_UNIFORM_SLOTS];
 } Cursor_Renderer;
 
 void cursor_renderer_init(Cursor_Renderer *cr,

+ 16 - 18
src/free_glyph.c

@@ -93,24 +93,26 @@ void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
 
     // Init Shaders
     {
-        GLuint vert_shader = 0;
-        if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &vert_shader)) {
+        GLuint shaders[3] = {0};
+
+        if (!compile_shader_file(vert_file_path, GL_VERTEX_SHADER, &shaders[0])) {
+            exit(1);
+        }
+        if (!compile_shader_file(frag_file_path, GL_FRAGMENT_SHADER, &shaders[1])) {
             exit(1);
         }
-        GLuint frag_shader = 0;
-        if (!compile_shader_file(frag_file_path, GL_FRAGMENT_SHADER, &frag_shader)) {
+        if (!compile_shader_file("./shaders/camera.vert", GL_VERTEX_SHADER, &shaders[2])) {
             exit(1);
         }
 
-        if (!link_program(vert_shader, frag_shader, &fgb->program)) {
+        fgb->program = glCreateProgram();
+        attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), fgb->program);
+        if (!link_program(fgb->program, __FILE__, __LINE__)) {
             exit(1);
         }
 
         glUseProgram(fgb->program);
-
-        fgb->time_uniform = glGetUniformLocation(fgb->program, "time");
-        fgb->resolution_uniform = glGetUniformLocation(fgb->program, "resolution");
-        fgb->camera_uniform = glGetUniformLocation(fgb->program, "camera");
+        get_uniform_location(fgb->program, fgb->uniforms);
     }
 
     // Glyph Texture Atlas
@@ -230,17 +232,17 @@ float free_glyph_buffer_cursor_pos(const Free_Glyph_Buffer *fgb, const char *tex
     return pos.x;
 }
 
-void free_glyph_buffer_render_line_sized(Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f pos, Vec4f fg_color, Vec4f bg_color)
+void free_glyph_buffer_render_line_sized(Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f *pos, Vec4f fg_color, Vec4f bg_color)
 {
     for (size_t i = 0; i < text_size; ++i) {
         Glyph_Metric metric = fgb->metrics[(int) text[i]];
-        float x2 = pos.x + metric.bl;
-        float y2 = -pos.y - metric.bt;
+        float x2 = pos->x + metric.bl;
+        float y2 = -pos->y - metric.bt;
         float w  = metric.bw;
         float h  = metric.bh;
 
-        pos.x += metric.ax;
-        pos.y += metric.ay;
+        pos->x += metric.ax;
+        pos->y += metric.ay;
 
         Free_Glyph glyph = {0};
         glyph.pos = vec2f(x2, -y2);
@@ -253,7 +255,3 @@ void free_glyph_buffer_render_line_sized(Free_Glyph_Buffer *fgb, const char *tex
     }
 }
 
-void free_glyph_buffer_render_line(Free_Glyph_Buffer *fgb, const char *text, Vec2f pos, Vec4f fg_color, Vec4f bg_color)
-{
-    free_glyph_buffer_render_line_sized(fgb, text, strlen(text), pos, fg_color, bg_color);
-}

+ 5 - 5
src/free_glyph.h

@@ -13,6 +13,8 @@
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
+#include "./uniforms.h"
+
 // https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02
 
 typedef struct {
@@ -59,9 +61,7 @@ typedef struct {
 
     GLuint glyphs_texture;
 
-    GLint time_uniform;
-    GLint resolution_uniform;
-    GLint camera_uniform;
+    GLint uniforms[COUNT_UNIFORM_SLOTS];
 
     size_t glyphs_count;
     Free_Glyph glyphs[FREE_GLYPH_BUFFER_CAP];
@@ -81,7 +81,7 @@ void free_glyph_buffer_draw(Free_Glyph_Buffer *fgb);
 
 float free_glyph_buffer_cursor_pos(const Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f pos, size_t col);
 
-void free_glyph_buffer_render_line_sized(Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f pos, Vec4f fg_color, Vec4f bg_color);
-void free_glyph_buffer_render_line(Free_Glyph_Buffer *fgb, const char *text, Vec2f pos, Vec4f fg_color, Vec4f bg_color);
+void free_glyph_buffer_render_line_sized(Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f *pos, Vec4f fg_color, Vec4f bg_color);
+
 
 #endif // FREE_GLYPH_H_

+ 12 - 12
src/gl_extra.c

@@ -47,26 +47,26 @@ bool compile_shader_file(const char *file_path, GLenum shader_type, GLuint *shad
     return ok;
 }
 
-bool link_program(GLuint vert_shader, GLuint frag_shader, GLuint *program)
+void attach_shaders_to_program(GLuint *shaders, size_t shaders_count, GLuint program)
 {
-    *program = glCreateProgram();
+    for (size_t i = 0; i < shaders_count; ++i) {
+        glAttachShader(program, shaders[i]);
+    }
+}
 
-    glAttachShader(*program, vert_shader);
-    glAttachShader(*program, frag_shader);
-    glLinkProgram(*program);
+bool link_program(GLuint program, const char *file_path, size_t line)
+{
+    glLinkProgram(program);
 
     GLint linked = 0;
-    glGetProgramiv(*program, GL_LINK_STATUS, &linked);
+    glGetProgramiv(program, GL_LINK_STATUS, &linked);
     if (!linked) {
         GLsizei message_size = 0;
         GLchar message[1024];
 
-        glGetProgramInfoLog(*program, sizeof(message), &message_size, message);
-        fprintf(stderr, "Program Linking: %.*s\n", message_size, message);
+        glGetProgramInfoLog(program, sizeof(message), &message_size, message);
+        fprintf(stderr, "%s:%zu: Program Linking: %.*s\n", file_path, line, message_size, message);
     }
 
-    glDeleteShader(vert_shader);
-    glDeleteShader(frag_shader);
-
-    return program;
+    return linked;
 }

+ 2 - 1
src/gl_extra.h

@@ -10,6 +10,7 @@
 
 bool compile_shader_source(const GLchar *source, GLenum shader_type, GLuint *shader);
 bool compile_shader_file(const char *file_path, GLenum shader_type, GLuint *shader);
-bool link_program(GLuint vert_shader, GLuint frag_shader, GLuint *program);
+void attach_shaders_to_program(GLuint *shaders, size_t shaders_count, GLuint program);
+bool link_program(GLuint program, const char *file_path, size_t line);
 
 #endif // GL_EXTRA_H_

+ 5 - 0
src/la.c

@@ -114,3 +114,8 @@ Vec4f vec4f_div(Vec4f a, Vec4f b)
 {
     return vec4f(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
 }
+
+float lerpf(float a, float b, float t)
+{
+    return a + (b - a) * t;
+}

+ 2 - 0
src/la.h

@@ -36,4 +36,6 @@ Vec4f vec4f_sub(Vec4f a, Vec4f b);
 Vec4f vec4f_mul(Vec4f a, Vec4f b);
 Vec4f vec4f_div(Vec4f a, Vec4f b);
 
+float lerpf(float a, float b, float t);
+
 #endif // LA_H_

+ 43 - 103
src/main.c

@@ -24,7 +24,6 @@
 #include "./la.h"
 #include "./sdl_extra.h"
 #include "./gl_extra.h"
-#include "./tile_glyph.h"
 #include "./free_glyph.h"
 #include "./cursor_renderer.h"
 
@@ -36,6 +35,8 @@
 
 Editor editor = {0};
 Vec2f camera_pos = {0};
+float camera_scale = 3.0f;
+float camera_scale_vel = 0.0f;
 Vec2f camera_vel = {0};
 
 void usage(FILE *stream)
@@ -71,90 +72,43 @@ void MessageCallback(GLenum source,
             type, severity, message);
 }
 
-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);
-    tile_glyph_render_line_sized(tgb, c ? c : " ", 1, tile, vec4fs(0.0f), vec4fs(1.0f));
-}
-
-// #define TILE_GLYPH_RENDER
-
-#ifdef TILE_GLYPH_RENDER
-static Tile_Glyph_Buffer tgb = {0};
-#else
 static Free_Glyph_Buffer fgb = {0};
 static Cursor_Renderer cr = {0};
-#endif
-
-void render_editor_into_tgb(SDL_Window *window, Tile_Glyph_Buffer *tgb, Editor *editor)
-{
-    {
-        // TODO: Zoom
-        const Vec2f cursor_pos =
-            vec2f((float) editor->cursor_col * FONT_CHAR_WIDTH * FONT_SCALE,
-                  (float) (-(int)editor->cursor_row) * FONT_CHAR_HEIGHT * FONT_SCALE);
-
-        camera_vel = vec2f_mul(
-                         vec2f_sub(cursor_pos, camera_pos),
-                         vec2fs(2.0f));
-
-        camera_pos = vec2f_add(camera_pos, vec2f_mul(camera_vel, vec2fs(DELTA_TIME)));
-    }
-
-    {
-        int w, h;
-        SDL_GetWindowSize(window, &w, &h);
-        glUniform2f(tgb->resolution_uniform, (float) w, (float) h);
-    }
-
-    tile_glyph_buffer_clear(tgb);
-    {
-        for (size_t row = 0; row < editor->size; ++row) {
-            const Line *line = editor->lines + row;
-
-            tile_glyph_render_line_sized(tgb, line->chars, line->size, vec2i(0, -(int)row), vec4fs(1.0f), vec4fs(0.0f));
-        }
-    }
-    tile_glyph_buffer_sync(tgb);
-
-    glUniform1f(tgb->time_uniform, (float) SDL_GetTicks() / 1000.0f);
-    glUniform2f(tgb->camera_uniform, camera_pos.x, camera_pos.y);
-
-    tile_glyph_buffer_draw(tgb);
-
-    tile_glyph_buffer_clear(tgb);
-    {
-        gl_render_cursor(tgb);
-    }
-    tile_glyph_buffer_sync(tgb);
-
-    tile_glyph_buffer_draw(tgb);
-}
 
 #define FREE_GLYPH_FONT_SIZE 64
-
+#define ZOOM_OUT_GLYPH_THRESHOLD 30
 
 void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Cursor_Renderer *cr, Editor *editor)
 {
     int w, h;
     SDL_GetWindowSize(window, &w, &h);
 
+    float max_line_len = 0.0f;
+
     free_glyph_buffer_use(fgb);
     {
-        glUniform2f(fgb->resolution_uniform, (float) w, (float) h);
-        glUniform1f(fgb->time_uniform, (float) SDL_GetTicks() / 1000.0f);
-        glUniform2f(fgb->camera_uniform, camera_pos.x, camera_pos.y);
+        glUniform2f(fgb->uniforms[UNIFORM_SLOT_RESOLUTION], (float) w, (float) h);
+        glUniform1f(fgb->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
+        glUniform2f(fgb->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
+        glUniform1f(fgb->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
 
         free_glyph_buffer_clear(fgb);
 
         {
             for (size_t row = 0; row < editor->size; ++row) {
                 const Line *line = editor->lines + row;
+
+                const Vec2f begin = vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE);
+                Vec2f end = begin;
                 free_glyph_buffer_render_line_sized(
                     fgb, line->chars, line->size,
-                    vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE),
+                    &end,
                     vec4fs(1.0f), vec4fs(0.0f));
+                // TODO: the max_line_len should be calculated based on what's visible on the screen right now
+                float line_len = fabsf(end.x - begin.x);
+                if (line_len > max_line_len) {
+                    max_line_len = line_len;
+                }
             }
         }
 
@@ -174,21 +128,33 @@ void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Cursor_R
 
     cursor_renderer_use(cr);
     {
-        glUniform2f(cr->resolution_uniform, (float) w, (float) h);
-        glUniform1f(cr->time_uniform, (float) SDL_GetTicks() / 1000.0f);
-        glUniform2f(cr->camera_uniform, camera_pos.x, camera_pos.y);
-        glUniform1f(cr->height_uniform, FREE_GLYPH_FONT_SIZE);
+        glUniform2f(cr->uniforms[UNIFORM_SLOT_RESOLUTION], (float) w, (float) h);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
+        glUniform2f(cr->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_CURSOR_HEIGHT], FREE_GLYPH_FONT_SIZE);
 
         cursor_renderer_move_to(cr, cursor_pos);
         cursor_renderer_draw();
     }
 
     {
+        float target_scale = 3.0f;
+        if (max_line_len > 0.0f) {
+            target_scale = SCREEN_WIDTH / max_line_len;
+        }
+
+        if (target_scale > 3.0f) {
+            target_scale = 3.0f;
+        }
+
         camera_vel = vec2f_mul(
                          vec2f_sub(cursor_pos, camera_pos),
                          vec2fs(2.0f));
+        camera_scale_vel = (target_scale - camera_scale) * 2.0f;
 
         camera_pos = vec2f_add(camera_pos, vec2f_mul(camera_vel, vec2fs(DELTA_TIME)));
+        camera_scale = camera_scale + camera_scale_vel * DELTA_TIME;
     }
 }
 
@@ -284,12 +250,7 @@ int main(int argc, char **argv)
         fprintf(stderr, "WARNING! GLEW_ARB_debug_output is not available");
     }
 
-#ifdef TILE_GLYPH_RENDER
-    tile_glyph_buffer_init(&tgb,
-                           "./charmap-oldschool_white.png",
-                           "./shaders/tile_glyph.vert",
-                           "./shaders/tile_glyph.frag");
-#else
+
     free_glyph_buffer_init(&fgb,
                            face,
                            "./shaders/free_glyph.vert",
@@ -297,7 +258,6 @@ int main(int argc, char **argv)
     cursor_renderer_init(&cr,
                          "./shaders/cursor.vert",
                          "./shaders/cursor.frag");
-#endif
 
     bool quit = false;
     while (!quit) {
@@ -314,10 +274,8 @@ int main(int argc, char **argv)
                 switch (event.key.keysym.sym) {
                 case SDLK_BACKSPACE: {
                     editor_backspace(&editor);
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                 }
                 break;
 
@@ -330,19 +288,15 @@ int main(int argc, char **argv)
 
                 case SDLK_RETURN: {
                     editor_insert_new_line(&editor);
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                 }
                 break;
 
                 case SDLK_DELETE: {
                     editor_delete(&editor);
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                 }
                 break;
 
@@ -350,39 +304,31 @@ int main(int argc, char **argv)
                     if (editor.cursor_row > 0) {
                         editor.cursor_row -= 1;
                     }
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                 }
                 break;
 
                 case SDLK_DOWN: {
                     editor.cursor_row += 1;
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                 }
                 break;
 
                 case SDLK_LEFT: {
                     if (editor.cursor_col > 0) {
                         editor.cursor_col -= 1;
-#ifndef TILE_GLYPH_RENDER
                         cursor_renderer_use(&cr);
-                        glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                        glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
                     }
                 }
                 break;
 
                 case SDLK_RIGHT: {
                     editor.cursor_col += 1;
-#ifndef TILE_GLYPH_RENDER
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
 
                 }
                 break;
@@ -392,10 +338,8 @@ int main(int argc, char **argv)
 
             case SDL_TEXTINPUT: {
                 editor_insert_text_before_cursor(&editor, event.text.text);
-#ifndef TILE_GLYPH_RENDER
                 cursor_renderer_use(&cr);
-                glUniform1f(cr.last_stroke_uniform, (float) SDL_GetTicks() / 1000.0f);
-#endif
+                glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
             }
             break;
             }
@@ -411,11 +355,7 @@ int main(int argc, char **argv)
         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
         glClear(GL_COLOR_BUFFER_BIT);
 
-#ifdef TILE_GLYPH_RENDER
-        render_editor_into_tgb(window, &tgb, &editor);
-#else
         render_editor_into_fgb(window, &fgb, &cr, &editor);
-#endif // TILE_GLYPH_RENDER
 
         SDL_GL_SwapWindow(window);
 

+ 0 - 177
src/tile_glyph.c

@@ -1,177 +0,0 @@
-#include <assert.h>
-#include <string.h>
-#include <stdbool.h>
-#include "./stb_image.h"
-#include "./tile_glyph.h"
-#include "./gl_extra.h"
-
-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");
-
-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);
-}

+ 0 - 66
src/tile_glyph.h

@@ -1,66 +0,0 @@
-#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;
-
-#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_buffer_draw(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);
-
-
-#endif // TILE_GLYPH_H_

+ 48 - 0
src/uniforms.c

@@ -0,0 +1,48 @@
+#include <assert.h>
+#include "./uniforms.h"
+
+static_assert(COUNT_UNIFORM_SLOTS == 7, "The amount of the shader uniforms have change. Please update the definition table accordingly");
+static const Uniform_Def uniform_defs[COUNT_UNIFORM_SLOTS] = {
+    [UNIFORM_SLOT_TIME] = {
+        .slot = UNIFORM_SLOT_TIME,
+        .name = "time",
+    },
+    [UNIFORM_SLOT_RESOLUTION] = {
+        .slot = UNIFORM_SLOT_RESOLUTION,
+        .name = "resolution",
+    },
+    [UNIFORM_SLOT_CAMERA_POS] = {
+        .slot = UNIFORM_SLOT_CAMERA_POS,
+        .name = "camera_pos",
+    },
+    [UNIFORM_SLOT_CAMERA_SCALE] = {
+        .slot = UNIFORM_SLOT_CAMERA_SCALE,
+        .name = "camera_scale",
+    },
+    [UNIFORM_SLOT_CURSOR_POS] = {
+        .slot = UNIFORM_SLOT_CURSOR_POS,
+        .name = "cursor_pos",
+    },
+    [UNIFORM_SLOT_CURSOR_HEIGHT] = {
+        .slot = UNIFORM_SLOT_CURSOR_HEIGHT,
+        .name = "cursor_height",
+    },
+    [UNIFORM_SLOT_LAST_STROKE] = {
+        .slot = UNIFORM_SLOT_LAST_STROKE,
+        .name = "last_stroke",
+    },
+};
+
+const Uniform_Def *get_uniform_def(Uniform_Slot slot)
+{
+    assert(0 <= slot);
+    assert(slot < COUNT_UNIFORM_SLOTS);
+    return &uniform_defs[slot];
+}
+
+void get_uniform_location(GLuint program, GLint locations[COUNT_UNIFORM_SLOTS])
+{
+    for (Uniform_Slot slot = 0; slot < COUNT_UNIFORM_SLOTS; ++slot) {
+        locations[slot] = glGetUniformLocation(program, uniform_defs[slot].name);
+    }
+}

+ 30 - 0
src/uniforms.h

@@ -0,0 +1,30 @@
+#ifndef UNIFORMS_H_
+#define UNIFORMS_H_
+
+#define GLEW_STATIC
+#include <GL/glew.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <SDL2/SDL_opengl.h>
+
+typedef enum {
+    UNIFORM_SLOT_TIME = 0,
+    UNIFORM_SLOT_RESOLUTION,
+    UNIFORM_SLOT_CAMERA_POS,
+    UNIFORM_SLOT_CAMERA_SCALE,
+
+    UNIFORM_SLOT_CURSOR_POS,
+    UNIFORM_SLOT_CURSOR_HEIGHT,
+    UNIFORM_SLOT_LAST_STROKE,
+    COUNT_UNIFORM_SLOTS,
+} Uniform_Slot;
+
+typedef struct {
+    Uniform_Slot slot;
+    const char *name;
+} Uniform_Def;
+
+const Uniform_Def *get_uniform_def(Uniform_Slot slot);
+void get_uniform_location(GLuint program, GLint locations[COUNT_UNIFORM_SLOTS]);
+
+#endif // UNIFORMS_H_