feat(text): suppress glyph strokes when SDF text is on

With OCS_TEXT_SDF set, text now renders only as SDF quads: the wire path
skips building glyph-stroke geometry (bins stays empty, so the existing
empty-wire branch still emits the insertion snap point). This removes the
double draw (strokes + SDF) and, as a side effect, fixes the long-standing
snap pollution (#276) — snapping near text no longer catches individual
glyph-stroke endpoints, only the insertion point.

Shared sdf_text_enabled() (cached env read) gates both the collector and
the stroke suppression so they stay in lock-step. Flag off: unchanged.

Verified in-app: TEXT/MTEXT/decorations render clean as single SDF, and
snap no longer hits glyph strokes. Click-pick on text is limited while the
flag is on (no stroke geometry) pending a text OBB pick box.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-07 08:18:08 +03:00
1 parent 1709d41e4f
commit 9f60470067
3 files changed
+16 -2

No files matched your search

+7 -1
View File
@@ -198,7 +198,13 @@ pub fn tessellate(
};
let anno = anno_scale as f64;
for group in &stroke_groups {
// With SDF text on, glyphs render as quads elsewhere — skip
// building the stroke geometry so text is not double-drawn.
// `bins` stays empty, so the empty-wire path below still emits
// the insertion snap point (text stays snappable, no glyph
// strokes polluting snap/pick).
let sdf_text = crate::scene::text::sdf_atlas::sdf_text_enabled();
for group in stroke_groups.iter().filter(|_| !sdf_text) {
let lx_v = group.origin[0];
let ly_v = group.origin[1];
let slx_v = (lx_v - ref_lx_v) * anno + ref_lx_v;
+8
View File
@@ -39,6 +39,14 @@ pub fn text_atlas() -> &'static Mutex<GlyphAtlas> {
ATLAS.get_or_init(|| Mutex::new(GlyphAtlas::new(1024, 1024)))
}
/// Whether SDF text rendering is enabled (env `OCS_TEXT_SDF`), read once.
/// When on, the wire path suppresses text glyph strokes so text draws only as
/// SDF quads (no double draw); the insertion snap point is kept.
pub fn sdf_text_enabled() -> bool {
static ON: OnceLock<bool> = OnceLock::new();
*ON.get_or_init(|| std::env::var_os("OCS_TEXT_SDF").is_some())
}
// ── Bake configuration ──────────────────────────────────────────────────────
/// Texels per glyph unit. Glyphs live in a 9-unit cap-height space, so a cap
+1 -1
View File
@@ -784,7 +784,7 @@ impl Scene {
pub(in crate::scene) fn sdf_text_vertices(
&self,
) -> Vec<crate::scene::pipeline::text_gpu::TextVertex> {
self.sdf_text_vertices_enabled(std::env::var_os("OCS_TEXT_SDF").is_some())
self.sdf_text_vertices_enabled(crate::scene::text::sdf_atlas::sdf_text_enabled())
}
#[allow(dead_code)]