commit ca556aac646ed548f2e5134abed6b065f04f47cc
parent 74d8f392326f8a022f095c65f8600169062ab1d5
Author: rexim <reximkut@gmail.com>
Date: Sat, 10 Jul 2021 22:31:10 +0700
Introduce Free_Glyph renderer
Diffstat:
10 files changed, 274 insertions(+), 45 deletions(-)
diff --git a/README.md b/README.md
@@ -16,3 +16,7 @@ $ ./ded src\main.c
> .\build_msvc.bat
> .\ded.exe src\main.c
```
+
+# Font
+
+Victor Mono: https://rubjo.github.io/victor-mono/
diff --git a/VictorMono-Regular.ttf b/VictorMono-Regular.ttf
Binary files differ.
diff --git a/build.sh b/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/tile_glyph.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 src/free_glyph.c"
if [ `uname` = "Darwin" ]; then
CFLAGS+=" -framework OpenGL"
diff --git a/shaders/free_glyph.frag b/shaders/free_glyph.frag
@@ -0,0 +1,7 @@
+#version 330 core
+
+uniform sampler2D font;
+
+void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
diff --git a/shaders/free_glyph.vert b/shaders/free_glyph.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout(location = 0) in vec2 pos;
+layout(location = 1) in vec2 size;
+layout(location = 2) in int ch;
+layout(location = 3) in vec4 fg_color;
+layout(location = 4) in vec4 bg_color;
+
+out vec2 uv;
+
+void main() {
+ uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));
+ gl_Position = vec4(uv - vec2(0.5), 0.0, 1.0);
+}
diff --git a/src/free_glyph.c b/src/free_glyph.c
@@ -0,0 +1,133 @@
+#include <assert.h>
+#include <stdbool.h>
+#include "./free_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_FREE_GLYPH_ATTRS] = {
+ [FREE_GLYPH_ATTR_POS] = {
+ .offset = offsetof(Free_Glyph, pos),
+ .comps = 2,
+ .type = GL_FLOAT
+ },
+ [FREE_GLYPH_ATTR_SIZE] = {
+ .offset = offsetof(Free_Glyph, size),
+ .comps = 2,
+ .type = GL_FLOAT
+ },
+ [FREE_GLYPH_ATTR_CH] = {
+ .offset = offsetof(Free_Glyph, ch),
+ .comps = 1,
+ .type = GL_INT
+ },
+ [FREE_GLYPH_ATTR_FG_COLOR] = {
+ .offset = offsetof(Free_Glyph, fg_color),
+ .comps = 4,
+ .type = GL_FLOAT
+ },
+ [FREE_GLYPH_ATTR_BG_COLOR] = {
+ .offset = offsetof(Free_Glyph, bg_color),
+ .comps = 4,
+ .type = GL_FLOAT
+ },
+};
+static_assert(COUNT_FREE_GLYPH_ATTRS == 5, "The amount of glyph vertex attributes have changed");
+
+
+void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
+ const char *vert_file_path,
+ const char *frag_file_path)
+{
+ // Init Vertex Attributes
+ {
+ glGenVertexArrays(1, &fgb->vao);
+ glBindVertexArray(fgb->vao);
+
+ glGenBuffers(1, &fgb->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, fgb->vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(fgb->glyphs), fgb->glyphs, GL_DYNAMIC_DRAW);
+
+ for (Free_Glyph_Attr attr = 0; attr < COUNT_FREE_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(Free_Glyph),
+ (void*) glyph_attr_defs[attr].offset);
+ break;
+
+ case GL_INT:
+ glVertexAttribIPointer(
+ attr,
+ glyph_attr_defs[attr].comps,
+ glyph_attr_defs[attr].type,
+ sizeof(Free_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);
+
+ fgb->time_uniform = glGetUniformLocation(program, "time");
+ fgb->resolution_uniform = glGetUniformLocation(program, "resolution");
+ fgb->camera_uniform = glGetUniformLocation(program, "camera");
+ }
+
+}
+
+void free_glyph_buffer_clear(Free_Glyph_Buffer *fgb)
+{
+ (void) fgb;
+ assert(0);
+}
+
+void free_glyph_buffer_push(Free_Glyph_Buffer *fgb, Free_Glyph glyph)
+{
+ (void) fgb;
+ (void) glyph;
+ assert(0);
+}
+
+void free_glyph_buffer_sync(Free_Glyph_Buffer *fgb)
+{
+ (void) fgb;
+ assert(0);
+}
+
+void free_glyph_buffer_draw(Free_Glyph_Buffer *fgb)
+{
+ (void) fgb;
+ assert(0);
+}
diff --git a/src/free_glyph.h b/src/free_glyph.h
@@ -0,0 +1,53 @@
+#ifndef FREE_GLYPH_H_
+#define FREE_GLYPH_H_
+
+#include <stdlib.h>
+#include "./la.h"
+
+#define GLEW_STATIC
+#include <GL/glew.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <SDL2/SDL_opengl.h>
+
+typedef struct {
+ Vec2f pos;
+ Vec2f size;
+ int ch;
+ Vec4f fg_color;
+ Vec4f bg_color;
+} Free_Glyph;
+
+typedef enum {
+ FREE_GLYPH_ATTR_POS = 0,
+ FREE_GLYPH_ATTR_SIZE,
+ FREE_GLYPH_ATTR_CH,
+ FREE_GLYPH_ATTR_FG_COLOR,
+ FREE_GLYPH_ATTR_BG_COLOR,
+ COUNT_FREE_GLYPH_ATTRS,
+} Free_Glyph_Attr;
+
+#define FREE_GLYPH_BUFFER_CAP (640 * 1000)
+
+typedef struct {
+ GLuint vao;
+ GLuint vbo;
+
+ GLint time_uniform;
+ GLint resolution_uniform;
+ GLint camera_uniform;
+
+ size_t glyphs_count;
+ Free_Glyph glyphs[FREE_GLYPH_BUFFER_CAP];
+} Free_Glyph_Buffer;
+
+void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
+ const char *vert_file_path,
+ const char *frag_file_path);
+void free_glyph_buffer_clear(Free_Glyph_Buffer *fgb);
+void free_glyph_buffer_push(Free_Glyph_Buffer *fgb, Free_Glyph glyph);
+void free_glyph_buffer_sync(Free_Glyph_Buffer *fgb);
+void free_glyph_buffer_draw(Free_Glyph_Buffer *fgb);
+
+
+#endif // FREE_GLYPH_H_
diff --git a/src/main.c b/src/main.c
@@ -19,6 +19,7 @@
#include "./sdl_extra.h"
#include "./gl_extra.h"
#include "./tile_glyph.h"
+#include "./free_glyph.h"
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
@@ -68,6 +69,50 @@ void gl_render_cursor(Tile_Glyph_Buffer *tgb)
}
static Tile_Glyph_Buffer tgb = {0};
+static Free_Glyph_Buffer fgb = {0};
+
+void render_editor_into_tgb(SDL_Window *window, Tile_Glyph_Buffer *tgb, Editor *editor)
+{
+ {
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+ // TODO(#19): update the viewport and the resolution only on actual window change
+ glViewport(0, 0, 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);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ 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);
+}
+
+void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *tgb, Editor *editor)
+{
+ (void) window;
+ (void) tgb;
+ (void) editor;
+}
// OPENGL
int main(int argc, char **argv)
@@ -133,10 +178,14 @@ int main(int argc, char **argv)
fprintf(stderr, "WARNING! GLEW_ARB_debug_output is not available");
}
- tile_glyph_buffer_init(&tgb,
- "./charmap-oldschool_white.png",
- "./shaders/tile_glyph.vert",
- "./shaders/tile_glyph.frag");
+ // tile_glyph_buffer_init(&tgb,
+ // "./charmap-oldschool_white.png",
+ // "./shaders/tile_glyph.vert",
+ // "./shaders/tile_glyph.frag");
+
+ free_glyph_buffer_init(&fgb,
+ "./shaders/free_glyph.vert",
+ "./shaders/free_glyph.frag");
bool quit = false;
while (!quit) {
@@ -237,38 +286,8 @@ int main(int argc, char **argv)
camera_pos = vec2f_add(camera_pos, vec2f_mul(camera_vel, vec2fs(DELTA_TIME)));
}
- {
- int w, h;
- SDL_GetWindowSize(window, &w, &h);
- // TODO(#19): update the viewport and the resolution only on actual window change
- glViewport(0, 0, 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);
-
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- 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);
+ // render_editor_into_tgb(window, &tgb, &editor);
+ render_editor_into_fgb(window, &fgb, &editor);
SDL_GL_SwapWindow(window);
diff --git a/src/tile_glyph.c b/src/tile_glyph.c
@@ -5,6 +5,12 @@
#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),
diff --git a/src/tile_glyph.h b/src/tile_glyph.h
@@ -33,12 +33,6 @@ typedef enum {
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 {
@@ -60,14 +54,13 @@ 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);
-void tile_glyph_buffer_draw(Tile_Glyph_Buffer *buffer);
#endif // TILE_GLYPH_H_