-
Notifications
You must be signed in to change notification settings - Fork 567
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
Add max_pack_XXX to nk_font_atlas #296
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not an expert myself, but the reasoning seems good. I only have one nitpick for the code
added zeros back into changelog numbers to keep formatting consistant
6615bcc
to
b884db8
Compare
According to a git notification, @RobLoach commented the change:
but I can't actually see the comment in this PR. Any way, I used the occasion to rebase this PR on the newest git master and reverted the version number formatting with how it was before, whilst I'm at it. (4.9.4) --> (4.09.4) I have been using
in every Nuklear project for a while now. And pretty happy with it, since using Japanese + Cyrillic font configs constantly blew past the small 1k x 16k texture strip. |
Actually this was intentional as "true" Semver doesn't use any zero padding 😉.
Interesting. Just for me - what are the overall sizes of all such atlases in RAM you see in practice per process (on x86, POWER, ARM machines of your choice)? Few MBytes or tens of MBytes or hundreds of MBytes? |
Ohh... reverted to how it was in git master again.
I only did x86 PCs so far, always with a GPU or iGPU present. After uploading to the GPU, I remove the image from RAM and as I understand it, no font atlas is kept in RAM any more. With the whole CJK Unicode block + all special characters + icons and small font size, in VRAM everything fits into 16kx1k and the bigger font sizes into 16kx2k. So I guess for 4-channel RGBA that would be 16kx2k = 32MP * 4 / 8... 16 megabytes in the worst case. Which is quite a chunk now that you mention it. Most used 2000 Joyo kanji as taught in school in Nuklear's format
I don't actually use the defaults as provided by the default Nuklear config and believe it's a bit of a mistake, to use oversampling (especially 3x only horizontally), as it does not contribute to sharpness as one might expect. I use 1:1 size + pixel snap and find the size where the font appears sharp after baking. Partly because stb_truetype doesn't use hinting, only certain sizes are sharp. So my texture sizes are actually a bit smaller than default I guess. |
Thanks for the practical insight!
That's an interesting observation - do you think we could add something like this (with some font size compensation on top) or at least some parts to upstream Nuklear? Font sharpness was (and still seems to be) a problem for some. It's a delicate topic, so we have to be extra careful but I seek any opportunity to explore how to make it better. |
Yes and no. I can add a tutorial or Git Wiki entry on how to find the correct fully sharp size for a font file. They come in integer steps. Sharp text sizes are eg. 22.7 and 26.7 and 30.7 and 34.7. But another font file bakes with proper sharpness at other steps 18.3 and 24.3 and 30.3 and 36.3... There is no rime or reason as to why stb_truetype rasterizes blurry on certain steps that I understand, but finding the correct sharp sizes gives you the same sharpness as Firefox or anything else that uses FreeType. The lack of hinting does not fully explain this behaviour but I am not the only one to has noticed this. But hey, stripping hinting information makes for smaller font files... |
Oh, I suspected this but prayed it's not true 😉. In that case, would you be willing to add it to our wiki? If you'll have any permission issues, just ping me here. |
@dumblob Sure I"ll put together a wiki tutorial. Though I don't have permissions to create a wiki page yet... |
Mind trying again? Just enabled public wiki editing. |
Works, will create an guide with visual examples over the next few days. |
Completed the full font guide with every detail a user might want to know with animated gifs to compare sharpness settings. Besides the requested sharpness discussion I covered related topics like how to avoid common segfaults when dealing with fonts and how to work with third-party apps to subset your font files for better inclusion in Nuklear. Some future ToDo:
|
@FrostKiwi this is mind blowing! I've went through about 20% of it quite closely and just skimmed the rest and it's awesome. So much effort and so much detailed information. It's definitely the best write up on fonts in practice I've ever seen. This might become the guide for nearly any font handling (not only Thanks a ton! We owe you a beer 😉. P.S. I think we should link this wiki from the |
Rebased branch on youngest master, so this PR can be added without conflicts. |
With a large number of glyphs (i.e. by including Unicode's CJK unified table for Japanese), Nuklear's default font handler produces tall but thin Texture atlases, that quickly break through the GPU's max texture size. See this texture atlas for context:
Example default texture atlas
To alleviate this, this PR introduces "nk_size max_pack_width" and "nk_size max_pack_height" to the struct "nk_font_atlas".
This allows the user to override the texture atlas size limits, as used by nk_font_bake_pack(). Because those numbers have to be initialized to prevent undefined behavior in the default case, nk_font_atlas_begin() sets this value to 0. As such, the values can only be set after nk_font_atlas_begin().
Here an example for context, which sets the pack size to the OpenGL Texture maximum, based on the GLFW_OpenGL3 demo.
Now the texture atlas is more square and does not blow past the GPU's size limit with bigger fontsizes or oversampling.
Those values are used to report the result of the atlas baking and packing operations. It would be inconstant logic, if the values are set one moment and change by themselves in the next one.
Same logic, those values are just used for reporting back, also it would require users to initialize those values to zero beforehand, breaking Nuklear by default.
It would break the API and all demos.
Although still arbitrary, the 16k textures are the upper limit of a big chunk of modern graphics cards. 16k textures are a sensible upper limit, if a more sensible value is not set by the user