diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 1476b90c1..030df4834 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -452,8 +452,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal { .uniforms = .{ .projection_matrix = undefined, .cell_size = undefined, - .strikethrough_position = @floatFromInt(font_critical.metrics.strikethrough_position), - .strikethrough_thickness = @floatFromInt(font_critical.metrics.strikethrough_thickness), .min_contrast = options.config.min_contrast, }, @@ -584,8 +582,6 @@ pub fn setFontGrid(self: *Metal, grid: *font.SharedGrid) void { @floatFromInt(metrics.cell_width), @floatFromInt(metrics.cell_height), }, - .strikethrough_position = @floatFromInt(metrics.strikethrough_position), - .strikethrough_thickness = @floatFromInt(metrics.strikethrough_thickness), .min_contrast = self.uniforms.min_contrast, }; } @@ -1436,8 +1432,6 @@ pub fn setScreenSize( @floatFromInt(self.grid_metrics.cell_width), @floatFromInt(self.grid_metrics.cell_height), }, - .strikethrough_position = old.strikethrough_position, - .strikethrough_thickness = old.strikethrough_thickness, .min_contrast = old.min_contrast, }; @@ -1936,14 +1930,6 @@ fn updateCell( .glyph_size = .{ render.glyph.width, render.glyph.height }, .glyph_offset = .{ render.glyph.offset_x, render.glyph.offset_y }, }); - - // self.cells.appendAssumeCapacity(.{ - // .mode = .strikethrough, - // .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, - // .cell_width = cell.gridWidth(), - // .color = .{ colors.fg.r, colors.fg.g, colors.fg.b, alpha }, - // .bg_color = bg, - // }); } return true; diff --git a/src/renderer/metal/shaders.zig b/src/renderer/metal/shaders.zig index 5a3cd196d..d5a6baccb 100644 --- a/src/renderer/metal/shaders.zig +++ b/src/renderer/metal/shaders.zig @@ -103,7 +103,6 @@ pub const Cell = extern struct { fg = 2, fg_constrained = 3, fg_color = 7, - strikethrough = 8, }; }; @@ -124,10 +123,6 @@ pub const Uniforms = extern struct { /// Size of a single cell in pixels, unscaled. cell_size: [2]f32, - /// Metrics for underline/strikethrough - strikethrough_position: f32, - strikethrough_thickness: f32, - /// The minimum contrast ratio for text. The contrast ratio is calculated /// according to the WCAG 2.0 spec. min_contrast: f32, diff --git a/src/renderer/shaders/cell.metal b/src/renderer/shaders/cell.metal index c77447cd5..10e5804cc 100644 --- a/src/renderer/shaders/cell.metal +++ b/src/renderer/shaders/cell.metal @@ -2,54 +2,51 @@ using namespace metal; // The possible modes that a shader can take. enum Mode : uint8_t { - MODE_BG = 1u, - MODE_FG = 2u, - MODE_FG_CONSTRAINED = 3u, - MODE_FG_COLOR = 7u, - MODE_STRIKETHROUGH = 8u, + MODE_BG = 1u, + MODE_FG = 2u, + MODE_FG_CONSTRAINED = 3u, + MODE_FG_COLOR = 7u, }; struct Uniforms { float4x4 projection_matrix; float2 cell_size; - float strikethrough_position; - float strikethrough_thickness; float min_contrast; }; struct VertexIn { // The mode for this cell. - uint8_t mode [[ attribute(0) ]]; + uint8_t mode [[attribute(0)]]; // The grid coordinates (x, y) where x < columns and y < rows - float2 grid_pos [[ attribute(1) ]]; + float2 grid_pos [[attribute(1)]]; // The width of the cell in cells (i.e. 2 for double-wide). - uint8_t cell_width [[ attribute(6) ]]; + uint8_t cell_width [[attribute(6)]]; // The color. For BG modes, this is the bg color, for FG modes this is // the text color. For styles, this is the color of the style. - uchar4 color [[ attribute(5) ]]; + uchar4 color [[attribute(5)]]; // The fields below are present only when rendering text (fg mode) // The background color of the cell. This is used to determine if // we need to render the text with a different color to ensure // contrast. - uchar4 bg_color [[ attribute(7) ]]; + uchar4 bg_color [[attribute(7)]]; // The position of the glyph in the texture (x,y) - uint2 glyph_pos [[ attribute(2) ]]; + uint2 glyph_pos [[attribute(2)]]; // The size of the glyph in the texture (w,h) - uint2 glyph_size [[ attribute(3) ]]; + uint2 glyph_size [[attribute(3)]]; // The left and top bearings for the glyph (x,y) - int2 glyph_offset [[ attribute(4) ]]; + int2 glyph_offset [[attribute(4)]]; }; struct VertexOut { - float4 position [[ position ]]; + float4 position [[position]]; float2 cell_size; uint8_t mode; float4 color; @@ -63,11 +60,11 @@ struct VertexOut { // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef float luminance_component(float c) { - if (c <= 0.03928f) { - return c / 12.92f; - } else { - return pow((c + 0.055f) / 1.055f, 2.4f); - } + if (c <= 0.03928f) { + return c / 12.92f; + } else { + return pow((c + 0.055f) / 1.055f, 2.4f); + } } float relative_luminance(float3 color) { @@ -89,20 +86,20 @@ float contrast_ratio(float3 color1, float3 color2) { // return a color that satisfies the contrast ratio. Currently, the color // is always white or black, whichever has the highest contrast ratio. float4 contrasted_color(float min, float4 fg, float4 bg) { - float3 fg_premult = fg.rgb * fg.a; - float3 bg_premult = bg.rgb * bg.a; - float ratio = contrast_ratio(fg_premult, bg_premult); - if (ratio < min) { - float white_ratio = contrast_ratio(float3(1.0f), bg_premult); - float black_ratio = contrast_ratio(float3(0.0f), bg_premult); - if (white_ratio > black_ratio) { - return float4(1.0f); - } else { - return float4(0.0f, 0.0f, 0.0f, 1.0f); - } + float3 fg_premult = fg.rgb * fg.a; + float3 bg_premult = bg.rgb * bg.a; + float ratio = contrast_ratio(fg_premult, bg_premult); + if (ratio < min) { + float white_ratio = contrast_ratio(float3(1.0f), bg_premult); + float black_ratio = contrast_ratio(float3(0.0f), bg_premult); + if (white_ratio > black_ratio) { + return float4(1.0f); + } else { + return float4(0.0f, 0.0f, 0.0f, 1.0f); } + } - return fg; + return fg; } //------------------------------------------------------------------- @@ -110,11 +107,9 @@ float4 contrasted_color(float min, float4 fg, float4 bg) { //------------------------------------------------------------------- #pragma mark - Terminal Grid Cell Shader -vertex VertexOut uber_vertex( - unsigned int vid [[ vertex_id ]], - VertexIn input [[ stage_in ]], - constant Uniforms &uniforms [[ buffer(1) ]] -) { +vertex VertexOut uber_vertex(unsigned int vid [[vertex_id]], + VertexIn input [[stage_in]], + constant Uniforms& uniforms [[buffer(1)]]) { // Convert the grid x,y into world space x, y by accounting for cell size float2 cell_pos = uniforms.cell_size * input.grid_pos; @@ -141,115 +136,98 @@ vertex VertexOut uber_vertex( out.cell_size = uniforms.cell_size; out.color = float4(input.color) / 255.0f; switch (input.mode) { - case MODE_BG: - // Calculate the final position of our cell in world space. - // We have to add our cell size since our vertices are offset - // one cell up and to the left. (Do the math to verify yourself) - cell_pos = cell_pos + cell_size_scaled * position; + case MODE_BG: + // Calculate the final position of our cell in world space. + // We have to add our cell size since our vertices are offset + // one cell up and to the left. (Do the math to verify yourself) + cell_pos = cell_pos + cell_size_scaled * position; - out.position = uniforms.projection_matrix * float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f); - break; + out.position = uniforms.projection_matrix * + float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f); + break; - case MODE_FG: - case MODE_FG_CONSTRAINED: - case MODE_FG_COLOR: { - float2 glyph_size = float2(input.glyph_size); - float2 glyph_offset = float2(input.glyph_offset); + case MODE_FG: + case MODE_FG_CONSTRAINED: + case MODE_FG_COLOR: { + float2 glyph_size = float2(input.glyph_size); + float2 glyph_offset = float2(input.glyph_offset); - // The glyph_offset.y is the y bearing, a y value that when added - // to the baseline is the offset (+y is up). Our grid goes down. - // So we flip it with `cell_size.y - glyph_offset.y`. - glyph_offset.y = cell_size_scaled.y - glyph_offset.y; + // The glyph_offset.y is the y bearing, a y value that when added + // to the baseline is the offset (+y is up). Our grid goes down. + // So we flip it with `cell_size.y - glyph_offset.y`. + glyph_offset.y = cell_size_scaled.y - glyph_offset.y; - // If we're constrained then we need to scale the glyph. - // We also always constrain colored glyphs since we should have - // their scaled cell size exactly correct. - if (input.mode == MODE_FG_CONSTRAINED || input.mode == MODE_FG_COLOR) { - if (glyph_size.x > cell_size_scaled.x) { - float new_y = glyph_size.y * (cell_size_scaled.x / glyph_size.x); - glyph_offset.y += (glyph_size.y - new_y) / 2; - glyph_size.y = new_y; - glyph_size.x = cell_size_scaled.x; + // If we're constrained then we need to scale the glyph. + // We also always constrain colored glyphs since we should have + // their scaled cell size exactly correct. + if (input.mode == MODE_FG_CONSTRAINED || input.mode == MODE_FG_COLOR) { + if (glyph_size.x > cell_size_scaled.x) { + float new_y = glyph_size.y * (cell_size_scaled.x / glyph_size.x); + glyph_offset.y += (glyph_size.y - new_y) / 2; + glyph_size.y = new_y; + glyph_size.x = cell_size_scaled.x; + } } + + // Calculate the final position of the cell which uses our glyph size + // and glyph offset to create the correct bounding box for the glyph. + cell_pos = cell_pos + glyph_size * position + glyph_offset; + out.position = uniforms.projection_matrix * + float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f); + + // Calculate the texture coordinate in pixels. This is NOT normalized + // (between 0.0 and 1.0) and must be done in the fragment shader. + out.tex_coord = + float2(input.glyph_pos) + float2(input.glyph_size) * position; + + // If we have a minimum contrast, we need to check if we need to + // change the color of the text to ensure it has enough contrast + // with the background. + if (uniforms.min_contrast > 1.0f && input.mode == MODE_FG) { + float4 bg_color = float4(input.bg_color) / 255.0f; + out.color = + contrasted_color(uniforms.min_contrast, out.color, bg_color); + } + + break; } - - // Calculate the final position of the cell which uses our glyph size - // and glyph offset to create the correct bounding box for the glyph. - cell_pos = cell_pos + glyph_size * position + glyph_offset; - out.position = uniforms.projection_matrix * float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f); - - // Calculate the texture coordinate in pixels. This is NOT normalized - // (between 0.0 and 1.0) and must be done in the fragment shader. - out.tex_coord = float2(input.glyph_pos) + float2(input.glyph_size) * position; - - // If we have a minimum contrast, we need to check if we need to - // change the color of the text to ensure it has enough contrast - // with the background. - if (uniforms.min_contrast > 1.0f && input.mode == MODE_FG) { - float4 bg_color = float4(input.bg_color) / 255.0f; - out.color = contrasted_color(uniforms.min_contrast, out.color, bg_color); - } - - break; - } - - case MODE_STRIKETHROUGH: { - // Strikethrough Y value is just our thickness - float2 strikethrough_size = float2(cell_size_scaled.x, uniforms.strikethrough_thickness); - - // Position the strikethrough where we are told to - float2 strikethrough_offset = float2(cell_size_scaled.x, uniforms.strikethrough_position); - - // Go to the bottom of the cell, take away the size of the - // strikethrough, and that is our position. We also float it slightly - // above the bottom. - cell_pos = cell_pos + strikethrough_offset - (strikethrough_size * position); - - out.position = uniforms.projection_matrix * float4(cell_pos, 0.0f, 1.0); - break; - } - } return out; } -fragment float4 uber_fragment( - VertexOut in [[ stage_in ]], - texture2d textureGreyscale [[ texture(0) ]], - texture2d textureColor [[ texture(1) ]] -) { +fragment float4 uber_fragment(VertexOut in [[stage_in]], + texture2d textureGreyscale [[texture(0)]], + texture2d textureColor [[texture(1)]]) { constexpr sampler textureSampler(address::clamp_to_edge, filter::linear); switch (in.mode) { - case MODE_BG: - return in.color; + case MODE_BG: + return in.color; - case MODE_FG_CONSTRAINED: - case MODE_FG: { - // Normalize the texture coordinates to [0,1] - float2 size = float2(textureGreyscale.get_width(), textureGreyscale.get_height()); - float2 coord = in.tex_coord / size; + case MODE_FG_CONSTRAINED: + case MODE_FG: { + // Normalize the texture coordinates to [0,1] + float2 size = + float2(textureGreyscale.get_width(), textureGreyscale.get_height()); + float2 coord = in.tex_coord / size; - // We premult the alpha to our whole color since our blend function - // uses One/OneMinusSourceAlpha to avoid blurry edges. - // We first premult our given color. - float4 premult = float4(in.color.rgb * in.color.a, in.color.a); - // Then premult the texture color - float a = textureGreyscale.sample(textureSampler, coord).r; - premult = premult * a; - return premult; - } + // We premult the alpha to our whole color since our blend function + // uses One/OneMinusSourceAlpha to avoid blurry edges. + // We first premult our given color. + float4 premult = float4(in.color.rgb * in.color.a, in.color.a); + // Then premult the texture color + float a = textureGreyscale.sample(textureSampler, coord).r; + premult = premult * a; + return premult; + } - case MODE_FG_COLOR: { - // Normalize the texture coordinates to [0,1] - float2 size = float2(textureColor.get_width(), textureColor.get_height()); - float2 coord = in.tex_coord / size; - return textureColor.sample(textureSampler, coord); - } - - case MODE_STRIKETHROUGH: - return in.color; + case MODE_FG_COLOR: { + // Normalize the texture coordinates to [0,1] + float2 size = float2(textureColor.get_width(), textureColor.get_height()); + float2 coord = in.tex_coord / size; + return textureColor.sample(textureSampler, coord); + } } } @@ -261,30 +239,28 @@ fragment float4 uber_fragment( struct ImageVertexIn { // The grid coordinates (x, y) where x < columns and y < rows where // the image will be rendered. It will be rendered from the top left. - float2 grid_pos [[ attribute(1) ]]; + float2 grid_pos [[attribute(1)]]; // Offset in pixels from the top-left of the cell to make the top-left // corner of the image. - float2 cell_offset [[ attribute(2) ]]; + float2 cell_offset [[attribute(2)]]; // The source rectangle of the texture to sample from. - float4 source_rect [[ attribute(3) ]]; + float4 source_rect [[attribute(3)]]; // The final width/height of the image in pixels. - float2 dest_size [[ attribute(4) ]]; + float2 dest_size [[attribute(4)]]; }; struct ImageVertexOut { - float4 position [[ position ]]; + float4 position [[position]]; float2 tex_coord; }; -vertex ImageVertexOut image_vertex( - unsigned int vid [[ vertex_id ]], - ImageVertexIn input [[ stage_in ]], - texture2d image [[ texture(0) ]], - constant Uniforms &uniforms [[ buffer(1) ]] -) { +vertex ImageVertexOut image_vertex(unsigned int vid [[vertex_id]], + ImageVertexIn input [[stage_in]], + texture2d image [[texture(0)]], + constant Uniforms& uniforms [[buffer(1)]]) { // The size of the image in pixels float2 image_size = float2(image.get_width(), image.get_height()); @@ -315,15 +291,14 @@ vertex ImageVertexOut image_vertex( float2 image_pos = (uniforms.cell_size * input.grid_pos) + input.cell_offset; image_pos += input.dest_size * position; - out.position = uniforms.projection_matrix * float4(image_pos.x, image_pos.y, 0.0f, 1.0f); + out.position = + uniforms.projection_matrix * float4(image_pos.x, image_pos.y, 0.0f, 1.0f); out.tex_coord = tex_coord; return out; } -fragment float4 image_fragment( - ImageVertexOut in [[ stage_in ]], - texture2d image [[ texture(0) ]] -) { +fragment float4 image_fragment(ImageVertexOut in [[stage_in]], + texture2d image [[texture(0)]]) { constexpr sampler textureSampler(address::clamp_to_edge, filter::linear); // Ehhhhh our texture is in RGBA8Uint but our color attachment is @@ -344,13 +319,13 @@ fragment float4 image_fragment( #pragma mark - Post Shader struct PostVertexOut { - float4 position [[ position ]]; + float4 position [[position]]; }; -constant float2 post_pos[4] = { {-1,-1}, {1,-1}, {-1,1}, {1,1 } }; +constant float2 post_pos[4] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; -vertex PostVertexOut post_vertex(uint id [[ vertex_id ]]) { - PostVertexOut out; - out.position = float4(post_pos[id], 0, 1); - return out; +vertex PostVertexOut post_vertex(uint id [[vertex_id]]) { + PostVertexOut out; + out.position = float4(post_pos[id], 0, 1); + return out; }