commit c7fb61a9e5c1d0bbc781946ebcf6416f85509aac
parent 12191cfcd0c778b1b07e88ded4850100eb0ed6b3
Author: Alexey Kutepov <reximkut@gmail.com>
Date: Mon, 19 Jul 2021 00:05:28 +0700
Merge pull request #33 from tsoding/zoom
Zoom
Diffstat:
20 files changed, 194 insertions(+), 507 deletions(-)
diff --git a/build.sh b/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"
diff --git a/charmap-oldschool_white.png b/charmap-oldschool_white.png
Binary files differ.
diff --git a/shaders/camera.vert b/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;
+}
diff --git a/shaders/cursor.vert b/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);
}
diff --git a/shaders/free_glyph.vert b/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));
diff --git a/shaders/tile_glyph.frag b/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;
-}
diff --git a/shaders/tile_glyph.vert b/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;
-}
diff --git a/src/cursor_renderer.c b/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()
diff --git a/src/cursor_renderer.h b/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,
diff --git a/src/free_glyph.c b/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);
-}
diff --git a/src/free_glyph.h b/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_
diff --git a/src/gl_extra.c b/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;
}
diff --git a/src/gl_extra.h b/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_
diff --git a/src/la.c b/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;
+}
diff --git a/src/la.h b/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_
diff --git a/src/main.c b/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);
diff --git a/src/tile_glyph.c b/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);
-}
diff --git a/src/tile_glyph.h b/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_
diff --git a/src/uniforms.c b/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);
+ }
+}
diff --git a/src/uniforms.h b/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_