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
(WIP) Dynamic glyph rasterization and unlimited number of font textures #3471
base: master
Are you sure you want to change the base?
Conversation
Texture baked anti-aliasing and freetype is not yet supported. Only GLFW-OpenGL2 and GLFW-OpenGL3 backends supported.
Great work, thanks for posting this! I haven't dug in this, but some early suggestions:
|
Thank you for the feedback Omar. I have added FIXME-DYNAMICFONT comments in the places where I soon intend to fix features. The remaining commented blocks are for CustomRect and baked antialiased lines which is not yet supported. I think the flickering is because I am currently generating glyphs in one frame and uploading to the graphics card in the next frame but this should be easy to fix by uploading at the end of the current frame instead. |
…obal define IMGUI_ENABLE_FREETYPE to enable it and disable stb_truetype.
I noticed in a gif you posted that it fallbacks to many textures, but then how are drawcalls handled? Wouldn’t this lead to drawcalls explosion very fast? |
… requested glyph has not yet been rendered.
There is only one draw call per font texture used. I have not implemented resizing font textures yet since I thought multiple font textures would still be a prerequisite to make it scalable since there is a limit how large a texture can be but no limit on how many textures there can be. ImFont::RenderText works like this: (lines correspond to latest commit 986738c)
In summary:
My latest push fixes the flicker issues. |
Great!
I think the the draw call explosion would be so problematic it is saner to focus on a system when we either
But to be z-order preserving that's per call to RenderText()? And we want to support thousands of calls to RenderText() every frame, interleaved with shapes. To minimize it guess we could have a scheme were:
I've added you the imgui_dev/ repository btw, when you run test_app under "Perfs" you can run perf tests (and probably add new ones) to compare branches, a critical part of this feature is and has always been performance of CalcTextSize() and RenderText() in the normal idle rendering case, for both Debug and Optimized builds, so it would be good to have early metrics of how the current version fare and see if we are within an acceptable ballpark for perfs. Thanks! |
imgui_draw.cpp
Outdated
result = &this->Glyphs[i]; // Save the result | ||
if(!backup_glyph) break; //Caller didn't want a backup glyph | ||
if((this->Glyphs[i].FontTexture && this->Glyphs[i].FontTexture->TexID != NULL) && this->Glyphs[i].FrameCountCreation != ImGui::GetFrameCount()) { | ||
*backup_glyph = NULL; // This glyph has already been rendered and uploeaded to the graphics card. No backup glyph needed. |
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.
*backup_glyph = NULL; // This glyph has already been rendered and uploeaded to the graphics card. No backup glyph needed. | |
*backup_glyph = NULL; // This glyph has already been rendered and uploaded to the graphics card. No backup glyph needed. |
I will focus on garbage collection and rearranging the glyphs to allow them to remain on the first font texture. These are the results I get when comparing to vanilla imgui. Am I reading it right that my version in -O3 is about a millisecond slower per frame? Since the tests results are similar when displaying proggy-clean on texture 1 and roboto-medium on texture 2 in release mode I think it is an indication that most of the disparity compared to master are optimizations I have not yet implemented. With master imgui -O0 (Debug):
With master imgui -O3 (Release):
With dynamic fonts -O0 (Debug): (Proggy-Clean on font texture 1)
With dynamic fonts -O3 (Release): (Proggy-Clean on font texture 1)
With dynamic fonts -O0 (Debug): (Roboto-Medium on font texture 2)
With dynamic fonts -O3 (Release): (Roboto-Medium on font texture 2)
|
Thanks for the update! Yes that's correct. Another way to read it is to state it is currently about 2-2.5 slower in both -O0 and -O3. For info, the Perf function measure the base dt before starting the test, so the time display is the added difference from that baseline (actual app may be e.g. an extra 1 ms to do the swap etc.). Those specific four tests are stressing one specific aspect - hammering text functions only. Since this is not really what a real app does, maybe we'd get more real-world representative number by running the Later on, another test which will be worth pursuing will be with lots of glyphs (e.g. rendering a typical of Chinese text) as with the new algorithm the hashing will be stressed a little more. Depending on how it far we can adjust the hashing, or perhaps even have specialization for ascii ranges of if find it is worth it. (hope we can later work on systems to turn that CSV data into easy to visualize stuff) |
FWIW: I just found this header-only font library tonight that seems amazingly close to the overall architectural methodology of Dear Imgui. It's quite different from what you're doing in this PR but might still be an interesting read... https://github.com/kv01/ttf-parser - Seems like a mature abandon'ed project... I really don't know much about how the font stuff works. Might be a complete waste of time. But anyway. Just trying to be friendly and pass something interesting along. It's about a thousand lines, comments and all, so should be a quick read. License is identical too so you are free to "borrow code" if it does end up being useful. If it helps ,great. If it's a distraction, sorry about that... In any case, keep up the good work. Looking forward to dynamically re-sizable fonts!! |
I left a PR on how to change the makefile to detect debug mode on Linux. I don't think you can do it only using a #define. frink: Thank you, but that looks like a parser of .ttf-files and I am still using STB or optionally Freetype for rendering those like vanilla imgui. This branch is about how imgui could handle the generated glyphs on the font texture to display them in different sizes while remaining fast. So it is a step after the library you are linking to. Freetype is a heavier dependency but more visually pleasing and the industry standard. |
Yes it is a parse that parses straight to GL triangles if I understand correctly. Not sure if it's better. Just different. First time I've seen GPU engaged to rasterize fonts. My thought is that if we're using GL for everything already why rasterize fonts as an intermediary step? You've probably got a better but it seemed like an interesting idea... |
Any news on when this will be merged? This is exactly what I need. |
Could be a while. Good code takes time and this one is no picnic. Right now the best thing you can do is oversample your font atlas in the init stage and then use font scaling. |
time. When the primary font texture is full overflow font textures are used to render the remaining glyphs. On the next frame all glyphs are cached and a new primary font texture is assembled with the glyphs from the cache. Changes to be committed: modified: examples/imgui_impl_opengl2.cpp modified: examples/imgui_impl_opengl3.cpp modified: imgui.h modified: imgui_demo.cpp modified: imgui_draw.cpp
In the latest update only one font texture is used 99% of the time. When the primary font texture is full glyphs spill over to overflow texture(s). On the next frame all glyphs are moved to a cache and the font atlas re-assembled with the custom rects and the currently visible glyphs. This is ocornut:master on my machine: This is the dynamic font branch on my machine (no glyph overflows triggered): |
Upgraded to v 1.84 WIP.
Changes to be committed: modified: backends/imgui_impl_dx9.cpp modified: backends/imgui_impl_dx9.h modified: backends/imgui_impl_glfw.cpp modified: examples/example_win32_directx9/main.cpp
0c1e5bd
to
bb6a60b
Compare
8b83e0a
to
d735066
Compare
b3b85d8
to
0755767
Compare
c817acb
to
8d39063
Compare
This PR is my attempt at bringing dynamic glyph rasterization and unlimited number of font textures to Dear ImGui. This is my proposal to fix #3365 #3406 #797 and all issues related to chinese glyphs, japanese glyphs etc...
Only the glfw_opengl2 and glfw_opengl3 backends are currently supported. The directx backends where changed to let me compile the example but do not work. I intend to fix them but wanted to show you my results before I get time for that. Tested on windows. Freetype, baked anti-aliased lines, software rendered mouse cursor and custom rects are not yet supported. The white pixel is located at (0, 0) on all generated font textures.
ImFontAtlas and ImFont has been completely revamped to generate glyphs upon use and packed in the same manner as fontstash. The rendering of the final text is the same as normal Dear ImGui. Instead of each font atlas having a personal FontSize the ImFontAtlas has a FontSize common to all loaded fonts.
Future plans is adding the missing features from normal Dear ImGui font code and unloading glyphs that have not been used for a certain amount of time.