ocornut / imgui

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

ImGui::GetWindowContentRegionMin() and flag "ImGuiWindowFlags_NoTitleBar" - one pixel difference #6666

Open ElectroidDes opened 11 months ago

ElectroidDes commented 11 months ago

Please tell me - is this the correct behavior of Imgui?

I create two regular windows: -Change for convenience in them the background color

Here is the code I am using:

  bool open_bool_1;
    ImGui::PushStyleColor(ImGuiCol_WindowBg, { 255, 255, 0, 255 });
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0,0});

    ImGui::Begin("Test_with_Title", &open_bool_1);

    ImDrawList* draw_list_1 = ImGui::GetWindowDrawList();

    ImVec2 Min_1 = { ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMin().x,  ImGui::GetWindowPos().y + ImGui::GetWindowContentRegionMin().y };

    draw_list_1->AddLine({ Min_1.x, Min_1.y }, { Min_1.x + 200, Min_1.y }, ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 1.0f }), 1.0f);

    ImGui::End();
    ImGui::PopStyleColor();
    ImGui::PopStyleVar();
    bool open_bool_2;
    ImGui::PushStyleColor(ImGuiCol_WindowBg, {255, 255, 0, 255});
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });

    ImGui::Begin("Test_without_Title", &open_bool_2, ImGuiWindowFlags_NoTitleBar);

    ImDrawList* draw_list_2 = ImGui::GetWindowDrawList();

//!!!!!ALARM PLEASE NOTE: In this window, I am incrementing the Y coordinate by one unit below what ImGui::GetWindowContentRegionMin().y returns
    ImVec2 Min_2 = { ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMin().x,  ImGui::GetWindowPos().y + ImGui::GetWindowContentRegionMin().y + 1 };

    draw_list_2->AddLine({ Min_2.x, Min_2.y }, { Min_2.x + 200, Min_2.y }, ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 1.0f}), 1.0f);

    ImGui::End();
    ImGui::PopStyleColor();
    ImGui::PopStyleVar();

Here are two screenshots of the window:

Window_JPEG

That is, with all this I wanted to ask, is it correct that:

-If I create a window with a Title, then the ImGui::GetWindowContentRegionMin().y function returns the coordinate Y IMMEDIATELY BELOW the title - this can be seen from the drawn green line.

-But when I create a window WITHOUT a Window Title, the ImGui::GetWindowContentRegionMin().y function returns the Y coordinate - ON the Window Border and in order for the green line to be drawn IMMEDIATELY BELOW the window border - I need to increase ImGui::GetWindowContentRegionMin().y by one one unit down the Y axis.

GamingMinds-DanielC commented 11 months ago

Your screenshot makes things hard to see since your non-enlarged version is scaled down and your enlarged version is interpolated.

It looks like you don't take pixel centers into account. The minimum position is the top left corner of the top left pixel while the maximum position is the bottom right corner of the bottom right pixel. Lines extend to half their width to either side. If you want to hit pixel centers exactly, you need to provide coordinates that go through those centers. That means adding an offset of { 0.5f, 0.5f }. If you don't do that, you have a line that barely touches pixel centers on both sides (assuming a width of 1), then you can get rounding issues. And yes, that is how it is supposed to work.

Here is some interesting info about rasterization rules with a proper visualization, these should apply to other APIs as well: Introduction to rasterization rules Rasterization Rules

ElectroidDes commented 11 months ago

Your screenshot makes things hard to see since your non-enlarged version is scaled down and your enlarged version is interpolated.

My enlarged version is an enlarged version of a smaller version. Why then should you look at something on the non-enlarged version - if it is also "interpolated"?

My line is strictly horizontal and does not take up multiple adjacent horizontal pixels - ONLY strictly one level of horizontal pixels, what kind of "interpolation" are you talking about?

Here is from your link:

изображение

GamingMinds-DanielC commented 11 months ago

My enlarged version is an enlarged version of a smaller version. Why then should you look at something on the non-enlarged version - if it is also "interpolated"?

The only useful image to investigate problems with pixel perfect rendering are 1:1 and versions scaled up by an integer factor with nearest filtering. Your image contains a scaled up version with interpolated colors (not useful) and a version that is scaled down, not 1:1, therefore also not useful to see rendering issues.

My line is strictly horizontal and does not take up multiple adjacent horizontal pixels - ONLY strictly one level of horizontal pixels, what kind of "interpolation" are you talking about?

I was talking about interpolation only in relation to your image, not your line placement.

And your line pretty much takes up two rows of pixels, covering the lower half of the upper row and the upper half of the lower row. If you used super sampling, you would see a half transparent line. It would be 2 pixels thick if it were not for the window clipping, that would reduce it to 1 pixel again.

The line you marked in the image from the rasterisation rules link has a vertical offset of 0.5 (no horizontal offset), your code doesn't have that offset.

ocornut commented 10 months ago

If I am not wrong, I recall writing an extensive answer to this on July 31 but it didn't go through (I was travelling. I'll see later on my laptop if I have a trace of this message.)