Commit: 8bf48859b5e39e7bce1c9bd8260621863c0c71f6
Parent: eefea3d75f758700c76af83c46e742684a7e927d
Author: Randy Palamar
Date: Mon, 21 Oct 2024 21:44:40 -0600
set up pipeline for drawing more arbitray rectangles
Diffstat:
6 files changed, 119 insertions(+), 59 deletions(-)
diff --git a/frag_post.glsl b/frag_post.glsl
@@ -1,7 +1,8 @@
#version 430 core
-layout(location = 0) in vec2 pixel_coord;
-layout(location = 1) in vec2 texture_coord;
+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;
@@ -10,6 +11,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 (false) {
vec4 tint = vec4(0.1, 0.1, 0.1, 1);
diff --git a/frag_render.glsl b/frag_render.glsl
@@ -1,7 +1,8 @@
#version 430 core
-layout(location = 0) in vec2 pixel_coord;
-layout(location = 1) in vec2 texture_coord;
+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;
@@ -51,6 +52,8 @@ unpack_glyph_position(uint glyph_position)
void main()
{
+ vec2 pixel_coord = fragment_pixel_coordinate;
+
uvec2 cell_index = uvec2((pixel_coord - top_left_margin) / cell_size);
vec2 cell_pos = mod((pixel_coord - top_left_margin), cell_size);
diff --git a/main.c b/main.c
@@ -129,18 +129,40 @@ init_window(Term *t, Arena arena, iv2 window_size)
glGenVertexArrays(1, &t->gl.vao);
glBindVertexArray(t->gl.vao);
- glGenBuffers(1, &t->gl.vbo);
- glBindBuffer(GL_ARRAY_BUFFER, t->gl.vbo);
-
- f32 verts[] = {
- 0.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 1.0f,
- 1.0f, 0.0f,
- };
+ glGenBuffers(ARRAY_COUNT(t->gl.vbos), t->gl.vbos);
+
+ RenderPushBuffer *rpb = NULL;
+ /* NOTE: vertex position buffer */
+ glBindBuffer(GL_ARRAY_BUFFER, t->gl.vbos[0]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(rpb->positions), 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
- glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+ glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, 0);
+
+ /* NOTE: vertex texture coordinate buffer */
+ glBindBuffer(GL_ARRAY_BUFFER, t->gl.vbos[1]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(rpb->texture_coordinates), 0, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0);
+
+ /* NOTE: vertex colour buffer */
+ glBindBuffer(GL_ARRAY_BUFFER, t->gl.vbos[2]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(rpb->colours), 0, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_FLOAT, 0, 0, 0);
+
+ /* NOTE: fill in element index buffer */
+ i32 *element_indices = alloc(&arena, i32, 6 * ARRAY_COUNT(rpb->positions));
+ for (i32 i = 0, j = 0; i < 6 * ARRAY_COUNT(rpb->positions); i += 6, j++) {
+ element_indices[i + 0] = 4 * j;
+ element_indices[i + 1] = 4 * j + 1;
+ element_indices[i + 2] = 4 * j + 2;
+ element_indices[i + 3] = 4 * j;
+ element_indices[i + 4] = 4 * j + 2;
+ element_indices[i + 5] = 4 * j + 3;
+ }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, t->gl.vbos[4]);
+ 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);
@@ -215,6 +237,7 @@ program_from_shader_text(s8 vertex, s8 fragment, Arena a)
u32 fid = compile_shader(a, GL_FRAGMENT_SHADER, fragment);
if (fid == 0) {
+ glDeleteShader(vid);
glDeleteProgram(pid);
return 0;
}
diff --git a/util.h b/util.h
@@ -184,14 +184,12 @@ typedef struct {
} TermView;
#define GL_RENDER_UNIFORMS \
- X(Pmat) \
- X(vertscale)
+ X(Pmat)
#define GL_POST_UNIFORMS \
X(Pmat) \
X(param) \
- X(texslot) \
- X(vertscale)
+ X(texslot)
enum gl_flags {
NEEDS_RESIZE = 1 << 0,
@@ -242,7 +240,7 @@ typedef struct {
GLFWwindow *window;
v2 window_size;
- u32 vao, vbo;
+ u32 vao, vbos[5];
u32 fb, fb_tex, fb_tex_unit;
@@ -275,21 +273,17 @@ typedef struct {
u32 bg;
} RenderCell;
-/* NOTE: This must match the number in the shaders & the number glyphs in
- * the gpu glyph cache. By doing this we ensure that filling a single push buffer
- * will not evict a needed glyph texture from the GPU */
-#define PUSH_BUFFER_CAP 512
+/* TODO: try different sizes; largely depends on how many things we want to batch together */
+#define RENDER_PUSH_BUFFER_CAP 8192
typedef struct {
- v2 vertscales[PUSH_BUFFER_CAP];
- v2 vertoffsets[PUSH_BUFFER_CAP];
- v2 texscales[PUSH_BUFFER_CAP];
- uv2 texcolours[PUSH_BUFFER_CAP];
- i32 charmap[PUSH_BUFFER_CAP];
+ v2 positions[RENDER_PUSH_BUFFER_CAP];
+ v2 texture_coordinates[RENDER_PUSH_BUFFER_CAP];
+ v4 colours[RENDER_PUSH_BUFFER_CAP];
u32 count;
} RenderPushBuffer;
-#define MIN_FONT_SIZE 8
-#define MAX_FONT_SIZE 128
+#define MIN_FONT_SIZE 8
+#define MAX_FONT_SIZE 128
enum conversion_status { CR_FAILURE, CR_SUCCESS };
struct conversion_result {
diff --git a/vert_for_rects.glsl b/vert_for_rects.glsl
@@ -1,21 +1,21 @@
#version 430 core
-layout(location = 0) in vec2 position;
+layout(location = 0) in vec2 vertex_position;
+layout(location = 1) in vec2 vertex_texture_coordinate;
+layout(location = 2) in vec4 vertex_colour;
-layout(location = 0) out vec2 pixel_coord;
-layout(location = 1) out vec2 texture_coord;
+layout(location = 0) out vec2 fragment_pixel_coordinate;
+layout(location = 1) out vec2 fragment_texture_coordinate;
+layout(location = 2) out vec4 fragment_colour;
+layout(location = 3) out flat int fragment_texture_index;
layout(location = 0) uniform mat4 u_Pmat;
-layout(location = 1) uniform vec2 u_vertscale;
void main()
{
- vec2 pos = position.xy;
- vec2 scale = u_vertscale;
+ fragment_texture_coordinate = vertex_texture_coordinate;
+ fragment_pixel_coordinate = vertex_position * vertex_texture_coordinate;
+ fragment_colour = vertex_colour;
- texture_coord = pos;
- pixel_coord = pos;
- pixel_coord.y = 1 - pixel_coord.y;
- pixel_coord *= scale;
- gl_Position = u_Pmat * vec4(pos * scale, 0.0, 1.0);
+ gl_Position = u_Pmat * vec4(vertex_position, 0.0, 1.0);
}
diff --git a/vtgl.c b/vtgl.c
@@ -176,25 +176,30 @@ get_gpu_glyph_index(Arena a, GLCtx *gl, FontAtlas *fa, u32 codepoint, enum face_
return cg->gpu_tile_index;
}
-#if 0
+/* NOTE: this function assumes we are drawing quads */
static void
flush_render_push_buffer(RenderPushBuffer *rpb, GLCtx *gl)
{
- if (rpb->count == 0)
- return;
- glUniform2fv(gl->render.vertscale, rpb->count, (f32 *)rpb->vertscales);
- glUniform2fv(gl->render.vertoff, rpb->count, (f32 *)rpb->vertoffsets);
- glUniform2fv(gl->render.texscale, rpb->count, (f32 *)rpb->texscales);
- glUniform2uiv(gl->render.texcolour, rpb->count, (u32 *)rpb->texcolours);
- glUniform1iv(gl->render.charmap, rpb->count, (i32 *)rpb->charmap);
- glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, rpb->count);
+ if (rpb->count > 0) {
+ u32 n = rpb->count;
+ ASSERT((n % 4) == 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, gl->vbos[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, n * sizeof(*rpb->positions), rpb->positions);
+ glBindBuffer(GL_ARRAY_BUFFER, gl->vbos[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, n * sizeof(*rpb->texture_coordinates), rpb->texture_coordinates);
+ glBindBuffer(GL_ARRAY_BUFFER, gl->vbos[2]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, n * sizeof(*rpb->colours), rpb->colours);
+
+ glDrawElements(GL_TRIANGLES, 6 * n / 4, GL_UNSIGNED_INT, 0);
+ }
rpb->count = 0;
}
static u32
get_render_push_buffer_idx(RenderPushBuffer *rpb, GLCtx *gl, u32 count)
{
- if (rpb->count + count > PUSH_BUFFER_CAP)
+ if (rpb->count + count > RENDER_PUSH_BUFFER_CAP)
flush_render_push_buffer(rpb, gl);
u32 result = rpb->count;
rpb->count += count;
@@ -202,6 +207,39 @@ get_render_push_buffer_idx(RenderPushBuffer *rpb, GLCtx *gl, u32 count)
}
static void
+push_rect(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour, b32 flip_texture)
+{
+ u32 idx = get_render_push_buffer_idx(rpb, gl, 4);
+ v2 start = r.pos;
+ v2 end = {.x = r.pos.x + r.size.w, .y = r.pos.y + r.size.h};
+
+ rpb->positions[idx + 0] = (v2){.x = end.x, .y = end.y };
+ rpb->positions[idx + 1] = (v2){.x = end.x, .y = start.y};
+ rpb->positions[idx + 2] = (v2){.x = start.x, .y = start.y};
+ rpb->positions[idx + 3] = (v2){.x = start.x, .y = end.y };
+
+ /* TODO: cleanup */
+ if (!flip_texture) {
+ rpb->texture_coordinates[idx + 0] = (v2){.x = 1.0f, .y = 1.0f};
+ rpb->texture_coordinates[idx + 1] = (v2){.x = 1.0f, .y = 0.0f};
+ rpb->texture_coordinates[idx + 2] = (v2){.x = 0.0f, .y = 0.0f};
+ rpb->texture_coordinates[idx + 3] = (v2){.x = 0.0f, .y = 1.0f};
+ } else {
+ rpb->texture_coordinates[idx + 0] = (v2){.x = 1.0f, .y = 0.0f};
+ rpb->texture_coordinates[idx + 1] = (v2){.x = 1.0f, .y = 1.0f};
+ rpb->texture_coordinates[idx + 2] = (v2){.x = 0.0f, .y = 1.0f};
+ rpb->texture_coordinates[idx + 3] = (v2){.x = 0.0f, .y = 0.0f};
+ }
+
+ rpb->colours[idx + 0] = colour;
+ rpb->colours[idx + 1] = colour;
+ rpb->colours[idx + 2] = colour;
+ rpb->colours[idx + 3] = colour;
+}
+
+#if 0
+
+static void
push_char(RenderPushBuffer *rpb, GLCtx *gl, v2 vertscale, v2 vertoff, v2 texscale,
uv2 colours, i32 char_idx)
{
@@ -771,6 +809,8 @@ do_terminal(Term *t, f32 dt)
update_selection(t);
+ RenderPushBuffer *rpb = alloc(&t->arena_for_frame, RenderPushBuffer, 1);
+
glUseProgram(t->gl.programs[SHADER_RENDER]);
glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb);
clear_colour(t->gl.mode & WIN_MODE_REVERSE);
@@ -794,13 +834,12 @@ do_terminal(Term *t, f32 dt)
sp->underline_min = (0.89 * t->fa.info.h);
sp->underline_max = (0.96 * t->fa.info.h);
- glUniform2fv(t->gl.render.vertscale, 1, t->gl.window_size.E);
-
glBindBuffer(GL_UNIFORM_BUFFER, t->gl.render_shader_ubo);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, t->gl.render_shader_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*sp), sp);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ push_rect(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 0);
+ flush_render_push_buffer(rpb, &t->gl);
static f32 param = 0;
static f32 p_scale = 1;
@@ -810,14 +849,13 @@ do_terminal(Term *t, f32 dt)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- v2 ws = t->gl.window_size;
-
clear_colour(t->gl.mode & WIN_MODE_REVERSE);
glUseProgram(t->gl.programs[SHADER_POST]);
glUniform1i(t->gl.post.texslot, t->gl.fb_tex_unit);
glUniform1f(t->gl.post.param, param);
- glUniform2fv(t->gl.post.vertscale, 1, ws.E);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ push_rect(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 1);
+ flush_render_push_buffer(rpb, &t->gl);
}
#ifdef _DEBUG