commit 4c4238177a13fbf28c16c322e6f10fd3b839c735
parent ff269718ccf571ef6c08a5f3f55e13bf946a23b1
Author: rexim <reximkut@gmail.com>
Date: Tue, 3 Jan 2023 23:09:30 +0700
Implement Simple_Renderer and replace Cursor_Renderer with it
Diffstat:
10 files changed, 264 insertions(+), 147 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/free_glyph.c src/cursor_renderer.c src/uniforms.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/uniforms.c src/simple_renderer.c"
if [ `uname` = "Darwin" ]; then
CFLAGS+=" -framework OpenGL"
diff --git a/shaders/cursor.frag b/shaders/cursor.frag
@@ -1,14 +0,0 @@
-#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);
-}
diff --git a/shaders/cursor.vert b/shaders/cursor.vert
@@ -1,20 +0,0 @@
-#version 330 core
-
-uniform vec2 resolution;
-uniform vec2 cursor_pos;
-uniform float cursor_height;
-
-#define WIDTH 5.0
-
-out vec2 uv;
-
-vec2 camera_project(vec2 point);
-
-void main() {
- uv = vec2(float(gl_VertexID & 1),
- float((gl_VertexID >> 1) & 1));
- gl_Position = vec4(
- camera_project(uv * vec2(WIDTH, cursor_height) + cursor_pos),
- 0.0,
- 1.0);
-}
diff --git a/shaders/simple.frag b/shaders/simple.frag
@@ -0,0 +1,7 @@
+#version 330 core
+
+in vec4 out_color;
+
+void main() {
+ gl_FragColor = out_color;
+}
diff --git a/shaders/simple.vert b/shaders/simple.vert
@@ -0,0 +1,22 @@
+#version 330 core
+
+uniform vec2 resolution;
+uniform float time;
+uniform float camera_scale;
+uniform vec2 camera_pos;
+
+layout(location = 0) in vec2 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 uv;
+
+out vec4 out_color;
+
+vec2 camera_project(vec2 point)
+{
+ return 2.0 * (point - camera_pos) * camera_scale / resolution;
+}
+
+void main() {
+ gl_Position = vec4(camera_project(position), 0, 1);
+ out_color = color;
+}
diff --git a/src/cursor_renderer.c b/src/cursor_renderer.c
@@ -1,47 +0,0 @@
-#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 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);
- }
- if (!compile_shader_file("./shaders/camera.vert", GL_VERTEX_SHADER, &shaders[2])) {
- exit(1);
- }
-
- 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);
- get_uniform_location(cr->program, cr->uniforms);
- }
-}
-
-void cursor_renderer_use(const Cursor_Renderer *cr)
-{
- glUseProgram(cr->program);
-}
-
-void cursor_renderer_move_to(const Cursor_Renderer *cr, Vec2f pos)
-{
- glUniform2f(cr->uniforms[UNIFORM_SLOT_CURSOR_POS], pos.x, pos.y);
-}
-
-void cursor_renderer_draw()
-{
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-}
diff --git a/src/cursor_renderer.h b/src/cursor_renderer.h
@@ -1,27 +0,0 @@
-#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"
-#include "./uniforms.h"
-
-typedef struct {
- GLuint program;
-
- GLint uniforms[COUNT_UNIFORM_SLOTS];
-} 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_
diff --git a/src/main.c b/src/main.c
@@ -25,7 +25,7 @@
#include "./sdl_extra.h"
#include "./gl_extra.h"
#include "./free_glyph.h"
-#include "./cursor_renderer.h"
+#include "./simple_renderer.h"
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
@@ -33,6 +33,7 @@
#define DELTA_TIME (1.0f / FPS)
Editor editor = {0};
+Uint32 last_stroke = 0;
Vec2f camera_pos = {0};
float camera_scale = 3.0f;
float camera_scale_vel = 0.0f;
@@ -72,12 +73,12 @@ void MessageCallback(GLenum source,
}
static Free_Glyph_Buffer fgb = {0};
-static Cursor_Renderer cr = {0};
+static Simple_Renderer sr = {0};
#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)
+void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Simple_Renderer *sr, Editor *editor)
{
int w, h;
SDL_GetWindowSize(window, &w, &h);
@@ -122,23 +123,33 @@ void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Cursor_R
size_t cursor_col = editor->cursor - line.begin;
cursor_pos.y = -(float) cursor_row * FREE_GLYPH_FONT_SIZE;
cursor_pos.x = free_glyph_buffer_cursor_pos(
- fgb,
- editor->data.items + line.begin, line.end - line.begin,
- vec2f(0.0, cursor_pos.y),
- cursor_col
- );
+ fgb,
+ editor->data.items + line.begin, line.end - line.begin,
+ vec2f(0.0, cursor_pos.y),
+ cursor_col
+ );
}
- cursor_renderer_use(cr);
+ simple_renderer_use(sr);
{
- 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();
+ glUniform2f(sr->uniforms[UNIFORM_SLOT_RESOLUTION], (float) w, (float) h);
+ glUniform1f(sr->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
+ glUniform2f(sr->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
+ glUniform1f(sr->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
+
+ sr->verticies_count = 0;
+ float CURSOR_WIDTH = 5.0f;
+ Uint32 CURSOR_BLINK_THRESHOLD = 500;
+ Uint32 CURSOR_BLINK_PERIOD = 1000;
+ Uint32 t = SDL_GetTicks() - last_stroke;
+ if (t < CURSOR_BLINK_THRESHOLD || t/CURSOR_BLINK_PERIOD%2 != 0) {
+ simple_renderer_solid_rect(
+ sr,
+ cursor_pos, vec2f(CURSOR_WIDTH, FREE_GLYPH_FONT_SIZE),
+ vec4fs(1));
+ }
+ simple_renderer_sync(sr);
+ simple_renderer_draw(sr);
}
{
@@ -260,9 +271,10 @@ 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");
+
+ simple_renderer_init(&sr,
+ "./shaders/simple.vert",
+ "./shaders/simple.frag");
bool quit = false;
while (!quit) {
@@ -279,8 +291,7 @@ int main(int argc, char **argv)
switch (event.key.keysym.sym) {
case SDLK_BACKSPACE: {
editor_backspace(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
@@ -293,44 +304,37 @@ int main(int argc, char **argv)
case SDLK_RETURN: {
editor_insert_char(&editor, '\n');
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
case SDLK_DELETE: {
editor_delete(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
case SDLK_UP: {
editor_move_line_up(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
case SDLK_DOWN: {
editor_move_line_down(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
case SDLK_LEFT: {
editor_move_char_left(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
case SDLK_RIGHT: {
editor_move_char_right(&editor);
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-
+ last_stroke = SDL_GetTicks();
}
break;
}
@@ -343,8 +347,7 @@ int main(int argc, char **argv)
for (size_t i = 0; i < text_len; ++i) {
editor_insert_char(&editor, text[i]);
}
- cursor_renderer_use(&cr);
- glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+ last_stroke = SDL_GetTicks();
}
break;
}
@@ -360,7 +363,7 @@ int main(int argc, char **argv)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
- render_editor_into_fgb(window, &fgb, &cr, &editor);
+ render_editor_into_fgb(window, &fgb, &sr, &editor);
SDL_GL_SwapWindow(window);
diff --git a/src/simple_renderer.c b/src/simple_renderer.c
@@ -0,0 +1,137 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "./simple_renderer.h"
+#include "./gl_extra.h"
+
+#define UNIMPLEMENTED(...) \
+ do { \
+ printf("%s:%d: UNIMPLEMENTED: %s \n", __FILE__, __LINE__, __VA_ARGS__); \
+ exit(1); \
+ } while(0)
+#define UNUSED(x) (void)(x)
+
+void simple_renderer_init(Simple_Renderer *sr,
+ const char *vert_file_path,
+ const char *frag_file_path)
+{
+ {
+ glGenVertexArrays(1, &sr->vao);
+ glBindVertexArray(sr->vao);
+
+ glGenBuffers(1, &sr->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, sr->vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(sr->verticies), sr->verticies, GL_DYNAMIC_DRAW);
+
+ // position
+ glEnableVertexAttribArray(SIMPLE_VERTEX_ATTR_POSITION);
+ glVertexAttribPointer(
+ SIMPLE_VERTEX_ATTR_POSITION,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Simple_Vertex),
+ (GLvoid *) offsetof(Simple_Vertex, position));
+
+ // color
+ glEnableVertexAttribArray(SIMPLE_VERTEX_ATTR_COLOR);
+ glVertexAttribPointer(
+ SIMPLE_VERTEX_ATTR_COLOR,
+ 4,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Simple_Vertex),
+ (GLvoid *) offsetof(Simple_Vertex, color));
+
+ // uv
+ glEnableVertexAttribArray(SIMPLE_VERTEX_ATTR_UV);
+ glVertexAttribPointer(
+ SIMPLE_VERTEX_ATTR_UV,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Simple_Vertex),
+ (GLvoid *) offsetof(Simple_Vertex, uv));
+ }
+
+ GLuint shaders[2] = {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);
+ }
+
+ sr->program = glCreateProgram();
+ attach_shaders_to_program(shaders, sizeof(shaders) / sizeof(shaders[0]), sr->program);
+ if (!link_program(sr->program, __FILE__, __LINE__)) {
+ exit(1);
+ }
+
+ glUseProgram(sr->program);
+
+ get_uniform_location(sr->program, sr->uniforms);
+}
+
+void simple_renderer_use(const Simple_Renderer *sr)
+{
+ glBindVertexArray(sr->vao);
+ glBindBuffer(GL_ARRAY_BUFFER, sr->vbo);
+ glUseProgram(sr->program);
+}
+
+void simple_renderer_vertex(Simple_Renderer *sr,
+ Vec2f p, Vec4f c, Vec2f uv)
+{
+ assert(sr->verticies_count < SIMPLE_VERTICIES_CAP);
+ Simple_Vertex *last = &sr->verticies[sr->verticies_count];
+ last->position = p;
+ last->color = c;
+ last->uv = uv;
+ sr->verticies_count += 1;
+}
+
+void simple_renderer_triangle(Simple_Renderer *sr,
+ Vec2f p0, Vec2f p1, Vec2f p2,
+ Vec4f c0, Vec4f c1, Vec4f c2,
+ Vec2f uv0, Vec2f uv1, Vec2f uv2)
+{
+ simple_renderer_vertex(sr, p0, c0, uv0);
+ simple_renderer_vertex(sr, p1, c1, uv1);
+ simple_renderer_vertex(sr, p2, c2, uv2);
+}
+
+// 2-3
+// |\|
+// 0-1
+void simple_renderer_quad(Simple_Renderer *sr,
+ Vec2f p0, Vec2f p1, Vec2f p2, Vec2f p3,
+ Vec4f c0, Vec4f c1, Vec4f c2, Vec4f c3,
+ Vec2f uv0, Vec2f uv1, Vec2f uv2, Vec2f uv3)
+{
+ simple_renderer_triangle(sr, p0, p1, p2, c0, c1, c2, uv0, uv1, uv2);
+ simple_renderer_triangle(sr, p1, p2, p3, c1, c2, c3, uv1, uv2, uv3);
+}
+
+void simple_renderer_solid_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec4f c)
+{
+ Vec2f uv = vec2fs(0);
+ simple_renderer_quad(
+ sr,
+ p, vec2f_add(p, vec2f(s.x, 0)), vec2f_add(p, vec2f(0, s.y)), vec2f_add(p, s),
+ c, c, c, c,
+ uv, uv, uv, uv);
+}
+
+void simple_renderer_sync(Simple_Renderer *sr)
+{
+ glBufferSubData(GL_ARRAY_BUFFER,
+ 0,
+ sr->verticies_count * sizeof(Simple_Vertex),
+ sr->verticies);
+}
+
+void simple_renderer_draw(Simple_Renderer *sr)
+{
+ glDrawArrays(GL_TRIANGLES, 0, sr->verticies_count);
+}
diff --git a/src/simple_renderer.h b/src/simple_renderer.h
@@ -0,0 +1,56 @@
+#ifndef SIMPLE_RENDERER_H_
+#define SIMPLE_RENDERER_H_
+
+#define GLEW_STATIC
+#include <GL/glew.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <SDL2/SDL_opengl.h>
+
+#include "./la.h"
+#include "./uniforms.h"
+
+typedef enum {
+ SIMPLE_VERTEX_ATTR_POSITION = 0,
+ SIMPLE_VERTEX_ATTR_COLOR,
+ SIMPLE_VERTEX_ATTR_UV,
+} Simple_Vertex_Attr;
+
+typedef struct {
+ Vec2f position;
+ Vec4f color;
+ Vec2f uv;
+} Simple_Vertex;
+
+#define SIMPLE_VERTICIES_CAP (3*640*1000)
+
+typedef struct {
+ GLuint vao;
+ GLuint vbo;
+ GLuint program;
+
+ GLint uniforms[COUNT_UNIFORM_SLOTS];
+ Simple_Vertex verticies[SIMPLE_VERTICIES_CAP];
+ size_t verticies_count;
+} Simple_Renderer;
+
+void simple_renderer_init(Simple_Renderer *sr,
+ const char *vert_file_path,
+ const char *frag_file_path);
+
+void simple_renderer_use(const Simple_Renderer *sr);
+void simple_renderer_vertex(Simple_Renderer *sr,
+ Vec2f p, Vec4f c, Vec2f uv);
+void simple_renderer_triangle(Simple_Renderer *sr,
+ Vec2f p0, Vec2f p1, Vec2f p2,
+ Vec4f c0, Vec4f c1, Vec4f c2,
+ Vec2f uv0, Vec2f uv1, Vec2f uv2);
+void simple_renderer_quad(Simple_Renderer *sr,
+ Vec2f p0, Vec2f p1, Vec2f p2, Vec2f p3,
+ Vec4f c0, Vec4f c1, Vec4f c2, Vec4f c3,
+ Vec2f uv0, Vec2f uv1, Vec2f uv2, Vec2f uv3);
+void simple_renderer_solid_rect(Simple_Renderer *sr, Vec2f p, Vec2f s, Vec4f c);
+void simple_renderer_sync(Simple_Renderer *sr);
+void simple_renderer_draw(Simple_Renderer *sr);
+
+#endif // SIMPLE_RENDERER_H_