Browse Source

Implement 3 stages of rendering with ripple effect

rexim 3 years ago
parent
commit
dbc782b343
5 changed files with 156 additions and 18 deletions
  1. 98 18
      main.c
  2. 7 0
      render.conf
  3. 5 0
      shaders/flash.frag
  4. 21 0
      shaders/ripple.frag
  5. 25 0
      shaders/ripple.vert

+ 98 - 18
main.c

@@ -149,14 +149,16 @@ typedef enum {
     RESOLUTION_UNIFORM = 0,
     RESOLUTION_UNIFORM = 0,
     TIME_UNIFORM,
     TIME_UNIFORM,
     MOUSE_UNIFORM,
     MOUSE_UNIFORM,
+    TEX_UNIFORM,
     COUNT_UNIFORMS
     COUNT_UNIFORMS
 } Uniform;
 } Uniform;
 
 
-static_assert(COUNT_UNIFORMS == 3, "Update list of uniform names");
+static_assert(COUNT_UNIFORMS == 4, "Update list of uniform names");
 static const char *uniform_names[COUNT_UNIFORMS] = {
 static const char *uniform_names[COUNT_UNIFORMS] = {
     [RESOLUTION_UNIFORM] = "resolution",
     [RESOLUTION_UNIFORM] = "resolution",
     [TIME_UNIFORM] = "time",
     [TIME_UNIFORM] = "time",
     [MOUSE_UNIFORM] = "mouse",
     [MOUSE_UNIFORM] = "mouse",
+    [TEX_UNIFORM] = "tex",
 };
 };
 
 
 typedef enum {
 typedef enum {
@@ -188,6 +190,7 @@ typedef struct {
 static double time = 0.0;
 static double time = 0.0;
 static bool pause = false;
 static bool pause = false;
 static Renderer global_renderer = {0};
 static Renderer global_renderer = {0};
+static Renderer ripple_renderer = {0};
 
 
 void r_vertex(Renderer *r, V2f pos, V2f uv, V4f color)
 void r_vertex(Renderer *r, V2f pos, V2f uv, V4f color)
 {
 {
@@ -230,12 +233,14 @@ void r_sync_buffers(Renderer *r)
 void r_sync_uniforms(Renderer *r,
 void r_sync_uniforms(Renderer *r,
                      GLfloat resolution_width, GLfloat resolution_height,
                      GLfloat resolution_width, GLfloat resolution_height,
                      GLfloat time,
                      GLfloat time,
-                     GLfloat mouse_x, GLfloat mouse_y)
+                     GLfloat mouse_x, GLfloat mouse_y,
+                     GLint tex_unit)
 {
 {
-    static_assert(COUNT_UNIFORMS == 3, "Exhaustive uniform handling in ");
+    static_assert(COUNT_UNIFORMS == 4, "Exhaustive uniform handling in ");
     glUniform2f(r->uniforms[RESOLUTION_UNIFORM], resolution_width, resolution_height);
     glUniform2f(r->uniforms[RESOLUTION_UNIFORM], resolution_width, resolution_height);
     glUniform1f(r->uniforms[TIME_UNIFORM], time);
     glUniform1f(r->uniforms[TIME_UNIFORM], time);
     glUniform2f(r->uniforms[MOUSE_UNIFORM], mouse_x, mouse_y);
     glUniform2f(r->uniforms[MOUSE_UNIFORM], mouse_x, mouse_y);
+    glUniform1i(r->uniforms[TEX_UNIFORM], tex_unit);
 }
 }
 
 
 bool load_shader_program(const char *vertex_file_path,
 bool load_shader_program(const char *vertex_file_path,
@@ -260,9 +265,42 @@ bool load_shader_program(const char *vertex_file_path,
 }
 }
 
 
 static char *render_conf = NULL;
 static char *render_conf = NULL;
-const char *vert_path = NULL;
-const char *frag_path = NULL;
-const char *texture_path = NULL;
+
+typedef struct {
+    float x, y, dx, dy;
+} Object;
+
+#define OBJECTS_CAP 1024
+Object objects[OBJECTS_CAP];
+size_t objects_count = 0;
+
+static const char *vert_path = NULL;
+static const char *frag_path = NULL;
+static const char *texture_path = NULL;
+static float follow_scale = 1.0f;
+static float object_size = 100.0f;
+static float rotate_radius = 500.0f;
+static float rotate_speed = 4.0f;
+
+void object_render(Renderer *r, Object *object)
+{
+    r_quad_cr(
+        r,
+        v2f(object->x, object->y),
+        v2ff(object_size),
+        COLOR_BLACK_V4F);
+}
+
+void object_update(Object *obj, float delta_time,
+                   float target_x, float target_y)
+{
+    if (!pause) {
+        obj->x += delta_time * obj->dx;
+        obj->y += delta_time * obj->dy;
+        obj->dx = (target_x - obj->x) * follow_scale;
+        obj->dy = (target_y - obj->y) * follow_scale;
+    }
+}
 
 
 void reload_render_conf(const char *render_conf_path)
 void reload_render_conf(const char *render_conf_path)
 {
 {
@@ -315,6 +353,21 @@ void reload_render_conf(const char *render_conf_path)
             } else if (sv_eq(key, SV("texture"))) {
             } else if (sv_eq(key, SV("texture"))) {
                 texture_path = value.data;
                 texture_path = value.data;
                 printf("Texture Path: %s\n", texture_path);
                 printf("Texture Path: %s\n", texture_path);
+            } else if (sv_eq(key, SV("follow_scale"))) {
+                follow_scale = strtof(value.data, NULL);
+            } else if (sv_eq(key, SV("object_size"))) {
+                object_size = strtof(value.data, NULL);
+            } else if (sv_eq(key, SV("rotate_radius"))) {
+                rotate_radius = strtof(value.data, NULL);
+            } else if (sv_eq(key, SV("rotate_speed"))) {
+                rotate_speed = strtof(value.data, NULL);
+            } else if (sv_eq(key, SV("objects_count"))) {
+                objects_count = strtol(value.data, NULL, 10);
+                if (objects_count > OBJECTS_CAP) {
+                    printf("%s:%d:%ld: WARNING: objects_count overflow\n",
+                           render_conf_path, row, key.data - line_start);
+                    objects_count = OBJECTS_CAP;
+                }
             } else {
             } else {
                 printf("%s:%d:%ld: ERROR: unsupported key `"SV_Fmt"`\n",
                 printf("%s:%d:%ld: ERROR: unsupported key `"SV_Fmt"`\n",
                        render_conf_path, row, key.data - line_start,
                        render_conf_path, row, key.data - line_start,
@@ -360,7 +413,7 @@ bool r_reload_textures(Renderer *r)
     return true;
     return true;
 }
 }
 
 
-bool r_reload_shaders(Renderer *r)
+bool r_reload_shaders(Renderer *r, const char *vert_path, const char *frag_path)
 {
 {
     glDeleteProgram(r->program);
     glDeleteProgram(r->program);
 
 
@@ -376,11 +429,11 @@ bool r_reload_shaders(Renderer *r)
     return true;
     return true;
 }
 }
 
 
-bool r_reload(Renderer *r)
+bool r_reload(Renderer *r, const char *vert_path, const char *frag_path)
 {
 {
     r->reload_failed = true;
     r->reload_failed = true;
 
 
-    if (!r_reload_shaders(r)) return false;
+    if (!r_reload_shaders(r, vert_path, frag_path)) return false;
     if (!r_reload_textures(r)) return false;
     if (!r_reload_textures(r)) return false;
 
 
     r->reload_failed = false;
     r->reload_failed = false;
@@ -399,6 +452,7 @@ typedef struct {
     GLuint tex_uniform;
     GLuint tex_uniform;
     GLuint color_uniform;
     GLuint color_uniform;
     GLuint t_uniform;
     GLuint t_uniform;
+    GLuint time_uniform;
 } Flash;
 } Flash;
 
 
 static Flash global_flash = {0};
 static Flash global_flash = {0};
@@ -451,6 +505,7 @@ void flash_init(Flash *flash)
     flash->tex_uniform = glGetUniformLocation(flash->program, "tex");
     flash->tex_uniform = glGetUniformLocation(flash->program, "tex");
     flash->color_uniform = glGetUniformLocation(flash->program, "color");
     flash->color_uniform = glGetUniformLocation(flash->program, "color");
     flash->t_uniform = glGetUniformLocation(flash->program, "t");
     flash->t_uniform = glGetUniformLocation(flash->program, "t");
+    flash->time_uniform = glGetUniformLocation(flash->program, "time");
 
 
     glUniform1i(flash->tex_uniform, 1);
     glUniform1i(flash->tex_uniform, 1);
     glUniform4f(flash->color_uniform, 1.0, 0.0, 0.0, 1.0);
     glUniform4f(flash->color_uniform, 1.0, 0.0, 0.0, 1.0);
@@ -478,6 +533,7 @@ void flash_sync_uniforms(Flash *f)
 {
 {
     glUniform1f(f->t_uniform, f->t);
     glUniform1f(f->t_uniform, f->t);
     glUniform4f(f->color_uniform, f->color.x, f->color.y, f->color.z, f->color.w);
     glUniform4f(f->color_uniform, f->color.x, f->color.y, f->color.z, f->color.w);
+    glUniform1f(f->time_uniform, time);
 }
 }
 
 
 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
@@ -489,7 +545,8 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
     if (action == GLFW_PRESS) {
     if (action == GLFW_PRESS) {
         if (key == GLFW_KEY_F5) {
         if (key == GLFW_KEY_F5) {
             reload_render_conf("render.conf");
             reload_render_conf("render.conf");
-            if (r_reload(&global_renderer)) {
+            if (r_reload(&global_renderer, vert_path, frag_path) &&
+                    r_reload(&ripple_renderer, "shaders/ripple.vert", "shaders/ripple.frag")) {
                 flash_bang(&global_flash, FLASH_GREEN_V4F);
                 flash_bang(&global_flash, FLASH_GREEN_V4F);
             } else {
             } else {
                 flash_bang(&global_flash, FLASH_RED_V4F);
                 flash_bang(&global_flash, FLASH_RED_V4F);
@@ -564,7 +621,6 @@ void MessageCallback(GLenum source,
 
 
 void r_init(Renderer *r)
 void r_init(Renderer *r)
 {
 {
-
     glGenVertexArrays(1, &r->vao);
     glGenVertexArrays(1, &r->vao);
     glBindVertexArray(r->vao);
     glBindVertexArray(r->vao);
 
 
@@ -653,7 +709,10 @@ int main(void)
     Renderer *r = &global_renderer;
     Renderer *r = &global_renderer;
 
 
     r_init(r);
     r_init(r);
-    r_reload(r);
+    r_reload(r, vert_path, frag_path);
+
+    r_init(&ripple_renderer);
+    r_reload(&ripple_renderer, "shaders/ripple.vert", "shaders/ripple.frag");
 
 
     glfwSetKeyCallback(window, key_callback);
     glfwSetKeyCallback(window, key_callback);
     glfwSetFramebufferSizeCallback(window, window_size_callback);
     glfwSetFramebufferSizeCallback(window, window_size_callback);
@@ -672,26 +731,47 @@ int main(void)
         glBindFramebuffer(GL_FRAMEBUFFER, global_flash.framebuffer);
         glBindFramebuffer(GL_FRAMEBUFFER, global_flash.framebuffer);
         {
         {
             glClear(GL_COLOR_BUFFER_BIT);
             glClear(GL_COLOR_BUFFER_BIT);
+            glBindVertexArray(r->vao);
+            glBindBuffer(GL_ARRAY_BUFFER, r->vbo);
             glUseProgram(r->program);
             glUseProgram(r->program);
             r_clear(r);
             r_clear(r);
-            r_sync_uniforms(r, width, height, time, xpos, ypos);
-            r_quad_cr(
-                r,
-                v2ff(0.0f),
-                v2f_mul(v2f(width, height), v2ff(0.5f)),
-                COLOR_BLACK_V4F);
+            r_sync_uniforms(r, width, height, time, xpos, ypos, 0);
+            for (size_t i = 0; i < objects_count; ++i) {
+                object_render(r, &objects[i]);
+            }
             r_sync_buffers(r);
             r_sync_buffers(r);
 
 
             glDrawArraysInstanced(GL_TRIANGLES, 0, (GLsizei) r->vertex_buf_sz, 1);
             glDrawArraysInstanced(GL_TRIANGLES, 0, (GLsizei) r->vertex_buf_sz, 1);
         }
         }
 
 
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
         {
         {
             glClear(GL_COLOR_BUFFER_BIT);
             glClear(GL_COLOR_BUFFER_BIT);
             glUseProgram(global_flash.program);
             glUseProgram(global_flash.program);
             flash_update(&global_flash, delta_time);
             flash_update(&global_flash, delta_time);
             flash_sync_uniforms(&global_flash);
             flash_sync_uniforms(&global_flash);
             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+            glBindVertexArray(ripple_renderer.vao);
+            glBindBuffer(GL_ARRAY_BUFFER, ripple_renderer.vbo);
+            glUseProgram(ripple_renderer.program);
+            r_clear(&ripple_renderer);
+            r_sync_uniforms(&ripple_renderer, width, height, time, xpos, ypos, 1);
+            r_quad_cr(&ripple_renderer, v2ff(0.0f), v2f(width * 0.5, height * 0.5), COLOR_BLACK_V4F);
+            r_sync_buffers(&ripple_renderer);
+
+            glDrawArraysInstanced(GL_TRIANGLES, 0, (GLsizei) ripple_renderer.vertex_buf_sz, 1);
+        }
+
+        if (objects_count > 0) {
+            float follow_x = sin(time * rotate_speed) * rotate_radius;
+            float follow_y = cos(time * rotate_speed) * rotate_radius;
+
+            object_update(&objects[0], delta_time, follow_x, follow_y);
+            for (size_t i = 1; i < objects_count; ++i) {
+                object_update(&objects[i], delta_time, objects[i - 1].x, objects[i - 1].y);
+            }
         }
         }
 
 
         glfwSwapBuffers(window);
         glfwSwapBuffers(window);

+ 7 - 0
render.conf

@@ -1,4 +1,11 @@
 vert = shaders/main.vert
 vert = shaders/main.vert
 frag = shaders/main.frag
 frag = shaders/main.frag
 texture = assets/tsodinW-345.png
 texture = assets/tsodinW-345.png
+#texture = assets/pogger.png
 #texture = assets/tsodinSleep-112.png
 #texture = assets/tsodinSleep-112.png
+
+follow_scale = 1.0
+object_size = 150.0
+rotate_radius = 300.0
+rotate_speed = 1.0
+objects_count = 3

+ 5 - 0
shaders/flash.frag

@@ -2,6 +2,7 @@
 
 
 precision mediump float;
 precision mediump float;
 
 
+uniform float time;
 uniform sampler2D tex;
 uniform sampler2D tex;
 uniform vec4 color;
 uniform vec4 color;
 uniform float t;
 uniform float t;
@@ -10,5 +11,9 @@ in vec2 uv;
 out vec4 out_color;
 out vec4 out_color;
 
 
 void main(void) {
 void main(void) {
+    vec2 cPos = 2.0*uv - 1.0;
+    float cLength = length(cPos);
+    vec2 tex_uv = uv + (cPos/cLength)*cos(cLength*12.0-time*4.0)*0.03;
+
     out_color = mix(texture(tex, uv), color, t);
     out_color = mix(texture(tex, uv), color, t);
 }
 }

+ 21 - 0
shaders/ripple.frag

@@ -0,0 +1,21 @@
+#version 330
+
+precision mediump float;
+
+uniform vec2 resolution;
+uniform float time;
+uniform vec2 mouse;
+uniform sampler2D tex;
+
+in vec2 uv;
+in vec4 color;
+out vec4 out_color;
+
+void main(void) {
+    vec2 cPos = 2.0*uv - 1.0;
+    float cLength = length(cPos);
+
+    vec2 tex_uv = uv + (cPos/cLength)*mix(cos(cLength*12.0-time*4.0)*0.03, 0.0, cLength / 0.25);
+
+    out_color = texture(tex, tex_uv);
+}

+ 25 - 0
shaders/ripple.vert

@@ -0,0 +1,25 @@
+#version 330
+
+layout(location = 0) in vec2 ver_pos;
+layout(location = 1) in vec2 ver_uv;
+layout(location = 2) in vec4 ver_color;
+
+uniform vec2 resolution;
+
+precision mediump float;
+
+out vec2 uv;
+out vec4 color;
+
+vec2 screen_project(vec2 pos)
+{
+    return (pos / resolution) * 2.0 - 1.0;
+}
+
+void main(void)
+{
+    float scale = 300.0;
+    gl_Position = vec4(screen_project(ver_pos + resolution * 0.5), 0.0, 1.0);
+    uv = ver_pos / resolution + 0.5;
+    color = ver_color;
+}