fix(render): filter the glyph atlas, snap chrome hairlines to pixels
Text was point-sampled (`GL_NEAREST` plus `floor(v_uv * u_tex_size)`), which at a non-integer scale *deletes* texels instead of blending them. The library's own default -- a 12 px style over the 13 px embedded bake -- dropped one of every 8 columns and one of every 17 rows of every glyph, so whole strokes went missing and which ones depended on where the unsnapped pen fell. `kTextFS` now does a 2x2 bilinear fetch clamped to the instance's own cell: the clamp keeps the no-bleed guarantee the sampler mode protects (the atlas is a tight strip of cells with no padding), and at scale 1 with a whole pen the weights are exactly 0, so it stays as crisp as the point sample. Grid and axis lines were staged in data space and mapped in the vertex shader, so a 1 px line's centre landed on an arbitrary fraction -- x = 100.0 lights two columns at half coverage, x = 100.5 lights one crisply, and a frame mixed both. `u_snap` rounds an axis-aligned segment's ink *leading edge* onto a pixel boundary, which reduces to integer+0.5 for odd widths and to an integer for even ones with no case analysis. It is on for the chrome that frames a plot and off for anything drawn at a data position, since the rounding moves a line by up to half a pixel. Diagonals are untouched. `text_pixel`'s threshold drops to 160 because filtered glyphs legitimately peak at 0.844 coverage at 12/13; the 180 threshold found text only while the sampler was also deleting a column and a row of it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
98cfc5805b
commit
525759f9a9
8 files changed
+295
-25
No files matched your search
@@ -397,7 +397,13 @@ class Renderer {
|
||||
/// crosshair passes and a dashed trace -- means **solid**. It is set on every flush,
|
||||
/// so one draw's dash can never leak into the next. The AA fringe (`u_aa`) is
|
||||
/// likewise set on every flush, from `style().line_aa_px` in device pixels.
|
||||
void flush_lines(const Mapping& map, Color color, f32 width, Vec2 dash = Vec2{}) noexcept;
|
||||
///
|
||||
/// `snap` is `LineProgram::set_snap()`'s pixel-grid rounding: on for the chrome
|
||||
/// that frames a plot -- the grid, the axis lines, a panel or legend border --
|
||||
/// and off for everything drawn at a data position, since it moves an
|
||||
/// axis-aligned line by up to half a pixel. Set on every flush, like `dash`.
|
||||
void flush_lines(const Mapping& map, Color color, f32 width, Vec2 dash = Vec2{},
|
||||
bool snap = false) noexcept;
|
||||
/// Draws every staged glyph in `batch` -- each instance carries its own tint
|
||||
/// (`a_colour`) -- and empties the batch. Text is texture-bound, so this runs
|
||||
/// once per text batch, after the line geometry it belongs over.
|
||||
|
||||
Reference in new issue
Block a user