Fonts #5301

Closed
opened 2022-05-09 09:54:56 +00:00 by noisewuwei · 16 comments
noisewuwei commented 2022-05-09 09:54:56 +00:00 (Migrated from github.com)

Platform: Mac OS
Backend: Metal

Why is the Chinese displayed so vague?

d546d0432a435cd911fb115648bb2c6a
Platform: Mac OS Backend: Metal Why is the Chinese displayed so vague? <img width="659" alt="d546d0432a435cd911fb115648bb2c6a" src="https://user-images.githubusercontent.com/7871750/167386055-29400da2-3110-4296-a7d7-d2ec5c33f653.png">
rokups commented 2022-05-09 10:33:31 +00:00 (Migrated from github.com)

Could you describe what you mean by "vague"?

Could you describe what you mean by "vague"?
celestialemily commented 2022-05-09 10:51:55 +00:00 (Migrated from github.com)

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

@rokups I think he is talking about the slight blurriness of the characters, for this I would probably assume DPI scaling or AA.
ocornut commented 2022-05-09 11:55:09 +00:00 (Migrated from github.com)

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.

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.
noisewuwei commented 2022-05-09 15:34:51 +00:00 (Migrated from github.com)

Could you describe what you mean by "vague"?

Sorry.I mean the text is not distinct.

> Could you describe what you mean by "vague"? Sorry.I mean the text is not distinct.
rokups commented 2022-05-10 08:08:56 +00:00 (Migrated from github.com)

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).

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: ```cpp 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 commented 2022-05-10 09:21:27 +00:00 (Migrated from github.com)

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.

> 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 commented 2022-05-10 09:21:43 +00:00 (Migrated from github.com)

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.

> 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: > > ```c++ > 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 commented 2022-05-10 09:27:07 +00:00 (Migrated from github.com)

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.

> 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: > > ```c++ > 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 commented 2022-08-22 14:15:23 +00:00 (Migrated from github.com)

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?

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 commented 2022-08-22 14:25:36 +00:00 (Migrated from github.com)

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.

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 commented 2022-08-22 14:46:36 +00:00 (Migrated from github.com)

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?

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 commented 2022-08-22 14:55:36 +00:00 (Migrated from github.com)

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.

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 commented 2022-08-23 07:04:19 +00:00 (Migrated from github.com)

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

Reducing OversampleH to 2 allowed me to load fonts at 2x, so now my app has crisp fonts on macs. :)
ypujante commented 2022-09-10 18:30:15 +00:00 (Migrated from github.com)

@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 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 commented 2022-09-11 07:05:54 +00:00 (Migrated from github.com)

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++.
rokups/imgui@1e68c78a5b/examples/imgui_impl_osx.mm (L310-L321)
rokups/imgui@1e68c78a5b/examples/imgui_impl_sdl.cpp (L58)

> 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 commented 2022-09-12 12:49:44 +00:00 (Migrated from github.com)

@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)

@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)
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#5301
No description provided.