Skip to content

Font Anti-Aliasing? #1498

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

Open
venixburda opened this issue Dec 12, 2017 · 21 comments
Open

Font Anti-Aliasing? #1498

venixburda opened this issue Dec 12, 2017 · 21 comments

Comments

@venixburda
Copy link

Is there a way to disable Anti-Aliasing (I think is what it's called) on fonts?
If I render fonts of smaller sizes, they become blurry. I want to make them sharp and from investigation it appears the best way to do that is to disable AA?

@ocornut
Copy link
Owner

ocornut commented Dec 12, 2017

It's not an easy problem to solve, there is no magical "disable AA".

  1. make sure you read the font documentations and experiment with oversampling.

  2. Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling).
    This technique and implementation are not ideal for fonts rendered at small sizes, which may appear a little blurry. There is an implementation of the ImFontAtlas builder using FreeType that you can use:

    https://github.com/ocornut/imgui_club

FreeType supports auto-hinting which tends to improve the readability of small fonts.
Note that this code currently creates textures that are unoptimally too large (could be fixed with some work)

@OvermindDL1
Copy link

OvermindDL1 commented Dec 12, 2017

@ocornut stb_truetype.h (if updated, and I think freetype or at least a fork of it supports SDF generation as well) has support for single channel SDF bitmap generation. It's not as great looking as 2-channel SDF generation, but by using it then someone can generate a single SDF font image that would look great at all sizes (though it would look better if 2-channel, stb is open for PR's though!). No antialiasing with it, everything is perfectly crisp and clear, you can do effects like outlining and shadows and more, effectively for free. Perhaps it would be useful to add support for SDF font rendering?

@itamago
Copy link

itamago commented Dec 13, 2017

That would be great to support SDF font rendering, sure !
My guess is that there are other top priorities for the moment, but SDF font rendering may become an important one on next year ?

@ocornut
Copy link
Owner

ocornut commented Dec 13, 2017

Some notes

  • SDF isn't magic, can you get actually quality render for a non-zoomed ~14px size font? Which is what we should care about the most. SDF is great for enlarged display in 3D space but this is not how you get desktop quality rendering as far as I know (maybe I'm wrong).
  • Heaver pixel shading which will affect drawing all our filled contents/surfaces - that or changing shader programs during imgui rendering, which is potentially worse. If you start adding options such as outline into the mix, how do you deal with the variety of shaders or do you push the cost into all rendering?
  • Harder to display normal images in your pipeline, you'd may need to redefine ImTextureId to be a higher-level construct. (Though one could imagine the renderer backend to be hardcoded to know that only the font atlas is SDF and the rest is by default RGBA).
  • Harder to include colored icons in the font atlas.
  • Harder to integrate in new projects.

Also linking to
#858
(Though I think that experiment was very misled by using the pixelated ProggyFont, should have focused on a font that we'd actually want to see scaled).

I personally don't suppose this is something I'll dig into next year, I think making the atlas dynamic would solve more issues than using SDF (such as the problem for localization). But if you want to experiment with it please do! And if you can find a way to make a possibility in imgui without affecting all users why not.

@OvermindDL1
Copy link

SDF isn't magic, can you get actually quality render for a non-zoomed ~14px size font? Which is what we should care about the most. SDF is great for enlarged display in 3D space but this is not how you get desktop quality rendering as far as I know (maybe I'm wrong).

I use 2-channel SDF's in my projects and they look fantastic at all resolutions, from tiny 8px big to the size of the screen, clear and readable at all steps. Single channel is indeed a bit wonky at times, but it still works the great majority of the time and is a good jumping point as the only change you need to make when going from 1 to 2 channel is changing the shader.

Heaver pixel shading which will affect drawing all our filled contents/surfaces - that or changing shader programs during imgui rendering, which is potentially worse. If you start adding options such as outline into the mix, how do you deal with the variety of shaders or do you push the cost into all rendering?

You should only need to change the shading program once for that, such as one shader to render the GUI pass then switch to another for the text pass, not much cost there (assuming clipping bounds are well set and so forth, which you can even bake that into the shader as well quite easily).

Options like outlines and so forth are usually all part of the same shader (at least mine is) and they are controlled via uniforms passed in (I need to clean it a bit), where basically if it is 0 there is not outline, same with shadow, same with italic, and a couple other things I have baked in. It is all the same shader running the same code path with no branches.

Harder to display normal images in your pipeline, you'd may need to redefine ImTextureId to be a higher-level construct. (Though one could imagine the renderer backend to be hardcoded to know that only the font atlas is SDF and the rest is by default RGBA).

Not really I'd think? An SDF is just a simple image/texture like any other, just black/white for 1-channel and red/green for 2 channel (I use blue and alpha for extra information in my renderer though, but just red/green is traditional).

Harder to include colored icons in the font atlas.

This is something I've not really explored yet. In my old renderer I can put images inline with text so I've not needed to create colored glyphs yet. However I could see a couple of fairly easy ways to do it that could be tested.

Harder to integrate in new projects.

Not really sure I see that. The only thing I did to add SDF to my renderer (from scratch) as change the font texture and write a different shader than the one I was using for text (I already had a text-specific shader to try to get text to look better before I switched to SDF a couple years ago).

(Though I think that experiment was very misled by using the pixelated ProggyFont, should have focused on a font that we'd actually want to see scaled).

I initially experimented with Valve's SDF font, it is quite well made, though there are better ones out there now.

And if you can find a way to make a possibility in imgui without affecting all users why not.

Honestly I'd just consider it as 'just another font'. A font could have properties like how it should be rendered and such, then the user's renderer can order it how they wish and render it with whatever shader's they want, just like any other font.

@ocornut
Copy link
Owner

ocornut commented Dec 13, 2017

Thanks for your feedback.

one shader to render the GUI pass then switch to another for the text pass

So we'd need imgui to separate the text output from the non-text, which would break cases where we rely on overlapping shapes. Will requires a fair bit of work/fixing.

Not really I'd think? An SDF is just a simple image/texture like any other,

Yes but the shader isn't the same. Most backend implementation are designed to transport "texture" information in ImTextureId rather than "full material information" (shaders/programs/textures, etc.). So if you want to submit regular images within your render you'd need to interleave shader change.

However I could see a couple of fairly easy ways to do it that could be tested.

FYI there is now an undocumented but public API for that:

ImFontAtlas::AddCustomRectRegular()
ImFontAtlas::AddCustomRectFontGlyph()
ImFontAtlas::GetCustomRectByIndex()
etc.

Harder to integrate in new projects.
Not really sure I see that. The only thing I did to add SDF to my renderer (from scratch) as change the font texture and write a different shader than the one I was using for text (I already had a text-specific shader to try to get text to look better before I switched to SDF a couple years ago).

Half of dear imgui users have no idea what they are doing with shaders, textures, and some of the high-level libraries don't provide the same mechanism for custom shaders. I'm not saying this fact alone should discourage us from trying that technique, especially since we're experimenting there, but it's something to keep in mind. Ideally I think being able to have both would be ideal.

@OvermindDL1
Copy link

So we'd need imgui to separate the text output from the non-text, which would break cases where we rely on overlapping shapes. Will requires a fair bit of work/fixing.

Honestly should already be done, there are a lot of areas that specialized shaders could be of huge benefit (imagine a whispy cloud effect in the background of windows for example), this should all be tied together as a shader/texture combination on something though. :-)

Yes but the shader isn't the same. Most backend implementation are designed to transport "texture" information in ImTextureId rather than "full material information" (shaders/programs/textures, etc.). So if you want to submit regular images within your render you'd need to interleave shader change.

The renderer would indeed need another shader for it, but they probably already have such a shader depending on the engine they use, and it's not like they aren't using dozens to hundreds of other shaders anyway.

And I still wouldn't interleave shaders, I'd probably just use z-culling well and bake certain functions into the shaders and then batch everything by 'type', as most renderers do already anyway.

Half of dear imgui users have no idea what they are doing with shaders, textures, and some of the high-level libraries don't provide the same mechanism for custom shaders. I'm not saying this fact alone should discourage us from trying that technique, especially since we're experimenting there, but it's something to keep in mind. Ideally I think being able to have both would be ideal.

The users sure, but the users don't need to know about all that, only the person that integrates it into the engine itself, and I'd certainly hope they have at least an inkling of what a shader is since that is required to render, well, anything on any half-modern card of the past 10-20 years. ^.^;

But yeah, handling both would be fairly easy, especially if the rendering was batched properly based on shader/texture/parameter combinations, and you could even bake clipping into shaders optionally to allow for doing that much faster as well. :-)

@rlalance
Copy link

SDF is not cross platform.

@OvermindDL1
Copy link

OvermindDL1 commented Jan 6, 2020

@richardlalancette Signed Distance Fields is a technique, there's nothing platform specific about it. As long as you have something shader-like for texture handling then you can perform the technique.

@rlalance
Copy link

rlalance commented Jan 6, 2020

Still not cross platform.

@rlalance
Copy link

rlalance commented Jan 6, 2020

So I would avoid that solution, unless you have a way to abstract the solution so there is an elegant fallback.

@rlalance
Copy link

rlalance commented Jan 6, 2020

We deal with devices that do not have sharers! Or even GPU!

@OvermindDL1
Copy link

OvermindDL1 commented Jan 6, 2020

Still not cross platform.

How so?

We deal with devices that do not have sharers! Or even GPU!

Then that's extremely trivial to perform. Running shader-like code on the CPU is just a normal part of software rendering, whatever is doing the rendering can perform it (and to boot it's extremely fast an able to be run in parallel unlike a lot of other rendering code).

About the only thing it wouldn't work properly on is OpenGL1. OpenGL2 or OpenGL1.1+extensions will work fine (and both of which are well over 20 years old, I doubt anything exists that doesn't support at least GL2 even on embedded accelerated hardware, and of course can always fallback to pre-genning it on the CPU on demand, just like normal on-demand font rendering).

@rlalance
Copy link

rlalance commented Jan 6, 2020 via email

@MrDiver
Copy link

MrDiver commented May 29, 2024

Well, it's about 4 years later now and it seems like there is still no implementation for this. Was there any work done on this? Or did we leave it at non-scalable text rendering? I think for a time where 4k displays are more and more present in the consumer market it might be the right time to finally implement good font rendering.

And as @OvermindDL1 already stated there is nothing special about signed distance fields, it can be done on any hardware either software rendered with the CPU or done with a Shader on the GPU. And it wouldn't take that much effort to implement.

And it also seems to exist in stb_truetype -> https://github.com/nothings/stb/blob/master/tests/sdf/sdf_test.c
https://github.com/nothings/stb/blob/449758bd74ce14b7d0ba9b24a3dbc4386702a0e0/stb_truetype.h#L941

So would there now be some more interest in having such functionality?

@ocornut
Copy link
Owner

ocornut commented May 29, 2024

I am interested in this, it is one the reason i am leaving the issue open.
I don’t have enough resources and most large contributions/PR are missing the mark on too many details so I have accepted that things will take time. I have big topics i want to close before investigating the texture partial update, dpi, text functions, dynamic font loading and possibly alternative font rendering types.

@rlalance
Copy link

OMG! I just got this update by email.

@ocornut Did you know we use to have IMGUI in After effect plugin at You.i TV / Warner Brother.

They never agreed to back your project...

I am running a game studio now, so I don't need ImGUI, but man, it was a good time.

That thing was 5 times faster than the terrible UI from scripting in After Effect....

I miss using ImGui. :D

Richard Lalancette
Founder & CEO, Honour Bound Game Studios Inc.

Steam: Relic Odyssey: Ruins of Xantao
Email: [email protected]
Web: www.honourboundgamestudios.com
Twitter: twitter.com/HonourBoundGS
Discord: discord.gg/K7WkH8pVNv
YouTube: www.youtube.com/@HonourBoundGameStudios
TikTok: www.tiktok.com/@honourboundgamestudios
Instagram: www.instagram.com/honourboundgamestudios

@ocornut
Copy link
Owner

ocornut commented May 29, 2024

I am running a game studio now, so I don't need ImGUI

*Cough* :)

@MrDiver
Copy link

MrDiver commented May 30, 2024

@ocornut Is there anything i could help with at the moment?

@ocornut
Copy link
Owner

ocornut commented May 30, 2024

I guess I am a control and perf freak, but I'm struggling to accept help for non-small changes or features presently. Most of my attempts have been stalled by the amount of things to review, finish or something simply redo (I have even notable features that I paid someone for that in private-branch-limbo until I can seriously give my attention to them). I currently think the best way to help dear imgui is to focus on small things, or fixes, or answering questions, etc, since they allow me to focus on bigger things. But anything that is not done meticulously and with great attention to details have a tendency to derail my attention into "can't trust this" quickly. That said, in general, all the open PR are useful, even if unmerged for years I always keep them open for references as they always point to something that needs improvement.

This morning I stumbled on some of the photos I took while reading "Working in Public: The Making and Maintenance of Open Source Software", and this page stroke a chord:

IMG_1379

I've been mostly overwhelmed in endless maintenance and iterative progress, and inability to close some large topics have been hogging attention (recently: I've been trying to finish and merge multi-select branch, a feature which I started in 2019, and it's always in a "should finish it within a few months!" state). But basically I need to close a few things before I can undergo new big things. I would however like to ship a nice big new thing around August. (for reference, my private imgui repository has ~220 branches).

@MrDiver
Copy link

MrDiver commented May 30, 2024

So if i understand your concerns correctly, then reviewing all the small things and keeping your back free so you can focus on rewriting the big things is the way to go ? Or otherwise when helping on big PRs pay attention to all the details that would come with that and ensure peak performance!?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants