Skip to content

Commit

Permalink
(tsoding#27) Add cursor rendering to Free_Glyph
Browse files Browse the repository at this point in the history
  • Loading branch information
rexim committed Jul 11, 2021
1 parent 6f5335c commit a68d1ad
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 24 deletions.
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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="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"

if [ `uname` = "Darwin" ]; then
CFLAGS+=" -framework OpenGL"
Expand Down
14 changes: 14 additions & 0 deletions shaders/cursor.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 330 core

#define PERIOD 1.0
#define BLINK_THRESHOLD 0.5

uniform float time;
uniform float last_stroke;

void main() {
float t = time - last_stroke;
float threshold = float(t < BLINK_THRESHOLD);
float blink = mod(floor(t / PERIOD), 2);
gl_FragColor = vec4(1.0) * min(threshold + blink, 1.0);
}
23 changes: 23 additions & 0 deletions shaders/cursor.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#version 330 core

uniform vec2 resolution;
uniform vec2 camera;
uniform vec2 pos;
uniform float height;

#define WIDTH 5.0

out vec2 uv;

vec2 project_point(vec2 point)
{
return 2.0 * (point - camera) / resolution;
}

void main() {
uv = vec2(float(gl_VertexID & 1), float((gl_VertexID >> 1) & 1));
gl_Position = vec4(
project_point(uv * vec2(WIDTH, height) + pos),
0.0,
1.0);
}
48 changes: 48 additions & 0 deletions src/cursor_renderer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <stdlib.h>
#include "./gl_extra.h"
#include "./cursor_renderer.h"

void cursor_renderer_init(Cursor_Renderer *cr,
const char *vert_file_path,
const char *frag_file_path)
{
// 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);
}

if (!link_program(vert_shader, frag_shader, &cr->program)) {
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");
}
}

void cursor_renderer_use(const Cursor_Renderer *cr)
{
glUseProgram(cr->program);
}

void cursor_renderer_move_to(const Cursor_Renderer *cr, Vec2f pos)
{
glUniform2f(cr->pos_uniform, pos.x, pos.y);
}

void cursor_renderer_draw()
{
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
31 changes: 31 additions & 0 deletions src/cursor_renderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef CURSOR_RENDERER_H_
#define CURSOR_RENDERER_H_

#define GLEW_STATIC
#include <GL/glew.h>

#define GL_GLEXT_PROTOTYPES
#include <SDL2/SDL_opengl.h>

#include "./la.h"

typedef struct {
GLuint program;

GLint time_uniform;
GLint resolution_uniform;
GLint camera_uniform;
GLint pos_uniform;
GLint height_uniform;
GLint last_stroke_uniform;
} Cursor_Renderer;

void cursor_renderer_init(Cursor_Renderer *cr,
const char *vert_file_path,
const char *frag_file_path);

void cursor_renderer_use(const Cursor_Renderer *cr);
void cursor_renderer_move_to(const Cursor_Renderer *cr, Vec2f pos);
void cursor_renderer_draw(void);

#endif // CURSOR_RENDERER_H_
33 changes: 27 additions & 6 deletions src/free_glyph.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,15 @@ void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
exit(1);
}

GLuint program = 0;
if (!link_program(vert_shader, frag_shader, &program)) {
if (!link_program(vert_shader, frag_shader, &fgb->program)) {
exit(1);
}

glUseProgram(program);
glUseProgram(fgb->program);

fgb->time_uniform = glGetUniformLocation(program, "time");
fgb->resolution_uniform = glGetUniformLocation(program, "resolution");
fgb->camera_uniform = glGetUniformLocation(program, "camera");
fgb->time_uniform = glGetUniformLocation(fgb->program, "time");
fgb->resolution_uniform = glGetUniformLocation(fgb->program, "resolution");
fgb->camera_uniform = glGetUniformLocation(fgb->program, "camera");
}

// Glyph Texture Atlas
Expand Down Expand Up @@ -185,6 +184,13 @@ void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
}
}

void free_glyph_buffer_use(const Free_Glyph_Buffer *fgb)
{
glBindVertexArray(fgb->vao);
glBindBuffer(GL_ARRAY_BUFFER, fgb->vbo);
glUseProgram(fgb->program);
}

void free_glyph_buffer_clear(Free_Glyph_Buffer *fgb)
{
fgb->glyphs_count = 0;
Expand All @@ -209,6 +215,21 @@ void free_glyph_buffer_draw(Free_Glyph_Buffer *fgb)
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, (GLsizei) fgb->glyphs_count);
}

float free_glyph_buffer_cursor_pos(const Free_Glyph_Buffer *fgb, const char *text, size_t text_size, Vec2f pos, size_t col)
{
for (size_t i = 0; i < text_size; ++i) {
if (i == col) {
return pos.x;
}

Glyph_Metric metric = fgb->metrics[(int) text[i]];
pos.x += metric.ax;
pos.y += metric.ay;
}

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)
{
for (size_t i = 0; i < text_size; ++i) {
Expand Down
4 changes: 4 additions & 0 deletions src/free_glyph.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ typedef struct {
typedef struct {
GLuint vao;
GLuint vbo;
GLuint program;

FT_UInt atlas_width;
FT_UInt atlas_height;
Expand All @@ -72,11 +73,14 @@ void free_glyph_buffer_init(Free_Glyph_Buffer *fgb,
FT_Face face,
const char *vert_file_path,
const char *frag_file_path);
void free_glyph_buffer_use(const Free_Glyph_Buffer *fgb);
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);

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);

Expand Down
92 changes: 75 additions & 17 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "./gl_extra.h"
#include "./tile_glyph.h"
#include "./free_glyph.h"
#include "./cursor_renderer.h"

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
Expand Down Expand Up @@ -80,6 +81,7 @@ void gl_render_cursor(Tile_Glyph_Buffer *tgb)
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)
Expand Down Expand Up @@ -119,31 +121,51 @@ void render_editor_into_tgb(SDL_Window *window, Tile_Glyph_Buffer *tgb, Editor *
// TODO(#27): Free_Glyph renderer does not support cursor
// TODO(#28): Camera location is broken in Free_Glyph Renderer

void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Editor *editor)
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);

free_glyph_buffer_use(fgb);
{
int w, h;
SDL_GetWindowSize(window, &w, &h);
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);

free_glyph_buffer_clear(fgb);

glUniform1f(fgb->time_uniform, (float) SDL_GetTicks() / 1000.0f);
glUniform2f(fgb->camera_uniform, camera_pos.x, camera_pos.y);
{
for (size_t row = 0; row < editor->size; ++row) {
const Line *line = editor->lines + row;
free_glyph_buffer_render_line_sized(
fgb, line->chars, line->size,
vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE),
vec4fs(1.0f), vec4fs(0.0f));
}
}

free_glyph_buffer_clear(fgb);
free_glyph_buffer_sync(fgb);
free_glyph_buffer_draw(fgb);
}

cursor_renderer_use(cr);
{
for (size_t row = 0; row < editor->size; ++row) {
const Line *line = editor->lines + row;
free_glyph_buffer_render_line_sized(
fgb, line->chars, line->size,
vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE),
vec4fs(1.0f), vec4fs(0.0f));
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);

float y = -(float) editor->cursor_row * FREE_GLYPH_FONT_SIZE;

float x = 0.0f;
if (editor->cursor_row < editor->size) {
Line *line = &editor->lines[editor->cursor_row];
x = free_glyph_buffer_cursor_pos(fgb, line->chars, line->size, vec2f(0.0, y), editor->cursor_col);
}
}

free_glyph_buffer_sync(fgb);
free_glyph_buffer_draw(fgb);
cursor_renderer_move_to(cr, vec2f(x, y));
cursor_renderer_draw();
}
}

int main(int argc, char **argv)
Expand Down Expand Up @@ -246,6 +268,9 @@ int main(int argc, char **argv)
face,
"./shaders/free_glyph.vert",
"./shaders/free_glyph.frag");
cursor_renderer_init(&cr,
"./shaders/cursor.vert",
"./shaders/cursor.frag");
#endif

bool quit = false;
Expand All @@ -263,6 +288,10 @@ 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
}
break;

Expand All @@ -275,35 +304,60 @@ 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
}
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
}
break;

case SDLK_UP: {
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
}
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
}
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
}
}
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

}
break;
}
Expand All @@ -312,6 +366,10 @@ 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
}
break;

Expand Down Expand Up @@ -360,7 +418,7 @@ int main(int argc, char **argv)
#ifdef TILE_GLYPH_RENDER
render_editor_into_tgb(window, &tgb, &editor);
#else
render_editor_into_fgb(window, &fgb, &editor);
render_editor_into_fgb(window, &fgb, &cr, &editor);
#endif // TILE_GLYPH_RENDER

SDL_GL_SwapWindow(window);
Expand Down

0 comments on commit a68d1ad

Please sign in to comment.