10000 Fix text distortion on mobile devices/browsers with `glow` backend by wareya · Pull Request #6893 · emilk/egui · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix text distortion on mobile devices/browsers with glow backend #6893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 30, 2025

Conversation

wareya
Copy link
Contributor
@wareya wareya commented Apr 28, 2025

Did not test on platforms other than my phone, but I can't imagine it causing problems. AFAIK if highp isn't supported then precision highp float; needs to still not cause the program to fail to link/compile or anything; it should just silently use some other precision.

Before:
image

After:
image

Copy link

Preview available at https://egui-pr-preview.github.io/pr/6893-master
Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

@wareya
Copy link
Contributor Author
wareya commented Apr 28, 2025

Realizing that for whatever reason this makes everything look better/more even:

floorp_2025-04-28_06-50-49
floorp_2025-04-28_06-50-55

floorp_2025-04-28_06-50-07floorp_2025-04-28_06-50-01

@wareya wareya changed the title Switch egui_glow shaders from mediump to highp to fix text distortion on mobile devices Switch egui_glow shaders from mediump to highp to fix text distortion on mobile devices/browsers Apr 28, 2025
@wareya
Copy link
Contributor Author
wareya commented Apr 28, 2025

Apparently on very old drivers (that I think are violating the GLES GLSL spec) precision highp float; in fragment shaders can cause compilation to fail, so it has to be wrapped in a preprocessor define check. Done so.

@wareya
Copy link
Contributor Author
wareya commented Apr 28, 2025

The Check spelling and links / lychee CI failure is a spurious network failure.

@wareya
Copy link
Contributor Author
wareya commented Apr 29, 2025

Why this is the right solution and why possible workarounds someone might think of to make mediump work better won't actually work:

mediump usually corresponds to the standard IEEE fp16 format, which can represent all integers only in the range from -2048 to +2048. The next biggest representable number after 2048 is 2050.

Because of the logarithmic scaling of fp numbers, this applies at all scales, i.e. if you try to linearly chop up the space between -1.0 and +1.0, the finest number of chops you can get is around 4 thousand. If you try to do 8 thousand then half of the new chops will get rounded off to a chopping location you've already chopped at. From 0 to 1.0, you get half as many available chops: the next smallest number below 1.0 is ~0.9995, or more precisely it's 2047/2048. So scaling isn't a viable workaround.

If UVs ever have to be represented in a range from 0 to 1, which they do during texture sampling, then any font glyph texture atlas cannot be bigger than 2048x2048 without it becoming impossible to address specific pixels within it.

But it gets slightly worse than this. The coordinate of the first pixel of a texture is not at 0. It's at (0.5/texsize). This is because 0 corresponds to the halfway point between the first and last pixels in the texture, wrapping left. So the coordinate for the first pixel of a 2048x2048 texture, in fp16, will get rounded down by half a pixel!. So our ACTUAL pixel-addressable texture size limit with mediump is 1024x1024.

Yikes!!! 1024x1024 textures could work, but it's awful! If you're rendering text at 32x32 pixels per glyph, for example, you run out of space in the glyph atlas after only a thousand-ish characters, and need to start doing context switches to switch to another atlas! With 4096x4096 textures, you get 16 thousand-ish characters for 32x32 pixel glyphs instead. And mobile devices are WAY more likely to run into bigger and more glyph atlasses, because they're generally higher dpi than desktops. And let's say I want to render a single giant letter on a 1080x1920 screen, vertically. With a 1024x1024 atlas, doing that is literally impossible.

To clarify, all of this happens the moment the texture UV is converted into the 0.0~1.0 range to be fed into the texture() function. Nothing done beforehand can avoid it, not splitting the UV up into multiple variables or anything.

Copy link
Owner
@emilk emilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch!

But can't we just always use highp, instead of having an #if defined?

Also @Wumpf can we do the same on wgpu?

@wareya
Copy link
Contributor Author
wareya commented Apr 29, 2025

Nice catch!

But can't we just always use highp, instead of having an #if defined?

In theory, yes! But I poked around on Google and there were people running into problems on old GLES2 drivers, where they would throw a hard error if they did this without the #if defined. I looked at the GLES spec and it lists the highp version as valid syntax and the default for vertex shaders, but it doesn't specify a default for fragment shaders and it doesn't specify what should happen if they don't natively support highp. I think shader compilation errors are out of spec, but I'm not 100% sure. At the very least those drivers apparently exist and I think it's a good idea to be defensive against them.

@emilk
Copy link
Owner
emilk commented Apr 29, 2025

That makes sense! Please add that explanation to the code as a comment, so we understand why the code is written as it is 🙏

@emilk emilk added egui_glow Relates to running egui_glow on native visuals Renderings / graphics releated bug Something is broken android iOS labels Apr 29, 2025
@wareya
Copy link
Contributor Author
wareya commented Apr 29, 2025

Short explanation added as comments.

// To avoid weird distortion issues when rendering text etc, we want highp if possible.
// But apparently some devices don't support it, so we have to check first.

Copy link
Owner
@emilk emilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@emilk emilk changed the title Switch egui_glow shaders from mediump to highp to fix text distortion on mobile devices/browsers Fix text distortion on mobile devices/browsers with glow backend Apr 30, 2025
@emilk emilk added the eframe Relates to epi and eframe label Apr 30, 2025
@emilk emilk merged commit 6c922f7 into emilk:master Apr 30, 2025
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android bug Something is broken eframe Relates to epi and eframe egui_glow Relates to running egui_glow on native iOS visuals Renderings / graphics releated
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Uneven font rendering with artifacts on Firefox on Android
2 participants
0