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

Fonts #5301

Closed
noisewuwei opened this issue May 9, 2022 · 16 comments
Closed

Fonts #5301

noisewuwei opened this issue May 9, 2022 · 16 comments

Comments

@noisewuwei
Copy link
Contributor

Platform: Mac OS
Backend: Metal

Why is the Chinese displayed so vague?

d546d0432a435cd911fb115648bb2c6a

@rokups
Copy link
Contributor

rokups commented May 9, 2022

Could you describe what you mean by "vague"?

@celestialemily
Copy link

@rokups I think he is talking about the slight blurriness of the characters, for this I would probably assume DPI scaling or AA.

@ocornut
Copy link
Owner

ocornut commented May 9, 2022 via email

@noisewuwei
Copy link
Contributor Author

Could you describe what you mean by "vague"?

Sorry.I mean the text is not distinct.

@rokups
Copy link
Contributor

rokups commented May 10, 2022

Issue with MacOS is that it pretends screen has 2x less pixels than it actually does. This simplifies application development in most cases, but in our case we happen to render fonts at 1x scale while screen renders at 2x scale. You can cheat a little:

CGFloat scale = NSScreen.mainScreen.backingScaleFactor;
ImFontConfig cfg;
cfg.SizePixels = 13.0f * scale;
io.Fonts->AddFontDefault(&cfg);
io.FontGlobalScale = 1.0f / scale;

cfg.SizePixels = 13.0f * scale;

This rasterizes default font at 2x scale (assuming your retina screen scale is 2x, most of them are i think) (13.0f is default size of default font).

io.FontGlobalScale = 1.0f / scale;

And this renders fonts at half a scale.

Here we worked around scaling issues by rasterizing fonts at twice size, but also reduce rendered fonts by half so they visually look same, except crisper (font atlas pixel matches physical pixel on the screen).

@noisewuwei
Copy link
Contributor Author

Our font rendering is not as good as OS ones for two mains reasons (but not only that): - stb_truetype doesn’t handle font hinting. For <4k resolutions and “small sizes” this is rather noticeable. Using imgui_freetype can noticeably improve rendering and you can do this today. - We don’t support sub-pixel rendering (there is an experimental pull request for that) which is a technique taking advantage of particular LCD/screen layout where typically a pixel is often composed of 3 R/G/B subpixels which are treated separately, effectively tripling horizontal resolution. This is what most OS rendering are using and this is why when you look closely at text you may notice r/g/b fringe bleeding. For a small you can look at imgui_freetype to improve rendering quality.

OK.I will have a try.

@noisewuwei
Copy link
Contributor Author

Issue with MacOS is that it pretends screen has 2x less pixels than it actually does. This simplifies application development in most cases, but in our case we happen to render fonts at 1x scale while screen renders at 2x scale. You can cheat a little:

CGFloat scale = NSScreen.mainScreen.backingScaleFactor;
ImFontConfig cfg;
cfg.SizePixels = 13.0f * scale;
io.Fonts->AddFontDefault(&cfg);
io.FontGlobalScale = 1.0f / scale;

cfg.SizePixels = 13.0f * scale;

This rasterizes default font at 2x scale (assuming your retina screen scale is 2x, most of them are i think) (13.0f is default size of default font).

io.FontGlobalScale = 1.0f / scale;

And this renders fonts at half a scale.

Here we worked around scaling issues by rasterizing fonts at twice size, but also reduce rendered fonts by half so they visually look same, except crisper (font atlas pixel matches physical pixel on the screen).

Thanks.I will have a try.

@noisewuwei
Copy link
Contributor Author

Issue with MacOS is that it pretends screen has 2x less pixels than it actually does. This simplifies application development in most cases, but in our case we happen to render fonts at 1x scale while screen renders at 2x scale. You can cheat a little:

CGFloat scale = NSScreen.mainScreen.backingScaleFactor;
ImFontConfig cfg;
cfg.SizePixels = 13.0f * scale;
io.Fonts->AddFontDefault(&cfg);
io.FontGlobalScale = 1.0f / scale;

cfg.SizePixels = 13.0f * scale;

This rasterizes default font at 2x scale (assuming your retina screen scale is 2x, most of them are i think) (13.0f is default size of default font).

io.FontGlobalScale = 1.0f / scale;

And this renders fonts at half a scale.

Here we worked around scaling issues by rasterizing fonts at twice size, but also reduce rendered fonts by half so they visually look same, except crisper (font atlas pixel matches physical pixel on the screen).

It seems to work.Thanks.

@parbo
Copy link

parbo commented Aug 22, 2022

I'm trying this workaround to get crisper fonts, and it kind of works. However, if I scale the fonts by more than 1.8 or so, the font textures seem to become all black. Any ideas why that would happen?

@parbo
Copy link

parbo commented Aug 22, 2022

Hmm, it seems to be related to max texture size. If I reduce the size of the biggest font I'm loading then scale factors above 2 works too.

@parbo
Copy link

parbo commented Aug 22, 2022

Is the loading of all glyphs to a single texture a thing that lives in imgui, or is it due to using stb_truetype.h? Maybe freetype would work better for me if so?

@ocornut
Copy link
Owner

ocornut commented Aug 22, 2022

It's an issue in dear imgui. Freetype does has the advantage that hinted rendering makes oversampling much less necessary and therefore save spaces. In my experience OversampleH=3 by default is largely overkill, =2 is enough.

@parbo
Copy link

parbo commented Aug 23, 2022

Reducing OversampleH to 2 allowed me to load fonts at 2x, so now my app has crisp fonts on macs. :)

@ypujante
Copy link
Contributor

@rokups This works great for me if I use auto scale = 2.0f on my 4k display (and I was really struggling with text looking really awful so than you for posting the solution!)

That being said, I am not sure how you get access to NSScreen, especially from the cpp side (not objective-C).

Shouldn't using auto scale = ImGui::GetIO().DisplayFramebufferScale.x work the same way in a more portable fashion?

@rokups
Copy link
Contributor

rokups commented Sep 11, 2022

Shouldn't using auto scale = ImGui::GetIO().DisplayFramebufferScale.x work the same way in a more portable fashion?

Not quite sure what you mean. DisplayFramebufferScale is specifically used on MacOS, where window size in units does not match window size in pixels. Some experimental work on HDPI support used it on other platforms, i suppose thats "more portable" as you say, but that work is experimental and largely incomplete and cant really be used.

That being said, I am not sure how you get access to NSScreen, especially from the cpp side (not objective-C).

You can create a function in obj-C and expose it to c++.
https://github.com/rokups/imgui/blob/1e68c78a5b41be1a68b236bf1887e95b0e2b9827/examples/imgui_impl_osx.mm#L310-L321
https://github.com/rokups/imgui/blob/1e68c78a5b41be1a68b236bf1887e95b0e2b9827/examples/imgui_impl_sdl.cpp#L58

@ypujante
Copy link
Contributor

@rokups Thank you. BTW it seems that the code you pointed to if (screen.visibleFrame.origin.x >= x && screen.visibleFrame.origin.y >= y && is actually backward... If you want (x,y) to be inside the visible frame, it should be x >= screen.visibleFrame.origin.x which is screen.visibleFrame.origin.x <= x (same for y)

pthom added a commit to pthom/hello_imgui that referenced this issue Nov 11, 2022
cf ocornut/imgui#5301
Issue with MacOS is that it pretends screen has 2x less pixels
than it actually does. This simplifies application development in most cases,
but in our case we happen to render fonts at 1x scale while screen renders at 2x scale.
wavewave added a commit to MercuryTechnologies/ghc-specter that referenced this issue Sep 22, 2023
Due to Dear ImGui issue ocornut/imgui#5301, the font scaling on HiDPI setup (only on macOS) is not correct and results in blurry text. This PR is a workaround for that.

* simple scale technique worked.
* check DisplayFramebufferScale
* start making a shim
* automatic detection of scale factor on macos
* make nix build succeed.
* remove stale code
* compile shim.mm only on macOS
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

No branches or pull requests

6 participants