Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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