Skip to content
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

Font aliasing on web (dark mode) #516

Closed
ShadowJonathan opened this issue Jun 25, 2021 · 15 comments · Fixed by #640
Closed

Font aliasing on web (dark mode) #516

ShadowJonathan opened this issue Jun 25, 2021 · 15 comments · Fixed by #640
Labels
web Related to running Egui on the web

Comments

@ShadowJonathan
Copy link

image

Browser version: Version 1.25.73 Chromium: 91.0.4472.106 (Official Build) (64-bit)

OS: PopOS 20.10

@crumblingstatue
Copy link
Contributor

I get the same behavior. Something has regressed since last version.

@EmbersArc
Copy link
Contributor

EmbersArc commented Jun 25, 2021

Looks like this both in Firefox and Chromium based browsers on Linux. It looks fine on mobile, probably because of the higher dpi.

Another thing pointing toward alpha blending to be the issue is that the slightly transparent parts of the plot disappear almost completely in the web version.

Here are the native and web versions side by side:

Screenshot_20210625_010450

@parasyte
Copy link
Contributor

It also appears this way in Edge 91 on Windows 10. The issue is limited to the egui_web build.

git bisect found effd3c7, which makes perfect sense.

Updated 2 paths from the index
effd3c7440d9f70c0eff677871a60be539cf1113 is the first bad commit
commit effd3c7440d9f70c0eff677871a60be539cf1113
Author: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Date:   Fri Jun 4 23:03:48 2021 +0200

    egui_web: Vastly improve WebGL alpha blending

    This finally fixes the rough edges on text, especially in light mode

 egui_web/CHANGELOG.md                   |  1 +
 egui_web/src/shader/fragment_100es.glsl | 23 ++++++++++++++++++-----
 egui_web/src/shader/fragment_300es.glsl | 23 ++++++++++++++++++-----
 3 files changed, 37 insertions(+), 10 deletions(-)

This work was done in response to #454

@parasyte
Copy link
Contributor

To be honest, the light theme really does look a lot better with that patch, but it still breaks blending unfortunately. See before and after with the light theme:

egui-light-before

egui-light-after

@EmbersArc
Copy link
Contributor

I did some testing and it's this line that has a very negative effect:

gl_FragColor.a *= sqrt(gl_FragColor.a);

@ShadowJonathan
Copy link
Author

(Thanks for the quick responses!)

@ShadowJonathan ShadowJonathan changed the title Font aliasing on linux Font aliasing on web (dark mode) Jun 26, 2021
@X-Ryl669
Copy link

X-Ryl669 commented Jul 2, 2021

I did some testing and it's this line that has a very negative effect:

gl_FragColor.a *= sqrt(gl_FragColor.a);

If I understand the code correctly, this compute a raised to the power of 1.5 for light mode. It's a magic number that seems to break for other theme. If I'm right, change that line to gl_FragColor.a = pow(gl_FragColor.a, 1/1.5) and it should be better on dark themes, since it'll use the inverted power for alpha blending.

@emilk
Copy link
Owner

emilk commented Jul 6, 2021

The web renderer has always had a problem with pixel perfection (aligning a html canvas to the physical pixel grid is something I haven't yet figured out), which has lead to slightly blurry text in some cases. In egui 0.13 I changed (improved) the gamma curve in the web renderer, which makes fonts slightly thinner. This makes the pixel-imperfection/blurryness much more noticeable.

So: the best fix would be to figure out how to perfectly position a webgl canvas. Alternatively, we make the fonts thicker again to cover up the problem.

@EmbersArc
Copy link
Contributor

EmbersArc commented Jul 6, 2021

Really fixing it may take some more effort, but in the meantime I'd suggest removing the line with the blending tweak since it has a very negative effect on the visuals for both themes. If the shadows look too dark in light mode then we should probably fix this in a different way.

We could also consider @X-Ryl669's tweak gl_FragColor.a = pow(gl_FragColor.a, 1/1.5), in my opinion it has a positive effect on both themes (again except for the shadows in the light theme).

Light mode with the current tweak and without:
Screenshot_20210706_205150
Screenshot_20210706_205226

Dark mode with tweak and without:
Also note that the filled area in the plot is almost gone with the tweak
Screenshot_20210706_204954
Screenshot_20210706_205053

@ShadowJonathan
Copy link
Author

imo, the "without the tweak" variant looks much less weird to me.

(also lol that plot)

@parasyte
Copy link
Contributor

parasyte commented Jul 7, 2021

If we're just going to throw around empirically derived numbers, I think gl_FragColor.a = pow(gl_FragColor.a, 1/1.5) produces colors that look reasonable, IMO.

It creates a wild curve with dark tones, which you can see in the shadows on the light theme. But the curve is less pronounced than multiplying (!) by the square root.

@X-Ryl669
Copy link

X-Ryl669 commented Jul 7, 2021

Honestly, changing gamma is just a hack. One should match what the monitor's gamma is showing here, not rely on hardcoded numbers. Also a * sqrt(a) = a^1.5 = pow(a, 1.5). Depending on your monitor gamma level, it can be better or worse. My tweak is simply to undo the monitor's gamma a bit (a monitor performs x^1.8 or x^2.1 depending if it's a Mac or Windows), so if you want to be pseudolinear here on the output, you must perform (x^1/1.8) first, or (x^1/2.1) so that the actually displayed value is x.

The right fix is to either not rely on gamma at all (that is, try to avoid as much as possible antialiasing/alpha blending with different color) by using larger font or bitmap font, or query the monitor's gamma, invert it, perform your aliasing with the anti-gamma value and let the monitor reapply the gamma correctly.

@emilk
Copy link
Owner

emilk commented Jul 7, 2021

It might also be possible to get linear blending when rendering to a texture in WebGL instead of rendering directly to the framebuffer, but I haven't tried it.

@billyswong
Copy link

Hi maybe "make the fonts thicker" is actually a proper solution! I came across an article in https://www.freetype.org/freetype2/docs/hinting/text-rendering-general.html

Assume we render fonts correctly. Gamma correction essentially lightens fonts since shades of gray are shifted to higher pixel values (corresponding to higher brightness) to match the original intention to the reality of our screens. The side-effect is that glyphs that were rendered incorrectly but fairly readable suddenly thin out. Correctly rendered but hard-to-read text doesn’t do anyone a favor. So Mac OS X and Adobe’s proprietary font engine implement a counter-measure: stem darkening at smaller sizes where shades of gray dominate. By emboldening a glyph slightly in relation to its pixel size, individual pixels get higher coverage of filled-in outlines and are therefore blacker. This increases contrast and prevents thinning out of glyphs. Text remains readable at smaller sizes.

So making the line / font thicker is actually what the big companies and big open source projects did.

@parasyte
Copy link
Contributor

That's exactly what I did for an app I'm working on, but for different reasons. Even when font rendering is not terrible (see egui_glium) a dark font on a light background looks worse than the same font with a light color on a dark background. I switched to a slightly heavy font weight for the light theme to make it appear roughly the same thickness on both.

This issue is a bit different, because the gamma curves are way off. You can see it mostly where alpha < 1.0.

@emilk emilk added the web Related to running Egui on the web label Aug 15, 2021
emilk added a commit that referenced this issue Aug 20, 2021
emilk added a