96e8ea4e
Plumb text coverage controls through renderer
a73x 2026-04-09 08:05
diff --git a/shaders/cell.frag b/shaders/cell.frag index 7de861c..e793941 100644 --- a/shaders/cell.frag +++ b/shaders/cell.frag @@ -2,13 +2,25 @@ layout(binding = 0) uniform sampler2D glyph_atlas; layout(push_constant) uniform PushConstants { vec2 viewport_size; vec2 cell_size; vec2 coverage_params; } pc; layout(location = 0) in vec2 in_uv; layout(location = 1) in vec4 in_fg; layout(location = 2) in vec4 in_bg; layout(location = 0) out vec4 out_color; float shape_coverage(float alpha) { float curved = pow(alpha, pc.coverage_params.x); return clamp(curved + pc.coverage_params.y, 0.0, 1.0); } void main() { float alpha = texture(glyph_atlas, in_uv).r; alpha = shape_coverage(alpha); out_color = mix(in_bg, in_fg, alpha); } diff --git a/src/renderer.zig b/src/renderer.zig index 53e574c..1728139 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -234,6 +234,7 @@ fn createFramebuffers( pub const PushConstants = extern struct { viewport_size: [2]f32, cell_size: [2]f32, coverage_params: [2]f32, }; /// Per-vertex data (binding 0, per-vertex rate) @@ -628,7 +629,7 @@ pub const Context = struct { // Create pipeline layout (push constants + descriptor set) const push_range = vk.PushConstantRange{ .stage_flags = .{ .vertex_bit = true }, .stage_flags = .{ .vertex_bit = true, .fragment_bit = true }, .offset = 0, .size = @sizeOf(PushConstants), }; @@ -1337,6 +1338,7 @@ pub const Context = struct { instance_count: u32, cell_size: [2]f32, clear_color: [4]f32, coverage_params: [2]f32, ) !void { // Wait for previous frame to finish _ = try self.vkd.waitForFences(self.device, 1, @ptrCast(&self.in_flight_fence), .true, std.math.maxInt(u64)); @@ -1401,11 +1403,12 @@ pub const Context = struct { @floatFromInt(self.swapchain_extent.height), }, .cell_size = cell_size, .coverage_params = coverage_params, }; self.vkd.cmdPushConstants( self.command_buffer, self.pipeline_layout, .{ .vertex_bit = true }, .{ .vertex_bit = true, .fragment_bit = true }, 0, @sizeOf(PushConstants), @ptrCast(&pc), @@ -1488,6 +1491,16 @@ test "coverageVariantParams returns baseline values" { try std.testing.expectEqualDeep([2]f32{ 1.0, 0.0 }, coverageVariantParams(.baseline)); } test "PushConstants carries baseline coverage params" { const push_constants = PushConstants{ .viewport_size = .{ 1920.0, 1080.0 }, .cell_size = .{ 9.0, 18.0 }, .coverage_params = coverageVariantParams(.baseline), }; try std.testing.expectEqualDeep([2]f32{ 1.0, 0.0 }, push_constants.coverage_params); } test "coverageVariantParams steepens progressively" { const mild = coverageVariantParams(.mild); const medium = coverageVariantParams(.medium);