This is a feature request.
ImGui aligns text rendering position to a pixel perfect one. This is great but in some cases (for example when custom rendering) could be useful to disable the pixel perfect alignment of the text.
The implementation of the feature itself is very straightforward but the proper integration with ImGui maybe requires some extra work like deciding if it is supported as a pushable ImGuiStyleVar_ or something like that. Omar is the man! He will know how to do it properly.
For now I hacked it for my purposes, would be nice to have the feature available as an official one. I changed this:
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
{
if (!text_end)
text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.
// Align to be pixel perfect
pos.x = (float)(int)pos.x + DisplayOffset.x;
pos.y = (float)(int)pos.y + DisplayOffset.y;
To:
bool g_imGuiTextPixelPerfect = true;
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
{
if (!text_end)
text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.
// Align to be pixel perfect
if (g_imGuiTextPixelPerfect)
{
pos.x = (float)(int)pos.x + DisplayOffset.x;
pos.y = (float)(int)pos.y + DisplayOffset.y;
}
else
{
pos.x = pos.x + DisplayOffset.x;
pos.y = pos.y + DisplayOffset.y;
}
Hello,
You aren’t really describing why this may be useful, please do so and in details. “For exemple when custom rendering” is not enough.
Note that individual characters can already be not pixel aligned, it is only the initial one which is aligned on a per RenderText call basis.
Ok, I'll describe my specific case:
I'm using ImGui as the 2D interface system of a little game. The game world is 3D. ImGui is used normally, like other apps and games do (overlay, popups and context windows). Everything is ok.
But sometimes a text has to be drawn above some 3D objects. The text needs to follow smoothly the position of the 3D object. Check this video as reference of what I mean: https://youtu.be/Y3n3c_8Nn2Y?t=83 Have a look to the name of the 3D objects.
The 3D world objects position is projected to the screen coordinates in order to show text tips above some animated 3D objects. For that, I'm using ImGui DrawList calls to render it. The problem is that, with pixel perfect position the text shakes, no smooth movement. In order to have a smooth text movement the pixel perfect alignment must be disabled.
I could implement my own text rendering system but been already using ImGui for the rest of the game UI it would be nice to be able to add that specific text above the 3D objects with the custom ImGui AddText() call.
As I said I already resolved the problem with that little hack, ImGui made me happy that way, simple and agile. I hope you consider that I'm using ImGui properly and that been able to disable aligment of the first character when drawing text is useful enough to be part of the official features set.
Thanks for the explanation.
For the equivalent in 2D game what I did what submitting unprojected vertices to ImDrawList + callback to request the renderer to change the projection matrix. This is not possible with a 3D scene because our vertices are 2D, so your request makes sense.
I was tempted to try remove the rounding all together and perform it at a higher level (e.g. internal ImGui::RenderText or ImDrawList::AddText controlled by a ImDrawListFlags_). This rounding was part of 1.0 (very old!) so it'll need some investigation of the side-effects, and it'll probably break some ImDrawList::AddText() user code in particular for users relying on the default font.
So perhaps a flag would be better after all, and depending on the result we could turn this flag off by default. The tricky part is that this code is actually in ImFont::RenderText.. I have an incoming refactor of the text draw functions (there is an accumulation of desirable text rendering features that are calling for a refactor).. so I can include this in it.
You may also check out im3d by John Chapman which is more full-featured in term of 3D primitives drawing: https://github.com/john-chapman/im3d
(Note that even though im3d is inspired by the structure of dear imgui, it doesn't depend on it and requires its own renderer).
Any progress on this topic?
Most helpful comment
Ok, I'll describe my specific case:
I'm using ImGui as the 2D interface system of a little game. The game world is 3D. ImGui is used normally, like other apps and games do (overlay, popups and context windows). Everything is ok.
But sometimes a text has to be drawn above some 3D objects. The text needs to follow smoothly the position of the 3D object. Check this video as reference of what I mean: https://youtu.be/Y3n3c_8Nn2Y?t=83 Have a look to the name of the 3D objects.
The 3D world objects position is projected to the screen coordinates in order to show text tips above some animated 3D objects. For that, I'm using ImGui DrawList calls to render it. The problem is that, with pixel perfect position the text shakes, no smooth movement. In order to have a smooth text movement the pixel perfect alignment must be disabled.
I could implement my own text rendering system but been already using ImGui for the rest of the game UI it would be nice to be able to add that specific text above the 3D objects with the custom ImGui AddText() call.
As I said I already resolved the problem with that little hack, ImGui made me happy that way, simple and agile. I hope you consider that I'm using ImGui properly and that been able to disable aligment of the first character when drawing text is useful enough to be part of the official features set.