Enable depth buffer, add depth to shader

This commit is contained in:
Mitchell Hashimoto
2022-08-19 10:07:30 -07:00
parent a36ae221ae
commit 390d95a5af
3 changed files with 45 additions and 7 deletions

View File

@ -35,6 +35,17 @@ layout (location = 5) in vec4 bg_color_in;
// the entire terminal grid in a single GPU pass. // the entire terminal grid in a single GPU pass.
layout (location = 6) in uint mode_in; layout (location = 6) in uint mode_in;
// The Z-depth. This is between 0.0 and 1.0. This is used to paint newer
// values on top of older ones to limit the amount of data that needs to
// be sent to the GPU.
//
// 0 is further back/away, 1 is front/near
//
// TODO: It would be better to just send the Z value as part of grid_coord
// and normalize it to NDC and then linearly transform it but this was easy
// to get going more quickly.
layout (location = 7) in float grid_z;
// The background or foreground color for the fragment, depending on // The background or foreground color for the fragment, depending on
// whether this is a background or foreground pass. // whether this is a background or foreground pass.
flat out vec4 color; flat out vec4 color;
@ -82,6 +93,11 @@ void main() {
// Example: (1,0) with a 30 wide cell is converted to (30,0) // Example: (1,0) with a 30 wide cell is converted to (30,0)
vec2 cell_pos = cell_size * grid_coord; vec2 cell_pos = cell_size * grid_coord;
// Our Z value. For now we just use grid_z directly but we pull it
// out here so the variable name is more uniform to our cell_pos and
// in case we want to do any other math later.
float cell_z = grid_z;
// Turn the cell position into a vertex point depending on the // Turn the cell position into a vertex point depending on the
// gl_VertexID. Since we use instanced drawing, we have 4 vertices // gl_VertexID. Since we use instanced drawing, we have 4 vertices
// for each corner of the cell. We can use gl_VertexID to determine // for each corner of the cell. We can use gl_VertexID to determine
@ -103,7 +119,7 @@ void main() {
// one cell up and to the left. (Do the math to verify yourself) // one cell up and to the left. (Do the math to verify yourself)
cell_pos = cell_pos + cell_size * position; cell_pos = cell_pos + cell_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = bg_color_in / 255.0; color = bg_color_in / 255.0;
break; break;
@ -117,7 +133,7 @@ void main() {
// Calculate the final position of the cell. // Calculate the final position of the cell.
cell_pos = cell_pos + glyph_size * position + glyph_offset_calc; cell_pos = cell_pos + glyph_size * position + glyph_offset_calc;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
// We need to convert our texture position and size to normalized // We need to convert our texture position and size to normalized
// device coordinates (0 to 1.0) by dividing by the size of the texture. // device coordinates (0 to 1.0) by dividing by the size of the texture.
@ -134,7 +150,7 @@ void main() {
// Same as background since we're taking up the whole cell. // Same as background since we're taking up the whole cell.
cell_pos = cell_pos + cell_size * position; cell_pos = cell_pos + cell_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = bg_color_in / 255.0; color = bg_color_in / 255.0;
break; break;
@ -145,7 +161,7 @@ void main() {
// Same as background since we're taking up the whole cell. // Same as background since we're taking up the whole cell.
cell_pos = cell_pos + cell_size * position; cell_pos = cell_pos + cell_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = bg_color_in / 255.0; color = bg_color_in / 255.0;
break; break;
@ -156,7 +172,7 @@ void main() {
// Same as background since we're taking up the whole cell. // Same as background since we're taking up the whole cell.
cell_pos = cell_pos + bar_size * position; cell_pos = cell_pos + bar_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = bg_color_in / 255.0; color = bg_color_in / 255.0;
break; break;
@ -174,7 +190,7 @@ void main() {
// above the bottom. // above the bottom.
cell_pos = cell_pos + underline_offset - underline_size * position; cell_pos = cell_pos + underline_offset - underline_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = fg_color_in / 255.0; color = fg_color_in / 255.0;
break; break;
} }

View File

@ -100,6 +100,10 @@ const GPUCell = struct {
/// uint mode /// uint mode
mode: u8, mode: u8,
/// float grid_z. This is normalized to a float by dividing by the
/// max int value.
grid_z: u16,
}; };
pub fn init(alloc: Allocator, config: *const Config) !Grid { pub fn init(alloc: Allocator, config: *const Config) !Grid {
@ -198,6 +202,8 @@ pub fn init(alloc: Allocator, config: *const Config) !Grid {
try vbobind.attributeAdvanced(5, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset); try vbobind.attributeAdvanced(5, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset);
offset += 4 * @sizeOf(u8); offset += 4 * @sizeOf(u8);
try vbobind.attributeIAdvanced(6, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset); try vbobind.attributeIAdvanced(6, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset);
offset += 1 * @sizeOf(u8);
try vbobind.attributeAdvanced(7, 1, gl.c.GL_UNSIGNED_SHORT, true, @sizeOf(GPUCell), offset);
try vbobind.enableAttribArray(0); try vbobind.enableAttribArray(0);
try vbobind.enableAttribArray(1); try vbobind.enableAttribArray(1);
try vbobind.enableAttribArray(2); try vbobind.enableAttribArray(2);
@ -205,6 +211,7 @@ pub fn init(alloc: Allocator, config: *const Config) !Grid {
try vbobind.enableAttribArray(4); try vbobind.enableAttribArray(4);
try vbobind.enableAttribArray(5); try vbobind.enableAttribArray(5);
try vbobind.enableAttribArray(6); try vbobind.enableAttribArray(6);
try vbobind.enableAttribArray(7);
try vbobind.attributeDivisor(0, 1); try vbobind.attributeDivisor(0, 1);
try vbobind.attributeDivisor(1, 1); try vbobind.attributeDivisor(1, 1);
try vbobind.attributeDivisor(2, 1); try vbobind.attributeDivisor(2, 1);
@ -212,6 +219,7 @@ pub fn init(alloc: Allocator, config: *const Config) !Grid {
try vbobind.attributeDivisor(4, 1); try vbobind.attributeDivisor(4, 1);
try vbobind.attributeDivisor(5, 1); try vbobind.attributeDivisor(5, 1);
try vbobind.attributeDivisor(6, 1); try vbobind.attributeDivisor(6, 1);
try vbobind.attributeDivisor(7, 1);
// Build our texture // Build our texture
const tex = try gl.Texture.create(); const tex = try gl.Texture.create();
@ -342,6 +350,7 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.mode = 1, .mode = 1,
.grid_col = @intCast(u16, x), .grid_col = @intCast(u16, x),
.grid_row = @intCast(u16, y), .grid_row = @intCast(u16, y),
.grid_z = 0,
.glyph_x = 0, .glyph_x = 0,
.glyph_y = 0, .glyph_y = 0,
.glyph_width = 0, .glyph_width = 0,
@ -380,6 +389,7 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.mode = 2, .mode = 2,
.grid_col = @intCast(u16, x), .grid_col = @intCast(u16, x),
.grid_row = @intCast(u16, y), .grid_row = @intCast(u16, y),
.grid_z = 1,
.glyph_x = glyph.atlas_x, .glyph_x = glyph.atlas_x,
.glyph_y = glyph.atlas_y, .glyph_y = glyph.atlas_y,
.glyph_width = glyph.width, .glyph_width = glyph.width,
@ -402,6 +412,7 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.mode = 6, // underline .mode = 6, // underline
.grid_col = @intCast(u16, x), .grid_col = @intCast(u16, x),
.grid_row = @intCast(u16, y), .grid_row = @intCast(u16, y),
.grid_z = 1,
.glyph_x = 0, .glyph_x = 0,
.glyph_y = 0, .glyph_y = 0,
.glyph_width = 0, .glyph_width = 0,
@ -435,6 +446,9 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.bg_g = 0xFF, .bg_g = 0xFF,
.bg_b = 0xFF, .bg_b = 0xFF,
.bg_a = 255, .bg_a = 255,
// The cursor is always at the very front
.grid_z = 255,
}); });
} }
} }

View File

@ -200,6 +200,14 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
gl.c.glEnable(gl.c.GL_BLEND); gl.c.glEnable(gl.c.GL_BLEND);
gl.c.glBlendFunc(gl.c.GL_SRC_ALPHA, gl.c.GL_ONE_MINUS_SRC_ALPHA); gl.c.glBlendFunc(gl.c.GL_SRC_ALPHA, gl.c.GL_ONE_MINUS_SRC_ALPHA);
// Depth test since we use the Z-buffer as an optimization to send
// only changed cells to the GPU. As cells are updated, we bump their
// Z value to be closer, so that over time new values are rendered "over"
// values (in reality old values are culled by the depth test, so they
// aren't ever "rendered").
gl.c.glEnable(gl.c.GL_DEPTH_TEST);
gl.c.glDepthFunc(gl.c.GL_LESS);
// Create our terminal grid with the initial window size // Create our terminal grid with the initial window size
const window_size = try window.getSize(); const window_size = try window.getSize();
var grid = try Grid.init(alloc, config); var grid = try Grid.init(alloc, config);
@ -960,7 +968,7 @@ fn renderTimerCallback(t: *libuv.Timer) void {
.a = win.bg_a, .a = win.bg_a,
}; };
gl.clearColor(gl_bg.r, gl_bg.g, gl_bg.b, gl_bg.a); gl.clearColor(gl_bg.r, gl_bg.g, gl_bg.b, gl_bg.a);
gl.clear(gl.c.GL_COLOR_BUFFER_BIT); gl.clear(gl.c.GL_COLOR_BUFFER_BIT | gl.c.GL_DEPTH_BUFFER_BIT);
// Update the cells for drawing // Update the cells for drawing
win.grid.updateCells(win.terminal) catch |err| win.grid.updateCells(win.terminal) catch |err|