-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
WIP use freetype for epaint text rendering #2356
base: master
Are you sure you want to change the base?
Conversation
1afc667
to
f0dfe6a
Compare
f0dfe6a
to
d2d93af
Compare
I would like to try this, but on my Mac I get:
I'd be far more interested in trying out https://github.com/pop-os/cosmic-text for the layouting and font rendering in egui. |
d2d93af
to
cd55c99
Compare
srry i don't have a mac, just pushed a commit that maybe fix this error. |
It is possible to perform subpixel antialiasing on the entire app and without freetype: It works for all graphics, including widgets and vector drawings and even a 3D view or images: |
how do u do that? |
The subpixel AA in this post, and above, accidentally assume a BGR panel instead of RGB, oops. It is trivially reversible, and the same concepts still apply
After 14 hours of searching I can't seem to find the article that I read that explains subpixel antialiasing. But basically, you can apply it to an entire application in the exact same way that you would apply it to text. The basic idea is to render to a buffer that is three times as wide as the actual window, and then downsample it using a subpixel antialiasing filter. This can be done efficiently with a fragment shader on the GPU, and doesn't require switching the entire text rasterization backend (esp. when FreeType would be one more non-Rust dependency to build). Let me explain in more detail, since that blog post is unfortunately lost to my browsers' lack of good history search. Let's say you are trying to subpixel-antialias a lowercase The point of subpixel antialiasing is to approximate the shape better, like this: We want to find a way to use the full precision of the LCD's subpixels to achieve this, since they can theoretically achieve a horizontal resolution of three times what grayscale AA can. First, though, we need to create a rendering where what will become each subpixel is represented individually. This can be done by rendering it at 3x width: Each three columns represents what will become only one column of output. The not-quite-right approach is to try to combine them as-is - that is, for each set of three columns, take the red channel from the left column, the green channel from the center column, and the blue channel from the right column. (And vice versa for BGR panels) This results in: But this is obviously too intense - for example, there is bright yellow to the left side. We're only missing one step, though. The trick is to average all pixels with their horizontal neighbors, so that the color fringing is less pronounced. That results in this rendering: and this subpixel-antialiased result: This approach is very easily generalizable - it can be applied to much more than just text. Here it is applied to this GitHub issue: Notice how not only is the text subpixel-antialiased, but everything is - border radii, emoji, your profile picture, icons and solid shapes. However, this reveals an issue with my implementation - solid pixels bordered by other solid pixels bleed into each other by one subpixel. I'm sure this can be fixed somehow - and I've tried not taking into account neighboring full-pixels - but I just can't seem to get a result as good as what I've shown so far. As always, more research is needed. (It took me four hours to compose this comment lol) |
thanks so much for the detailed reply! |
implemented subpixel AA using freetype, this PR is working but still need to make freetype a optional dependency, maybe controled by a feature tag?
related issue #2354