The text rendering nuklear_glfw_gl4 is disgusting
Tried going under the latest version of gl4.6.
Built an example from nuklear_glfw_gl4.
Disabling or enabling nk_anti_aliasing param does not bring any changes.
The picture looks extremely ugly.
Is there any way to fix it?
I built the same demo on Windows 10, msys2 environment.
For reference here are the library versions I have on my system:
- Nuklear 4.12.5
- mingw-w64-x86_64-glew 2.2.0-3
- mingw-w64-x86_64-glfw 3.4-1
- mingw-w64-x86_64-glm 1.0.1-1
Library versions correspond to their upstream version numbering schemes. E.g. glfw 3.4-1 corresponds to Arch Linux version 3.4. Further packaging information can be found on the msys2 packages website.
I have no clue whether it matters or not, but my native resolution is 1920 x 1080 at 100% DPI level.
Video card features are attached, produced by glewinfo tool.
You've enlarged the font... That's not a valid comparison. I build without glfw on pure opengl, because glfw window slows down and jerks in the application if the cursor moves over the window. I need have fast stable rendering.
I am building demo in Windows 10, in Visual Studio 2019 using collected lib dlls from official sites. I have a similar display resolution with dpi = 96.0 OpenGL ver 4.60 RTX2070
In the pure OpenGL version, the result looks even worse. And the left edge of the buttons is cut off, although the gap between the button and the window is significant. The hidden bug is undoubtedly present in the library. Because the same cut is on the DirectX version. I assume this is due to incorrect rounding of float coordinates
You've enlarged the font... That's not a valid comparison.
I built \Nuklear\demo\glfw_opengl4\Makefile from tag 4.12.5 as-is. No changes.
Please, check the project for yours PC Here It's an “as is” demo.
The attached NukearTest.zip contains a single cpp file with dependencies to a dozen unavailable headers. The cpp seems to be realizing class members. There is no entry point to an actual application.
In the pure OpenGL version
Just to clarify. Did you tried to build the glfw_opengl4 demo for comparison? Is that ugly the same way on your system?
the same cut is on the DirectX version
Do you refer to \Nuklear\demo\d3d12\build.bat?
pure OpenGL version
On a clean gl you can see the result in the picture above. But the player works super fast. And there are no any glitches from mouse and keyboard events. So there is no point in going back to glfw anyway. 3D picture quality is more important than the quality of interface letters. It's for a 3D player .
It seems to me that currently we cannot build a common test software that can be objectively compared on both ends to triage a root cause. If you can point me to a self contained Nuklear "demo" that you can also build, please let me know.
What I find interesting is that on the comparison screenshot the left side window frame is 99% same size that the right side window frame has not considering filtering or aliasing glitches on the left. The arrows on left side are single color polygons, on the right side they are blended or multi sampled or similar. The left side widget frames are single pixel, the right side are not really. If you use the NK_INCLUDE_VERTEX_BUFFER_OUTPUT switch I would say the primitives are 100% same regardless of the windowing system used as long as the samplers and similar are also configured the same way in the render pipeline. I quickly built sdl_opengl3 and it is pixel perfect exactly the same as the window I get from the glfw_opengl4 demo.
So my initial assumptions are as follows:
- the reason why I get good results for glfw is independent from glfw as I get the same good results with sdl.
- in both demos NK_INCLUDE_VERTEX_BUFFER_OUTPUT is on so in both cases Nuklear produces the vertices/polygons and determines the UVs for textures (baked fonts) or sets colors for vertices.
- in both cases 32 bit floats are used on CPU side and the very same shaders are used by both where fragment shaders use 16 bit float precision.
Yeah, checked. For some reason the files are not attached to the archive. Put the zip back together. Try please. Should open *.sln project file in VS2019 or higher ver.
DirectX version
Made it for Dx10 by myself. Because at that time there was no ready example. Then I went back to the built-in GUI DX because the result with Nuklear was bad and I didn't have time to deal with it.
You can try running this player and see. It was made on glfw3. The button trimming problem is exactly the same there. I had to add an empty cell in front of each button so that the edge would not be cropped. You understand, the rendering speed became only worse from such “crutches”.
And as I wrote earlier, if you hold the mouse over the glfw3 window, it starts jittering and drawing delays. The problem is aggravated if a web browser is open. It jitters significantly. In 3D it is immediately visible by loss of synchronization. So I had to give up ready-made libraries and the bugs hidden in them and do it right again with pure GL.
NK_INCLUDE_VERTEX_BUFFER_OUTPUT Enabled
If you make the window visible. You can see that there is a gap between the window border and the button. And the left edge is “bitten off”. If you look at the earlier picture. You can see the same thing in the original example.
Enlarge the picture in the editor in 3...4 times and it will become clear that the left edges of the controls do not exist....
This is the output of the test app in case the default ProggyClean font is used at EM=13 pixels render size and anti aliasing is NK_ANTI_ALIASING_ON.
In the example Roboto-Regular is configured to have render size of 16 pixels. It is important to note that this font is a true vector font with real curves and such. ProggyClean is a vector font too, but it is built from uniform quads so that if render size in pixels is small but render size is selected appropriately, then even an inefficient font rasterizer library could reach pixel perfect outputs. In addition subpixel font rendering is configured. The effect of that is probably somewhat comparable to a bilinear filter on a roughly 16 by 16 sprite. The stb_truetype library is notorious for producing bad quality rasterized outputs in case the selected render size is small and not carefully aligned with or tailored for the used font. You can read about why and when stb_truetype produces blurry output and how ImGui tackles these kind of blur issues here.
With anti aliasing disabled, I could reproduce the cut borders and this happens too in the stock Nuklear\demo\glfw_opengl4 demo. I enabled the style configurator which allows us to play around with most style attributes in real time, but i found not a single attribute that affects this behavior.
I went though the command buffer that creates the button face and 1 pixel rounded border stroke. The commands set the bounds of these primitives to be bigger than the spacer or sizer allocated irrespective that clipping was enabled. The command buffers held only integer x,y,w,h values. There is a section in the code that truncates all fractions from these values. NK_COMMAND_RECT_FILLED and NK_COMMAND_RECT are the involved commands.
In case anti aliasing is disabled these commands apply a -0.5f offset to their X, Y whatever coordinates inside nk_draw_list_fill_rect and nk_draw_list_stroke_rect. Applying an offset of +0.5f instead results in such an output:
What can I do to make it work properly?
Do you have specific instructions on what to do to fix this?
Probably should be corrected in Nuklear itself so that people do not suffer with this problem.
Hello @RobLoach , in nuklear_vertex.c there are specific offsets to some coordinates in case anti aliasing is disabled. Based on limited trial and error attempts it seems that the offsets cause visual glitches in the use cases that we checked. A few comments above there are screenshots showcasing the problem. Git blame says that there is no change since 7 years and git blame cannot compute the original single file header as it is way too big and old.
Do you know by chance why could such offsets be present in various vertex output functions? Could it happen that those offsets really have to be added instead of subtracted and there are no corner cases where the offsets would be required in the other way around?
I haven't studied that deeply into it yet. Thought you might know how it works. Just put the assembled player with this version, gui certainly looks awful.... :(
It is definitely a strange issue. I believe it has to do with calculating the line widths with AA, but I've been unable to track it down.
What happens when we remove the 0.5f offset across all those vertex calculations? I have a theory: When the 0.5f offset is applied, the line border gets clipped by the rectangle clipping.
Everyone was spitting at me yesterday for this quality of text. A little more comparison. This is Pot Player gui and Nuklear gui.
Sounds some weirdness on the button border. Mind testing this out? Reverted the commit in https://github.com/Immediate-Mode-UI/Nuklear/pull/800
Everyone was spitting at me yesterday for this quality of text.
Pot Player uses freetype2 not stb_truetype. As noted earlier, stb_truetype will not do with arbitrary fonts not optimized for small render sizes and personally I encourage you to integrate freetype2. It can be done, I did it too using the guidance of the online documentation. But if you want to stick to stb_truetype you have to find the font and render size combination that is sharp. Here is the official wiki how you do it.