ded

Dramatic EDitor
Index Commits Files Refs README LICENSE
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:
Mbuild.sh | 2+-
Dshaders/cursor.frag | 14--------------
Dshaders/cursor.vert | 20--------------------
Ashaders/simple.frag | 7+++++++
Ashaders/simple.vert | 22++++++++++++++++++++++
Dsrc/cursor_renderer.c | 47-----------------------------------------------
Dsrc/cursor_renderer.h | 27---------------------------
Msrc/main.c | 79+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Asrc/simple_renderer.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/simple_renderer.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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_