a73x

96e8ea4e

Plumb text coverage controls through renderer

a73x   2026-04-09 08:05

Commit message
Plumb text coverage controls through renderer

shaders/cell.frag
Old New
@@ -2,13 +2,25 @@
2 2
3 layout(binding = 0) uniform sampler2D glyph_atlas; 3 layout(binding = 0) uniform sampler2D glyph_atlas;
4 4
5 layout(push_constant) uniform PushConstants {
6 vec2 viewport_size;
7 vec2 cell_size;
8 vec2 coverage_params;
9 } pc;
10
5 layout(location = 0) in vec2 in_uv; 11 layout(location = 0) in vec2 in_uv;
6 layout(location = 1) in vec4 in_fg; 12 layout(location = 1) in vec4 in_fg;
7 layout(location = 2) in vec4 in_bg; 13 layout(location = 2) in vec4 in_bg;
8 14
9 layout(location = 0) out vec4 out_color; 15 layout(location = 0) out vec4 out_color;
10 16
17 float shape_coverage(float alpha) {
18 float curved = pow(alpha, pc.coverage_params.x);
19 return clamp(curved + pc.coverage_params.y, 0.0, 1.0);
20 }
21
11 void main() { 22 void main() {
12 float alpha = texture(glyph_atlas, in_uv).r; 23 float alpha = texture(glyph_atlas, in_uv).r;
24 alpha = shape_coverage(alpha);
13 out_color = mix(in_bg, in_fg, alpha); 25 out_color = mix(in_bg, in_fg, alpha);
14 } 26 }
src/renderer.zig
Old New
@@ -234,6 +234,7 @@ fn createFramebuffers(
234 pub const PushConstants = extern struct { 234 pub const PushConstants = extern struct {
235 viewport_size: [2]f32, 235 viewport_size: [2]f32,
236 cell_size: [2]f32, 236 cell_size: [2]f32,
237 coverage_params: [2]f32,
237 }; 238 };
238 239
239 /// Per-vertex data (binding 0, per-vertex rate) 240 /// Per-vertex data (binding 0, per-vertex rate)
@@ -628,7 +629,7 @@ pub const Context = struct {
628 629
629 // Create pipeline layout (push constants + descriptor set) 630 // Create pipeline layout (push constants + descriptor set)
630 const push_range = vk.PushConstantRange{ 631 const push_range = vk.PushConstantRange{
631 .stage_flags = .{ .vertex_bit = true }, 632 .stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
632 .offset = 0, 633 .offset = 0,
633 .size = @sizeOf(PushConstants), 634 .size = @sizeOf(PushConstants),
634 }; 635 };
@@ -1337,6 +1338,7 @@ pub const Context = struct {
1337 instance_count: u32, 1338 instance_count: u32,
1338 cell_size: [2]f32, 1339 cell_size: [2]f32,
1339 clear_color: [4]f32, 1340 clear_color: [4]f32,
1341 coverage_params: [2]f32,
1340 ) !void { 1342 ) !void {
1341 // Wait for previous frame to finish 1343 // Wait for previous frame to finish
1342 _ = try self.vkd.waitForFences(self.device, 1, @ptrCast(&self.in_flight_fence), .true, std.math.maxInt(u64)); 1344 _ = 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 {
1401 @floatFromInt(self.swapchain_extent.height), 1403 @floatFromInt(self.swapchain_extent.height),
1402 }, 1404 },
1403 .cell_size = cell_size, 1405 .cell_size = cell_size,
1406 .coverage_params = coverage_params,
1404 }; 1407 };
1405 self.vkd.cmdPushConstants( 1408 self.vkd.cmdPushConstants(
1406 self.command_buffer, 1409 self.command_buffer,
1407 self.pipeline_layout, 1410 self.pipeline_layout,
1408 .{ .vertex_bit = true }, 1411 .{ .vertex_bit = true, .fragment_bit = true },
1409 0, 1412 0,
1410 @sizeOf(PushConstants), 1413 @sizeOf(PushConstants),
1411 @ptrCast(&pc), 1414 @ptrCast(&pc),
@@ -1488,6 +1491,16 @@ test "coverageVariantParams returns baseline values" {
1488 try std.testing.expectEqualDeep([2]f32{ 1.0, 0.0 }, coverageVariantParams(.baseline)); 1491 try std.testing.expectEqualDeep([2]f32{ 1.0, 0.0 }, coverageVariantParams(.baseline));
1489 } 1492 }
1490 1493
1494 test "PushConstants carries baseline coverage params" {
1495 const push_constants = PushConstants{
1496 .viewport_size = .{ 1920.0, 1080.0 },
1497 .cell_size = .{ 9.0, 18.0 },
1498 .coverage_params = coverageVariantParams(.baseline),
1499 };
1500
1501 try std.testing.expectEqualDeep([2]f32{ 1.0, 0.0 }, push_constants.coverage_params);
1502 }
1503
1491 test "coverageVariantParams steepens progressively" { 1504 test "coverageVariantParams steepens progressively" {
1492 const mild = coverageVariantParams(.mild); 1505 const mild = coverageVariantParams(.mild);
1493 const medium = coverageVariantParams(.medium); 1506 const medium = coverageVariantParams(.medium);