Commit: 17cdb1108111ff4ebdd0f01e9c76890aca6a4945
Parent: 8bf48859b5e39e7bce1c9bd8260621863c0c71f6
Author: Randy Palamar
Date:   Tue, 22 Oct 2024 06:58:16 -0600
add basic rectangle drawing shader
this will be used for UI (and fixing the debug overlay)
Diffstat:
5 files changed, 73 insertions(+), 38 deletions(-)
diff --git a/frag_for_rects.glsl b/frag_for_rects.glsl
@@ -0,0 +1,14 @@
+#version 430 core
+
+layout(location = 0) in vec2 fragment_pixel_coordinate;
+layout(location = 1) in vec2 fragment_texture_coordinate;
+layout(location = 2) in vec4 fragment_colour;
+
+layout(location = 0) out vec4 colour;
+
+layout(location = 3) uniform sampler2D u_texslot;
+
+void main()
+{
+	colour = fragment_colour * texture(u_texslot, fragment_texture_coordinate);
+}
diff --git a/frag_post.glsl b/frag_post.glsl
@@ -12,7 +12,7 @@ layout(location = 4) uniform float     u_param;
 void main()
 {
 	vec2 texture_coord = fragment_texture_coordinate;
-	//if (mod(tex_coord.y + u_param, 0.005) < 0.0005) {
+	//if (mod(texture_coord.y + u_param, 0.005) < 0.0005) {
 	if (false) {
 		vec4 tint = vec4(0.1, 0.1, 0.1, 1);
 		colour = mix(texture(u_texslot, texture_coord), tint, 0.5);
diff --git a/main.c b/main.c
@@ -91,6 +91,19 @@ error_callback(int code, const char *desc)
 	fprintf(stderr, "GLFW Error (0x%04X): %s\n", code, desc);
 }
 
+static u32
+gen_2D_texture(iv2 size, u32 format, u32 filter, u32 *rgba)
+{
+	/* TODO: logging */
+	u32 result;
+	glGenTextures(1, &result);
+	glBindTexture(GL_TEXTURE_2D, result);
+	glTexImage2D(GL_TEXTURE_2D, 0, format, size.w, size.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+	return result;
+}
+
 static void
 init_window(Term *t, Arena arena, iv2 window_size)
 {
@@ -164,13 +177,10 @@ init_window(Term *t, Arena arena, iv2 window_size)
 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * ARRAY_COUNT(rpb->positions) * sizeof(i32),
 	             element_indices, GL_STATIC_DRAW);
 
-	glGenTextures(1, &t->gl.glyph_bitmap_tex);
-	glBindTexture(GL_TEXTURE_2D, t->gl.glyph_bitmap_tex);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-	             t->gl.glyph_bitmap_dim.w, t->gl.glyph_bitmap_dim.h,
-	             0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	u32 white = 0xFFFFFFFF;
+
+	t->gl.default_tex      = gen_2D_texture((iv2){.x = 1, .y = 1}, GL_RGBA, GL_NEAREST, &white);
+	t->gl.glyph_bitmap_tex = gen_2D_texture(t->gl.glyph_bitmap_dim, GL_RGBA, GL_NEAREST, 0);
 
 	glEnable(GL_BLEND);
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -182,14 +192,8 @@ init_window(Term *t, Arena arena, iv2 window_size)
 
 	t->gl.fb_tex_unit = 1;
 	glActiveTexture(GL_TEXTURE0 + t->gl.fb_tex_unit);
-	glGenTextures(1, &t->gl.fb_tex);
-	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);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
+	iv2 ws = {.x = t->gl.window_size.w, .y = t->gl.window_size.h};
+	t->gl.fb_tex = gen_2D_texture(ws, GL_RGBA, GL_NEAREST, 0);
 	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, t->gl.fb_tex, 0);
 
 	glGenBuffers(1, &t->gl.render_shader_ubo);
@@ -197,6 +201,8 @@ init_window(Term *t, Arena arena, iv2 window_size)
 	glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderParameters), 0, GL_DYNAMIC_DRAW);
 	glBindBufferBase(GL_UNIFORM_BUFFER, 0, t->gl.render_shader_ubo);
 
+	glActiveTexture(GL_TEXTURE0);
+
 	t->gl.flags |= INIT_DEBUG;
 }
 
@@ -256,14 +262,24 @@ program_from_shader_text(s8 vertex, s8 fragment, Arena a)
 static void
 check_shaders(GLCtx *gl, Arena a)
 {
-	static char *fs_name[SHADER_LAST] = {"frag_render.glsl",    "frag_post.glsl"};
-	static char *vs_name[SHADER_LAST] = {"vert_for_rects.glsl", "vert_for_rects.glsl"};
+	static char *fs_name[SHADER_LAST] = {
+		"frag_render.glsl",
+		"frag_for_rects.glsl",
+		"frag_post.glsl",
+	};
+	static char *vs_name[SHADER_LAST] = {
+		"vert_for_rects.glsl",
+		"vert_for_rects.glsl",
+		"vert_for_rects.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_RENDER] = {.name = "Render", .flag = 0},
+		[SHADER_RECTS]  = {.name = "Rects",  .flag = 0},
 		[SHADER_POST]   = {.name = "Post",   .flag = UPDATE_POST_UNIFORMS},
 	};
 
diff --git a/util.h b/util.h
@@ -183,8 +183,7 @@ typedef struct {
 	size        last_line_idx;
 } TermView;
 
-#define GL_RENDER_UNIFORMS \
-	X(Pmat)
+#define SHADER_PMAT_LOC 0
 
 #define GL_POST_UNIFORMS \
 	X(Pmat)          \
@@ -197,7 +196,6 @@ enum gl_flags {
 	NEEDS_FULL_REFILL      = 1 << 2,
 	UPDATE_RENDER_BUFFER   = 1 << 3,
 
-	UPDATE_RENDER_UNIFORMS = 1 << 27,
 	UPDATE_POST_UNIFORMS   = 1 << 28,
 	INIT_DEBUG             = 1 << 29,
 	DRAW_DEBUG_OVERLAY     = 1 << 30,
@@ -213,6 +211,7 @@ enum win_mode {
 
 enum shader_stages {
 	SHADER_RENDER,
+	SHADER_RECTS,
 	SHADER_POST,
 	SHADER_LAST
 };
@@ -244,15 +243,13 @@ typedef struct {
 
 	u32 fb, fb_tex, fb_tex_unit;
 
+	u32 default_tex;
+
 	u32 programs[SHADER_LAST];
 	#define X(name) i32 name;
 	union {
-		struct { GL_RENDER_UNIFORMS };
-		i32 uniforms[7];
-	} render;
-	union {
 		struct { GL_POST_UNIFORMS };
-		i32 uniforms[4];
+		i32 uniforms[3];
 	} post;
 	#undef X
 
diff --git a/vtgl.c b/vtgl.c
@@ -48,10 +48,9 @@ set_projection_matrix(GLCtx *gl)
 		0.0,     0.0,      0.0,     1.0,
 	};
 
-	glUseProgram(gl->programs[SHADER_RENDER]);
-	glUniformMatrix4fv(gl->render.Pmat, 1, GL_TRUE, pmat);
-	glUseProgram(gl->programs[SHADER_POST]);
-	glUniformMatrix4fv(gl->post.Pmat, 1, GL_TRUE, pmat);
+	glProgramUniformMatrix4fv(gl->programs[SHADER_RENDER], SHADER_PMAT_LOC, 1, GL_TRUE, pmat);
+	glProgramUniformMatrix4fv(gl->programs[SHADER_RECTS],  SHADER_PMAT_LOC, 1, GL_TRUE, pmat);
+	glProgramUniformMatrix4fv(gl->programs[SHADER_POST],   SHADER_PMAT_LOC, 1, GL_TRUE, pmat);
 }
 
 static v2
@@ -127,11 +126,7 @@ update_uniforms(Term *t, enum shader_stages stage)
 {
 	switch (stage) {
 	case SHADER_RENDER:
-		#define X(name) \
-			t->gl.render.name = glGetUniformLocation(t->gl.programs[stage], "u_" #name);
-		GL_RENDER_UNIFORMS
-		#undef X
-		t->gl.flags &= ~UPDATE_RENDER_UNIFORMS;
+	case SHADER_RECTS:
 		break;
 	case SHADER_POST:
 		#define X(name) \
@@ -771,8 +766,6 @@ do_terminal(Term *t, f32 dt)
 {
 	dt_for_frame = dt;
 
-	if (t->gl.flags & UPDATE_RENDER_UNIFORMS)
-		update_uniforms(t, SHADER_RENDER);
 	if (t->gl.flags & UPDATE_POST_UNIFORMS)
 		update_uniforms(t, SHADER_POST);
 
@@ -784,6 +777,11 @@ do_terminal(Term *t, f32 dt)
 		t->gl.flags &= ~INIT_DEBUG;
 	}
 
+	/* NOTE: this needs to be bound for blitting lines because that function can
+	 * access the font cache.
+	 * TODO: cleanup */
+	glBindTexture(GL_TEXTURE_2D, t->gl.glyph_bitmap_tex);
+
 	size parsed_lines = 0;
 	if (os_child_data_available(t->child)) {
 		RingBuf *rb = &t->views[t->view_idx].log;
@@ -856,6 +854,16 @@ do_terminal(Term *t, f32 dt)
 
 	push_rect(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 1);
 	flush_render_push_buffer(rpb, &t->gl);
+
+	#if 0
+	/* NOTE: this happens at the end so that ui stuff doesn't go through the post
+	 * processing/effects shader */
+	glUseProgram(t->gl.programs[SHADER_RECTS]);
+	glBindTexture(GL_TEXTURE_2D, t->gl.default_tex);
+	push_rect(rpb, &t->gl, (Rect){.size = {.w = 300, .h = 200}}, (v4){.r = 0.5, .a = 1}, 0);
+	push_rect(rpb, &t->gl, (Rect){.pos = {.x = 300, .y = 200}, .size = {.w = 300, .h = 200}}, (v4){.g = 0.5, .a = 1}, 0);
+	flush_render_push_buffer(rpb, &t->gl);
+	#endif
 }
 
 #ifdef _DEBUG