Commit: 7d1c35b39e63aeb8dfea640aa6724de442955fba
Parent: 1be2e60791c0b00cecfaaf917ce81e5fad3011e3
Author: Randy Palamar
Date: Tue, 2 Jul 2024 22:58:32 -0600
add post processing shader and scanline nonsense
Diffstat:
7 files changed, 186 insertions(+), 77 deletions(-)
diff --git a/frag_post.glsl b/frag_post.glsl
@@ -0,0 +1,22 @@
+#version 460 core
+
+out vec4 colour;
+
+in VS_OUT {
+ vec2 tex_coord;
+} fs_in;
+
+uniform sampler2D u_texslot;
+uniform float u_param;
+
+void main()
+{
+ vec2 tex_coord = fs_in.tex_coord;
+
+ if (mod(tex_coord.y + u_param, 0.005) < 0.0005) {
+ vec4 tint = vec4(0.1, 0.1, 0.1, 1);
+ colour = mix(texture(u_texslot, tex_coord), tint, 0.5);
+ } else {
+ colour = texture(u_texslot, tex_coord);
+ }
+}
diff --git a/frag.glsl b/frag_render.glsl
diff --git a/main.c b/main.c
@@ -227,29 +227,40 @@ program_from_shader_text(s8 vertex, s8 fragment, Arena a)
static void
check_shaders(GLCtx *gl, Arena a)
{
- static char *fs_name = "frag.glsl";
- static char *vs_name = "vert.glsl";
- static os_file_stats fs_stats, vs_stats;
- os_file_stats fs_test = os_get_file_stats(fs_name);
- os_file_stats vs_test = os_get_file_stats(vs_name);
-
- if (os_filetime_changed(fs_test.timestamp, fs_stats.timestamp) ||
- os_filetime_changed(vs_test.timestamp, vs_stats.timestamp)) {
- fprintf(stderr, "Reloading Shaders!\n");
- fs_stats = fs_test;
- vs_stats = vs_test;
-
- s8 vs_text = os_read_file(&a, vs_name, vs_stats.filesize);
- s8 fs_text = os_read_file(&a, fs_name, fs_stats.filesize);
+ static char *fs_name[SHADER_LAST] = {"frag_render.glsl", "frag_post.glsl"};
+ static char *vs_name[SHADER_LAST] = {"vert_render.glsl", "vert_post.glsl"};
+ static os_file_stats fs_stats[SHADER_LAST], vs_stats[SHADER_LAST];
+ static struct {
+ char *name;
+ u32 flag;
+ } map[SHADER_LAST] = {
+ [SHADER_RENDER] = {.name = "Render", .flag = UPDATE_RENDER_UNIFORMS},
+ [SHADER_POST] = {.name = "Post", .flag = UPDATE_POST_UNIFORMS},
+ };
+
+ for (u32 i = 0; i < SHADER_LAST; i++) {
+ os_file_stats fs_test = os_get_file_stats(fs_name[i]);
+ os_file_stats vs_test = os_get_file_stats(vs_name[i]);
+
+ if (!os_filetime_changed(fs_test.timestamp, fs_stats[i].timestamp) &&
+ !os_filetime_changed(vs_test.timestamp, vs_stats[i].timestamp))
+ continue;
+
+ fprintf(stderr, "Reloading %s Shader!\n", map[i].name);
+ fs_stats[i] = fs_test;
+ vs_stats[i] = vs_test;
+
+ s8 vs_text = os_read_file(&a, vs_name[i], vs_stats[i].filesize);
+ s8 fs_text = os_read_file(&a, fs_name[i], fs_stats[i].filesize);
ASSERT(vs_text.len > 0 && fs_text.len > 0);
u32 program = program_from_shader_text(vs_text, fs_text, a);
- if (program) {
- glDeleteProgram(gl->program);
- gl->program = program;
- gl->flags |= UPDATE_UNIFORMS;
- fprintf(stderr, "Program Updated!\n");
- }
+ if (!program)
+ continue;
+ glDeleteProgram(gl->programs[i]);
+ gl->programs[i] = program;
+ gl->flags |= map[i].flag;
+ fprintf(stderr, "%s Program Updated!\n", map[i].name);
}
}
diff --git a/util.h b/util.h
@@ -122,21 +122,6 @@ typedef struct {
Line *buf;
} LineBuf;
-#define GL_UNIFORMS \
- X(Pmat) \
- X(charmap) \
- X(texcolour) \
- X(texscale) \
- X(texslot) \
- X(vertoff) \
- X(vertscale)
-
-enum gl_flags {
- NEEDS_RESIZE = 1 << 0,
- DISCARD_BUFFER = 1 << 1,
- UPDATE_UNIFORMS = 1 << 30,
-};
-
typedef struct {
/* distance to shift glyph from bounding box origin */
iv2 delta;
@@ -144,6 +129,34 @@ typedef struct {
uv2 size;
} Glyph;
+#define GL_RENDER_UNIFORMS \
+ X(Pmat) \
+ X(charmap) \
+ X(texcolour) \
+ X(texscale) \
+ X(texslot) \
+ X(vertoff) \
+ X(vertscale)
+
+#define GL_POST_UNIFORMS \
+ X(Pmat) \
+ X(param) \
+ X(texslot) \
+ X(vertscale) \
+ X(yoff)
+
+enum gl_flags {
+ DISCARD_BUFFER = 1 << 0,
+ UPDATE_RENDER_UNIFORMS = 1 << 29,
+ UPDATE_POST_UNIFORMS = 1 << 30,
+};
+
+enum shader_stages {
+ SHADER_RENDER,
+ SHADER_POST,
+ SHADER_LAST
+};
+
typedef struct {
GLFWwindow *window;
v2 window_size;
@@ -154,12 +167,16 @@ typedef struct {
u32 fb, fb_tex, fb_tex_unit;
- u32 program;
+ u32 programs[SHADER_LAST];
#define X(name) i32 name;
union {
- struct { GL_UNIFORMS };
+ struct { GL_RENDER_UNIFORMS };
i32 uniforms[7];
- };
+ } render;
+ union {
+ struct { GL_POST_UNIFORMS };
+ i32 uniforms[5];
+ } post;
#undef X
u32 flags;
diff --git a/vert_post.glsl b/vert_post.glsl
@@ -0,0 +1,28 @@
+#version 460 core
+
+in vec2 position;
+
+uniform mat4 u_Pmat;
+uniform vec2 u_vertscale;
+uniform float u_yoff;
+
+out VS_OUT {
+ vec2 tex_coord;
+} vs_out;
+
+void main()
+{
+ vec2 pos = position.xy;
+ vec2 scale = u_vertscale;
+
+ mat4 transform = mat4(
+ scale.x, 0, 0, 0,
+ 0, scale.y, 0, 0,
+ 0, 0, 1, 0,
+ 0, u_yoff, 0, 1
+ );
+
+ gl_Position = u_Pmat * transform * vec4(pos, 0.0, 1.0);
+
+ vs_out.tex_coord = pos;
+}
diff --git a/vert.glsl b/vert_render.glsl
diff --git a/vtgl.c b/vtgl.c
@@ -10,10 +10,13 @@
#define TEXTURE_GLYPH_COUNT 128
#define X(name) "u_"#name,
-static char *uniform_names[] = { GL_UNIFORMS };
+static char *render_uniform_names[] = { GL_RENDER_UNIFORMS };
+static char *post_uniform_names[] = { GL_POST_UNIFORMS };
#undef X
-static_assert(ARRAY_COUNT(uniform_names) == ARRAY_COUNT(((GLCtx *)0)->uniforms),
- "GLCtx.uniforms must be same length as GL_UNIFORMS\n");
+static_assert(ARRAY_COUNT(render_uniform_names) == ARRAY_COUNT(((GLCtx *)0)->render.uniforms),
+ "GLCtx.render.uniforms must be same length as GL_RENDER_UNIFORMS\n");
+static_assert(ARRAY_COUNT(post_uniform_names) == ARRAY_COUNT(((GLCtx *)0)->post.uniforms),
+ "GLCtx.post.uniforms must be same length as GL_POST_UNIFORMS\n");
static v4
normalized_colour(Colour c)
@@ -34,14 +37,22 @@ static void
resize(GLCtx *gl)
{
v2 ws = gl->window_size;
- f32 pmat[4 * 4] = {
- 2.0 / ws.w, 0.0, 0.0, -1.0,
- 0.0, 2.0 / ws.h, 0.0, -1.0,
+ f32 render_pmat[4 * 4] = {
+ 2.0/ws.w, 0.0, 0.0, -1.0,
+ 0.0, 2.0/ws.h, 0.0, -1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
};
- glUniformMatrix4fv(gl->Pmat, 1, GL_TRUE, pmat);
- gl->flags &= ~NEEDS_RESIZE;
+ f32 post_pmat[4 * 4] = {
+ 2.0/ws.w, 0.0, 0.0, -1.0,
+ 0.0, 4.0/ws.h, 0.0, -1.0,
+ 0.0, 0.0, -1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+ glUseProgram(gl->programs[SHADER_RENDER]);
+ glUniformMatrix4fv(gl->render.Pmat, 1, GL_TRUE, render_pmat);
+ glUseProgram(gl->programs[SHADER_POST]);
+ glUniformMatrix4fv(gl->post.Pmat, 1, GL_TRUE, post_pmat);
}
static void
@@ -66,16 +77,27 @@ update_font_textures(Term *t)
}
static void
-update_uniforms(Term *t)
+update_uniforms(Term *t, enum shader_stages stage)
{
- for (u32 i = 0; i < ARRAY_COUNT(t->gl.uniforms); i++)
- t->gl.uniforms[i] = glGetUniformLocation(t->gl.program, uniform_names[i]);
- t->gl.flags &= ~UPDATE_UNIFORMS;
+ ASSERT(stage != SHADER_LAST);
+
+ switch (stage) {
+ case SHADER_RENDER:
+ for (u32 i = 0; i < ARRAY_COUNT(t->gl.render.uniforms); i++)
+ t->gl.render.uniforms[i] = glGetUniformLocation(t->gl.programs[stage],
+ render_uniform_names[i]);
+ t->gl.flags &= ~UPDATE_RENDER_UNIFORMS;
+ break;
+ case SHADER_POST:
+ for (u32 i = 0; i < ARRAY_COUNT(t->gl.post.uniforms); i++)
+ t->gl.post.uniforms[i] = glGetUniformLocation(t->gl.programs[stage],
+ post_uniform_names[i]);
+ t->gl.flags &= ~UPDATE_POST_UNIFORMS;
+ break;
+ case SHADER_LAST: ASSERT(0); break;
+ }
- glUniform1i(t->gl.texslot, 0);
update_font_textures(t);
-
- resize(&t->gl);
}
static i32
@@ -107,11 +129,11 @@ measure_text(GLCtx *gl, s8 text, b32 monospaced)
static void
push_char(GLCtx *gl, v2 vertscale, v2 vertoff, v2 texscale, uv2 colours, i32 char_idx)
{
- glUniform2uiv(gl->texcolour, 1, colours.E);
- glUniform1iv(gl->charmap, 1, &char_idx);
- glUniform2fv(gl->texscale, 1, texscale.E);
- glUniform2fv(gl->vertscale, 1, vertscale.E);
- glUniform2fv(gl->vertoff, 1, vertoff.E);
+ glUniform2uiv(gl->render.texcolour, 1, colours.E);
+ glUniform1iv(gl->render.charmap, 1, &char_idx);
+ glUniform2fv(gl->render.texscale, 1, texscale.E);
+ glUniform2fv(gl->render.vertscale, 1, vertscale.E);
+ glUniform2fv(gl->render.vertoff, 1, vertoff.E);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
}
@@ -176,11 +198,11 @@ push_cell(Term *t, u32 cp, Rect r, u32 bg, u32 fg)
colours[2] = fg;
colours[3] = bg;
- glUniform2uiv(gl->texcolour, 2, colours);
- glUniform1iv(gl->charmap, 2, charmap);
- glUniform2fv(gl->texscale, 2, (f32 *)texscale);
- glUniform2fv(gl->vertscale, 2, (f32 *)vertscale);
- glUniform2fv(gl->vertoff, 2, (f32 *)vertoff);
+ glUniform2uiv(gl->render.texcolour, 2, colours);
+ glUniform1iv(gl->render.charmap, 2, charmap);
+ glUniform2fv(gl->render.texscale, 2, (f32 *)texscale);
+ glUniform2fv(gl->render.vertscale, 2, (f32 *)vertscale);
+ glUniform2fv(gl->render.vertoff, 2, (f32 *)vertoff);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 2);
}
@@ -267,7 +289,6 @@ fb_callback(GLFWwindow *win, i32 w, i32 h)
Term *t = glfwGetWindowUserPointer(win);
t->gl.window_size.w = w;
t->gl.window_size.h = FB_HEIGHT_SCALE * h;
- t->gl.flags |= NEEDS_RESIZE;
v2 cs = get_cell_size(t);
t->size.w = (u32)(w / cs.w);
@@ -281,6 +302,8 @@ fb_callback(GLFWwindow *win, i32 w, i32 h)
glBindTexture(GL_TEXTURE_2D, t->gl.fb_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t->gl.window_size.w, t->gl.window_size.h,
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ resize(&t->gl);
}
static void
@@ -328,11 +351,10 @@ init_callbacks(GLCtx *gl)
DEBUG_EXPORT void
do_terminal(Term *t, Arena a)
{
- if (t->gl.flags & UPDATE_UNIFORMS)
- update_uniforms(t);
-
- if (t->gl.flags & NEEDS_RESIZE)
- resize(&t->gl);
+ if (t->gl.flags & UPDATE_RENDER_UNIFORMS)
+ update_uniforms(t, SHADER_RENDER);
+ if (t->gl.flags & UPDATE_POST_UNIFORMS)
+ update_uniforms(t, SHADER_POST);
if (os_child_data_available(t->child)) {
if (os_child_exited(t->child))
@@ -350,6 +372,8 @@ do_terminal(Term *t, Arena a)
v2 ws = t->gl.window_size;
/* NOTE: reset the camera/viewport */
+ glUseProgram(t->gl.programs[SHADER_RENDER]);
+ glUniform1i(t->gl.render.texslot, 0);
glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb);
clear_colour();
glViewport(0, 0, ws.w, ws.h);
@@ -393,12 +417,19 @@ do_terminal(Term *t, Arena a)
draw_text(&t->gl, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1);
}
- glBindFramebuffer(GL_READ_FRAMEBUFFER, t->gl.fb);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
- glBlitFramebuffer(src_bl.x, src_bl.y, src_tr.x, src_tr.y,
- 0, 0, ws.w, ws.h / FB_HEIGHT_SCALE,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
- //glActiveTexture(GL_TEXTURE0 + t->gl.fb_tex_unit);
- //glBindTexture(GL_TEXTURE_2D, t->gl.fb_tex);
+ static f32 param = 0;
+ static f32 p_scale = 1;
+ param += p_scale * 0.005 * t->gl.dt;
+ if (param > 1.0f || param < 0)
+ p_scale *= -1.0f;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, ws.w, ws.h/FB_HEIGHT_SCALE);
+ glUseProgram(t->gl.programs[SHADER_POST]);
+ glUniform1i(t->gl.post.texslot, t->gl.fb_tex_unit);
+ f32 yoff = -MIN(cursor_pos.y, ws.h/FB_HEIGHT_SCALE);
+ glUniform1f(t->gl.post.yoff, yoff);
+ glUniform1f(t->gl.post.param, param);
+ glUniform2fv(t->gl.post.vertscale, 1, (f32 []){ws.w, ws.h});
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}