ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.68k stars 9.9k forks source link

ImDrawList rects aren't perfect #7563

Open ramoops opened 1 month ago

ramoops commented 1 month ago

Version/Branch of Dear ImGui:

1.90.4

Back-ends:

imgui_impl_dx11.cpp + imgui_impl_win32.cpp

Compiler, OS:

Win 10 + MSVC 22

Full config/build information:

Dear ImGui 1.90.4 WIP (19031)
--------------------------------

sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _WIN64
define: _MSC_VER=1939
define: _MSVC_LANG=202002
--------------------------------

io.BackendPlatformName: imgui_impl_win32
io.BackendRendererName: imgui_impl_dx11
io.ConfigFlags: 0x00000020
 NoMouseCursorChange
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------

io.Fonts: 17 fonts, Flags: 0x00000000, TexSize: 2048,4096
io.DisplaySize: 1920.00,1080.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------

style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 4.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,12.00
style.ItemInnerSpacing: 12.00,4.00

Details:

My Issue/Question:

ok so, my code draws inconsistent rects as shown in screenshots it may not be very noticeable on mine screenshots, but it's very noticeable when rendering it on 1920x1080 I also tried turning off antialiasing using drawlist flags and drawing using other methods (rectfilled, other positions, sizes, etc), but nothing changed

Screenshots/Video:

image_2024-05-06_10-14-19 image

Minimal, Complete and Verifiable Example code:

const ImRect& bar_bb = {
  ImVec2(bb_rect.Min.x - 6, bb_rect.Min.y),
  ImVec2(bb_rect.Min.x - 6, bb_rect.Max.y)
};

draw->AddLine(bar_bb.Min, bar_bb.Max, ImColor(0, 0, 0, 160), 2);
draw->AddRect(bar_bb.Min - ImVec2(2, 1), bar_bb.Max + ImVec2(2, 1), ImColor(0, 0, 0, 200));

draw->AddLine(bar_bb.Max, bar_bb.Max - ImVec2(0, bar_bb.GetHeight()), ImColor(255, 0, 0), 2);
ocornut commented 1 month ago

Haven't looked in details yet but linking to #6669, #6971, #3258

ramoops commented 1 month ago

it kinda looks like it's half-pixel shorter, so I don't think that's the same problem that you linked

ramoops commented 1 month ago

oops, accidentally closed issue as resolved

ocornut commented 1 month ago

Btw your screenshot is hard to read because it is upscaled with filtering, and you are not stating in very specific terms what your problem is. It would be easier if you were more specific, as I personally have to deal with hundreds of concurrent topics and coming back to one later when the issue isn't clear makes it harder to help.

ramoops commented 1 month ago

yep I'll try to take normal screenshot, the point is that the {0, 0, 0, 255} (outline) rect looks inconsistent, right line looks bigger than left. when I'm rendering horizontal rect - it's surprisingly fine

ramoops commented 1 month ago

hm. strange enough, screenshot zoomed in mspaint looks absolutely normal, but on screen it looks inconsistent, so that isn't imgui issue then, sorry image (there's right bar bigger than left) image_2024-05-07_11-56-20

ruby3141 commented 1 month ago

That's subpixel problem, and it's out of imgui's scope.

As you can see, one pixel on your screen is actually consists of three subpixels, ordered red, green and blue. And because three subpixels are not in the same physical position inside a pixel, objects colored in pure red on your monitor is actually out of center in left by 1/3 pixel. (And black stripe on the right side is 5 subpixel in width, not 3.)

It can be compensated using subpixel rendering. Untitled With your monitor black stripe on both side of red stripe will look in same thickness, but actually right one has one black and one cyan pixel.

The problem is, it's hardware dependant. If you compensate it on one monitor, the result will look like crap when you show it on another monitor. (For example, mine has triangular subpixel, so my red is half a pixel up out of center.)

To do subpixel rendering, first you need to know what subpixel arrangement the monitor use is, That's why it's usually integrated in OS level with narrow scope of usage(like Windows ClearType text renderer), and why your issue is unsolvable in imgui's level.