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

feat: implement subpixel rendering #2092

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

paxcut
Copy link
Contributor

@paxcut paxcut commented Jan 29, 2025

Proof of concept for implementing subpixel processing in ImGui. This is work in progress, and it is bound to have problems.

What it does:

  1. Uses freetype own subpixel processing implementation to build a 32-bit color atlas for the default font only (no icons, no unifont) . 2) Avoids pixel perfect font conversion when possible. 3) Self contained, no ImGui source code changes.
  2. Results in much improved legibility of fonts rendered on low dpi LCD screens that use horizontal RGB pixel layouts (no BRG or OLED or CRT if they even exist anymore)

What it doesn't:

  1. Fancy class based interface. The code is barely the minimum needed to show it can work. 2) Dual source color blending. That needs to be implemented in shader code, so it needs to change ImGui source code although minimally. This will result in some characters appearing dimmer than others. Easily fixed with small fragment and vertex shaders. 3) subpixel positioning. If characters are very thin they will look colored, or they can be moved to improve legibility. 4) deal with detection of fringe cases including rare pixel layouts, non LCD screens, Mac-OS not handling subpixel rendering and any other deviation from the standard LCD. 5) tries to be efficient in speed or memory use. Font Atlases will be 4 times the size they were before, but there are no noticeable delays in font loading in the examples I have tried.

Any comments and code improvements are welcome.

paxcut and others added 7 commits January 29, 2025 06:59
Proof of concept for implementing subpixel processing in ImGui. This is work in progress, and it is bound to have problems.

What it does:
1) Uses freetype own subpixel processing implementation to build a 32-bit color atlas for the default font only (no icons, no unifont) .
2) Avoids pixel perfect font conversion when possible.
3) Self contained, no ImGui source code changes.
4) Results in much improved legibility of fonts rendered on low dpi LCD screens that use horizontal RGB pixel layouts (no BRG or OLED or CRT if they even exist anymore)

What it doesn't:
1) Fancy class based interface. The code is barely the minimum needed to show it can work.
2) Dual source color blending. That needs to be implemented in shader code, so it needs to change ImGui source code although minimally. This will result in some characters appearing dimmer than others. Easily fixed with small fragment and vertex shaders.
3) subpixel positioning. If characters are very thin they will look colored, or they can be moved to improve legibility.
4) deal with detection of fringe cases including rare pixel layouts, non LCD screens, Mac-OS not handling subpixel rendering and any other deviation from the standard LCD.
5) tries to be efficient in speed or memory use. Font Atlases will be 4 times the size they were before, but there are no noticeable delays in font loading in the examples I have tried.

Any comments and code improvements are welcome.
Icons become unaligned because the default font's descent is not calculated until the atlas is built. Atlas building must be delayed until custom rects are defined and besides, building an atlas just to obtain the descent is something that ImGui font implementation makes necessary.

All font and glyph metrics are accessible when they are loaded by specifying some desired size using the freetype api. It takes a little bit of extra code, but it is the most efficient way to obtain metrics.
The dual double loop done inside the final rendering, one to remove the padding and the other to move the data to the atlas rect have been merged into one double loop that loads the atlas data directly from the bitmap saving time and memory.
The dual glyph rasterization, one during rect creation and the other during Atlas final data write have also been made more efficient. All the bitmaps are saved into a map from rect id to bitmap.
In the debug version on my slow computer fonts load in about 4 seconds. In comparison, a nightly takes about 2 seconds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant