fix(element): render MSDF text at the true glyph edge#8935
Merged
Conversation
A fixed 0.05 bias in the coverage remap placed the edge at sigDist ~0.525 instead of 0.5, eroding every glyph inward; at thin junctions this carved a hole in the 'f' crossbar and notches in the 'x' crossing. Render at the true edge (font_sdfIntensity 0 -> 0.5, still fattening with the same slope) and derive anti-aliasing from the distance-field gradient so edges of any orientation - including italic diagonals - anti-alias correctly. Drop the now-unused map(), font_pxrange and font_textureWidth uniforms and _getPxRange(). Fixes #2948 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build size reportThis PR changes the size of the minified bundles.
|
Contributor
Author
The coverage change removes the font_pxrange and font_textureWidth uniforms (the engine no longer sets them), changing the msdfPS chunk contract. Register msdfPS in chunkVersions so an older user override is flagged by the validator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the historical narrative from the coverage/anti-aliasing comments and describe only what the code does. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mvaligursky
approved these changes
Jun 22, 2026
mvaligursky
left a comment
Contributor
There was a problem hiding this comment.
all good, the versioning is required as well, as old chunk will no longer work (missing uniforms).
Contributor
|
Docs follow-up: added an Engine v2.20 entry to the shader chunk migrations page (covering the |
willeastcott
added a commit
that referenced
this pull request
Jun 30, 2026
…e field gradient (#8990) #8935 switched the coverage anti-aliasing to fwidth(median(sample)). On minified (small) text the atlas is undersampled, so that gradient is noisy and breathes as the text translates - small text shimmers and thin strokes (l, i, 1) flicker on and off (#8984). Derive the transition width from the uv magnification (both axes) and the atlas spread instead - the msdfgen screenPxRange approach - which depends only on geometry, so it is stable under motion and minification, floored at 1px. Keep the true-edge threshold (edge = 0.5 - 0.5*intensity) from #8935 so the #2948 crossbar fix and the rendered weight are unchanged. Re-adds the font_pxrange uniform removed by #8935 (atlas size comes from textureSize/textureDimensions); bumps the msdfPS chunk version to 2.21. Fixes #8984 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
willeastcott
added a commit
that referenced
this pull request
Jun 30, 2026
…e field gradient (#8990) #8935 switched the coverage anti-aliasing to fwidth(median(sample)). On minified (small) text the atlas is undersampled, so that gradient is noisy and breathes as the text translates - small text shimmers and thin strokes (l, i, 1) flicker on and off (#8984). Derive the transition width from the uv magnification (both axes) and the atlas spread instead - the msdfgen screenPxRange approach - which depends only on geometry, so it is stable under motion and minification, floored at 1px. Keep the true-edge threshold (edge = 0.5 - 0.5*intensity) from #8935 so the #2948 crossbar fix and the rendered weight are unchanged. Re-adds the font_pxrange uniform removed by #8935 (atlas size comes from textureSize/textureDimensions). The msdfPS chunk version is left at 2.20 on this release line. Fixes #8984 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Problem
Magnified MSDF text rendered via an
ElementComponent(text) shows a hole in thefcrossbar and notches in thexcrossing — MSDF median sign-errors at thin junctions, not aliasing.Roboto Light Italic, "fox" at fontSize 256–480 (≈ 4× the 64px atlas glyphs):
Cause
applyMsdfremapped the field withmap(0.05, …), placing the 50%-coverage threshold atsigDist ≈ 0.525instead of0.5— a fixed inward erosion of every glyph. Where the MSDF median plateaus just above 0.5 (thin crossbars / crossings) the erosion cuts through, producing the hole and notches. This is the0.05threshold @mvaligursky flagged in #2948.Separately, the AA width came from the horizontal uv derivative only (
fwidth(vUv0).x), so diagonal/italic edges were under-anti-aliased.Fix
edge = 0.5 - 0.5 * font_sdfIntensity— intensity0renders at the real edge;font_sdfIntensitystill fattens with the same slope; this also removes a latent divide-by-zeromap()had at high intensity.fwidth(sigDist)/abs(dpdx)+abs(dpdy)), correct for edges of any orientation.map(),font_pxrange/font_textureWidthuniforms and the_getPxRange()helper.GLSL and WGSL chunks kept in parity.
Compatibility
Removing the erosion means text now renders at its true (designer-intended) weight, which is marginally heavier than before. The shift is uniform and equals the erosion that was applied (≈ 0.2 atlas texels per edge). It is most visible on very thin fonts stored at low atlas resolution — the Roboto Light Italic above is near a worst case (≈ +25% stroke width, because its strokes are only ≈ 2 texels wide); most fonts will change far less. Deliberate weight adjustments should use the per-font
font_sdfIntensity(oroutlineThickness), not a global threshold bias.Because the fix removes the
font_pxrangeandfont_textureWidthuniforms from themsdfPSchunk,msdfPSis registered in the chunk-version table (API2.20) so a custom override of that chunk is flagged by the chunk validator.Testing
npm testpasses (incl. thetext-elementsuite); lint clean.Fixes #2948
Related to #830 (small-size MSDF readability): this removes the erosion and improves AA, but that issue's atlas-side asks — uniform glyph scale, sub-pixel quad placement, and a bitmap/MTSDF fallback — are out of scope here.