mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-05 19:08:17 +00:00
renderer: add custom shader cursor uniforms
Based on / supersedes PR #6912, implements discussion #6901 Co-authored-by: Krone Corylus <ahustinkrone@gmail.com>
This commit is contained in:
@@ -50,7 +50,11 @@ pub fn renderGlyph(
|
||||
const region = try canvas.writeAtlas(alloc, atlas);
|
||||
|
||||
return font.Glyph{
|
||||
.width = width,
|
||||
// HACK: Set the width for the bar cursor to just the thickness,
|
||||
// this is just for the benefit of the custom shader cursor
|
||||
// uniform code. -- In the future code will be introduced to
|
||||
// auto-crop the canvas so that this isn't needed.
|
||||
.width = if (sprite == .cursor_bar) thickness else width,
|
||||
.height = height,
|
||||
.offset_x = 0,
|
||||
.offset_y = @intCast(height),
|
||||
|
@@ -33,6 +33,8 @@ pub const cellpkg = @import("metal/cell.zig");
|
||||
pub const imagepkg = @import("metal/image.zig");
|
||||
|
||||
pub const custom_shader_target: shadertoy.Target = .msl;
|
||||
// The fragCoord for Metal shaders is +Y = down.
|
||||
pub const custom_shader_y_is_down = true;
|
||||
|
||||
/// Triple buffering.
|
||||
pub const swap_chain_count = 3;
|
||||
|
@@ -28,6 +28,8 @@ pub const cellpkg = @import("opengl/cell.zig");
|
||||
pub const imagepkg = @import("opengl/image.zig");
|
||||
|
||||
pub const custom_shader_target: shadertoy.Target = .glsl;
|
||||
// The fragCoord for OpenGL shaders is +Y = up.
|
||||
pub const custom_shader_y_is_down = false;
|
||||
|
||||
/// Because OpenGL's frame completion is always
|
||||
/// sync, we have no need for multi-buffering.
|
||||
|
@@ -675,6 +675,9 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
.mouse = @splat(0), // not currently updated
|
||||
.date = @splat(0), // not currently updated
|
||||
.sample_rate = 0, // N/A, we don't have any audio
|
||||
.current_cursor = @splat(0),
|
||||
.previous_cursor = @splat(0),
|
||||
.cursor_change_time = 0,
|
||||
},
|
||||
|
||||
// Fonts
|
||||
@@ -1966,17 +1969,70 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
|
||||
self.custom_shader_uniforms.frame += 1;
|
||||
|
||||
const screen = self.size.screen;
|
||||
const padding = self.size.padding;
|
||||
const cell = self.size.cell;
|
||||
|
||||
self.custom_shader_uniforms.resolution = .{
|
||||
@floatFromInt(self.size.screen.width),
|
||||
@floatFromInt(self.size.screen.height),
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
};
|
||||
self.custom_shader_uniforms.channel_resolution[0] = .{
|
||||
@floatFromInt(self.size.screen.width),
|
||||
@floatFromInt(self.size.screen.height),
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
0,
|
||||
};
|
||||
|
||||
// Update custom cursor uniforms, if we have a cursor.
|
||||
if (self.cells.fg_rows.lists[0].items.len > 0) {
|
||||
const cursor: shaderpkg.CellText =
|
||||
self.cells.fg_rows.lists[0].items[0];
|
||||
|
||||
const cursor_width: f32 = @floatFromInt(cursor.glyph_size[0]);
|
||||
const cursor_height: f32 = @floatFromInt(cursor.glyph_size[1]);
|
||||
|
||||
var pixel_x: f32 = @floatFromInt(
|
||||
cursor.grid_pos[0] * cell.width + padding.left,
|
||||
);
|
||||
var pixel_y: f32 = @floatFromInt(
|
||||
cursor.grid_pos[1] * cell.height + padding.top,
|
||||
);
|
||||
|
||||
pixel_x += @floatFromInt(cursor.bearings[0]);
|
||||
pixel_y += @floatFromInt(cursor.bearings[1]);
|
||||
|
||||
// If +Y is up in our shaders, we need to flip the coordinate.
|
||||
if (!GraphicsAPI.custom_shader_y_is_down) {
|
||||
pixel_y = @as(f32, @floatFromInt(screen.height)) - pixel_y;
|
||||
// We need to add the cursor height because we need the +Y
|
||||
// edge for the Y coordinate, and flipping means that it's
|
||||
// the -Y edge now.
|
||||
pixel_y += cursor_height;
|
||||
}
|
||||
|
||||
const cursor_changed: bool =
|
||||
pixel_x != self.custom_shader_uniforms.current_cursor[0] or
|
||||
pixel_y != self.custom_shader_uniforms.current_cursor[1] or
|
||||
cursor_width != self.custom_shader_uniforms.current_cursor[2] or
|
||||
cursor_height != self.custom_shader_uniforms.current_cursor[3];
|
||||
|
||||
if (cursor_changed) {
|
||||
self.custom_shader_uniforms.previous_cursor =
|
||||
self.custom_shader_uniforms.current_cursor;
|
||||
|
||||
self.custom_shader_uniforms.current_cursor = .{
|
||||
pixel_x,
|
||||
pixel_y,
|
||||
cursor_width,
|
||||
cursor_height,
|
||||
};
|
||||
|
||||
self.custom_shader_uniforms.cursor_change_time =
|
||||
self.custom_shader_uniforms.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the terminal state to GPU cells stored in CPU memory. These
|
||||
|
@@ -11,6 +11,9 @@ layout(binding = 1, std140) uniform Globals {
|
||||
uniform vec4 iMouse;
|
||||
uniform vec4 iDate;
|
||||
uniform float iSampleRate;
|
||||
uniform vec4 iCurrentCursor;
|
||||
uniform vec4 iPreviousCursor;
|
||||
uniform float iTimeCursorChange;
|
||||
};
|
||||
|
||||
layout(binding = 0) uniform sampler2D iChannel0;
|
||||
|
@@ -21,6 +21,9 @@ pub const Uniforms = extern struct {
|
||||
mouse: [4]f32 align(16),
|
||||
date: [4]f32 align(16),
|
||||
sample_rate: f32 align(4),
|
||||
current_cursor: [4]f32 align(16),
|
||||
previous_cursor: [4]f32 align(16),
|
||||
cursor_change_time: f32 align(4),
|
||||
};
|
||||
|
||||
/// The target to load shaders for.
|
||||
|
Reference in New Issue
Block a user