You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MSDF font atlas textures are loaded with mipmaps enabled (mipmaps: true, minFilter: FILTER_LINEAR_MIPMAP_LINEAR). Mipmapping is wrong for MSDF: each mip level box-averages the R/G/B channels, but median(average) != average(median), so under minification the shader samples a corrupted median. This shows as faint ghost/flicker artifacts on small text — e.g. a thin horizontal line that flickers on and off just below closely-spaced stems (the ll in "Hello") as the text moves. Most visible at small fontSize and DPR 1 / non-HiDPI.
Why it's visible now
Latent for a long time (the atlas has always been mipmapped), but surfaced by #8990, which renders MSDF text at the true glyph edge (threshold 0.5). The previous inward erosion (~0.525 plus the (m-0.05)/0.95 remap) had kept the faint corrupted-median values below the render threshold. Related to #8984.
Repro
MSDF font (e.g. store Roboto), ElementComponent text, small fontSize (~6), useDevicePixelRatio: false (DPR 1 makes it much easier to see), text translating sub-pixel.
A faint horizontal line flickers below the ll. Forcing the atlas to sample the base level only (no mipmaps) eliminates it, without making small text look worse.
Fix direction / constraints
Load MSDF atlases at the base level only — mipmaps: false + minFilter: FILTER_LINEAR (bitmap fonts should keep their mipmaps). Two things make this non-trivial:
Must be set at texture creation, not mutated after load. On WebGPU Texture#mipmaps can't be changed after creation (the setter warns and keeps the mip chain), and the WebGPU sampler sets no lodMaxClamp, so even a non-mip minFilter still minifies into the chain — the artifact persists unless the mip chain doesn't exist.
No clean creation-options channel. Font atlas textures load via loader.load(url, 'texture', cb) with no asset, so there's currently no tidy way to pass creation options (mipmaps/minFilter) through to the texture handler. fix(font): disable mipmaps on MSDF font atlases #8996 attempted to add one by threading an options arg through ResourceHandler.open but that was rejected (too broad / public-API surface). The clean channel is the open design question.
Summary
MSDF font atlas textures are loaded with mipmaps enabled (
mipmaps: true,minFilter: FILTER_LINEAR_MIPMAP_LINEAR). Mipmapping is wrong for MSDF: each mip level box-averages the R/G/B channels, butmedian(average) != average(median), so under minification the shader samples a corrupted median. This shows as faint ghost/flicker artifacts on small text — e.g. a thin horizontal line that flickers on and off just below closely-spaced stems (thellin "Hello") as the text moves. Most visible at smallfontSizeand DPR 1 / non-HiDPI.Why it's visible now
Latent for a long time (the atlas has always been mipmapped), but surfaced by #8990, which renders MSDF text at the true glyph edge (threshold
0.5). The previous inward erosion (~0.525plus the(m-0.05)/0.95remap) had kept the faint corrupted-median values below the render threshold. Related to #8984.Repro
ElementComponenttext, smallfontSize(~6),useDevicePixelRatio: false(DPR 1 makes it much easier to see), text translating sub-pixel.ll. Forcing the atlas to sample the base level only (no mipmaps) eliminates it, without making small text look worse.Fix direction / constraints
Load MSDF atlases at the base level only —
mipmaps: false+minFilter: FILTER_LINEAR(bitmap fonts should keep their mipmaps). Two things make this non-trivial:Texture#mipmapscan't be changed after creation (the setter warns and keeps the mip chain), and the WebGPU sampler sets nolodMaxClamp, so even a non-mipminFilterstill minifies into the chain — the artifact persists unless the mip chain doesn't exist.loader.load(url, 'texture', cb)with no asset, so there's currently no tidy way to pass creation options (mipmaps/minFilter) through to the texture handler. fix(font): disable mipmaps on MSDF font atlases #8996 attempted to add one by threading anoptionsarg throughResourceHandler.openbut that was rejected (too broad / public-API surface). The clean channel is the open design question.Closed attempt: #8996.