About clipping rectangle #582

Closed
opened 2016-04-11 09:23:07 +00:00 by ottoGithub · 7 comments
ottoGithub commented 2016-04-11 09:23:07 +00:00 (Migrated from github.com)

hello,
please forgive my pool English, I will try my best to make it clear.

when I want to use a texture to fully cover the window, I found that there was a blank area at the edge of the texture even though I set WindowPadding = ImVec2(0, 0);
So I found the code as follows:

    // Inner clipping rectangle
    // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
    // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior.
    const ImRect title_bar_rect = window->TitleBarRect();
    const float border_size = window->BorderSize;
    ImRect clip_rect;
    clip_rect.Min.x = title_bar_rect.Min.x + 0.5f + ImMax(border_size, window->WindowPadding.x*0.5f);
    clip_rect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + 0.5f + border_size;
    clip_rect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, window->WindowPadding.x*0.5f);
    clip_rect.Max.y = window->Pos.y + window->Size.y - border_size - window->ScrollbarSizes.y;
    PushClipRect(clip_rect.Min, clip_rect.Max, true);

when I comment "+0.5f" ,it works fine.Is this the correct way to solve the problem that I faced?
thank you.

hello, please forgive my pool English, I will try my best to make it clear. when I want to use a texture to fully cover the window, I found that there was a blank area at the edge of the texture even though I set WindowPadding = ImVec2(0, 0); So I found the code as follows: ``` // Inner clipping rectangle // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); const float border_size = window->BorderSize; ImRect clip_rect; clip_rect.Min.x = title_bar_rect.Min.x + 0.5f + ImMax(border_size, window->WindowPadding.x*0.5f); clip_rect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + 0.5f + border_size; clip_rect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, window->WindowPadding.x*0.5f); clip_rect.Max.y = window->Pos.y + window->Size.y - border_size - window->ScrollbarSizes.y; PushClipRect(clip_rect.Min, clip_rect.Max, true); ``` when I comment "+0.5f" ,it works fine.Is this the correct way to solve the problem that I faced? thank you.
ocornut commented 2016-04-11 23:05:40 +00:00 (Migrated from github.com)

Hello,

I will look into it. The solution is indeed around the spot you pointed but those lines have historically been tricky to get right, scissoring rectangles do not seem to behave the same with all renderers.

Are you using a renderer from one of the example?

Here's a repro (please try to submit a repro for subsequent bugs, thanks!)

ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0));
ImGui::Begin("Bug #582", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar);
ImGui::Image(ImGui::GetIO().Fonts->TexID, ImVec2(100,100), ImGui::GetFontTexUvWhitePixel(), ImGui::GetFontTexUvWhitePixel());
ImGui::End();
ImGui::PopStyleVar(2);

OpenGL: the white square is 99x99 because of clipping.
opengl2

DirectX9, DirectX11, square is 100x100
dx9

EDIT Fixed attachments, first post had twice the same picture.

Hello, I will look into it. The solution is indeed around the spot you pointed but those lines have historically been tricky to get right, scissoring rectangles do not seem to behave the same with all renderers. Are you using a renderer from one of the example? Here's a repro (please try to submit a repro for subsequent bugs, thanks!) ``` ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); ImGui::Begin("Bug #582", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar); ImGui::Image(ImGui::GetIO().Fonts->TexID, ImVec2(100,100), ImGui::GetFontTexUvWhitePixel(), ImGui::GetFontTexUvWhitePixel()); ImGui::End(); ImGui::PopStyleVar(2); ``` OpenGL: the white square is 99x99 because of clipping. ![opengl2](https://cloud.githubusercontent.com/assets/8225057/14445233/b881b294-004b-11e6-9424-8b75d8df1a96.png) DirectX9, DirectX11, square is 100x100 ![dx9](https://cloud.githubusercontent.com/assets/8225057/14445200/6ffb19ac-004b-11e6-8584-e8186da50a1c.png) _EDIT_ Fixed attachments, first post had twice the same picture.
ocornut commented 2016-04-11 23:32:14 +00:00 (Migrated from github.com)

Right now in my preliminary test it seems that removing both +0.5f works, but that leaves me with the question "why did I add them?".

Revision: 6e4d959953
Date: 30/09/2015 21:30:27
Message: Window: fixed window lower-right clipping limit so it plays more friendly with both OpenGL and DirectX coordinates. Not sure about this. Hmm.

--    ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f);`
++    ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y);

Note the "not sure about this", I rarely write that sort of thing in my commit message so something must have smelled fishy at the time already.

Revision: ad00d88923
Date: 25/08/2015 16:01:33
Message: Window clipping rect fixes (for child windows with borders among others)

--     ImVec4 clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Rect().Max.x+0.5f-window->WindowPadding.x*0.5f, window->Rect().Max.y-1.5f);
++     ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f);
    if ((flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_ShowBorders))
        clip_rect.Min += ImVec2(1.0f,1.0f);

Something else to note: borders were changed to lay WITHIN bound of every widget/window (see b49a985324 which happened after those two commits above), so this will affect this specific use case. Here the visible portion is 98x98. I don't intend to change that as having border lay inside made lots of code much simpler and bug-free. So if you have borders and you want zero-padding you can compensate by adding +1 padding on each axis.
with borders

This is still a little confusing, I will investigate more tomorrow and probably apply fix of removing the two +0.5f but I ought to clarify this back and forth.

Right now in my preliminary test it seems that removing both +0.5f works, but that leaves me with the question "why did I add them?". Revision: 6e4d9599532360878469b61a383119b06f1cb46e Date: 30/09/2015 21:30:27 Message: Window: fixed window lower-right clipping limit so it plays more friendly with both OpenGL and DirectX coordinates. Not sure about this. Hmm. ``` -- ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f);` ++ ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y); ``` Note the "not sure about this", I rarely write that sort of thing in my commit message so something must have smelled fishy at the time already. Revision: ad00d88923072413b7cb2be8f123e224995aae02 Date: 25/08/2015 16:01:33 Message: Window clipping rect fixes (for child windows with borders among others) ``` -- ImVec4 clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Rect().Max.x+0.5f-window->WindowPadding.x*0.5f, window->Rect().Max.y-1.5f); ++ ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f); if ((flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_ShowBorders)) clip_rect.Min += ImVec2(1.0f,1.0f); ``` Something else to note: borders were changed to lay WITHIN bound of every widget/window (see b49a985324981ef77caf12f1eacf12b6bb93cd80 which happened after those two commits above), so this will affect this specific use case. Here the visible portion is 98x98. I don't intend to change that as having border lay inside made lots of code much simpler and bug-free. So if you have borders and you want zero-padding you can compensate by adding +1 padding on each axis. ![with borders](https://cloud.githubusercontent.com/assets/8225057/14445511/ca27f9ac-004d-11e6-9ee7-7392aa6f9e0d.png) This is still a little confusing, I will investigate more tomorrow and probably apply fix of removing the two +0.5f but I ought to clarify this back and forth.
ocornut commented 2016-04-11 23:59:13 +00:00 (Migrated from github.com)

The reason for all this fishyness is because the renderers in examples/ are casting the floating point values to int which is a truncation. The OpenGL example is passing (float)x1 and (float)(x2-x1) whereas the DirectX examples are passing (float)x1 and (float)x2 which leads to different results. It is the OpenGL example behavior which led to the faulty commit linked at the top of the previous message. In addition, relying on the cast to preserve the integer value here is rather unreliable.

Will first soon. If it works for you can locally remove the +0.5f locally. Sorry fot the wall of text, @ottogithub

The reason for all this fishyness is because the renderers in examples/ are casting the floating point values to int which is a truncation. The OpenGL example is passing (float)x1 and (float)(x2-x1) whereas the DirectX examples are passing (float)x1 and (float)x2 which leads to different results. It is the OpenGL example behavior which led to the faulty commit linked at the top of the previous message. In addition, relying on the cast to preserve the integer value here is rather unreliable. Will first soon. If it works for you can locally remove the +0.5f locally. Sorry fot the wall of text, @ottogithub
ottoGithub commented 2016-04-12 03:14:31 +00:00 (Migrated from github.com)

As you say, I indeed use OpenGL as My renderer。When I test the same code with directX9, it works fine.
Thank you very much for your detailed explanation.
@ocornut

As you say, I indeed use OpenGL as My renderer。When I test the same code with directX9, it works fine. Thank you very much for your detailed explanation. @ocornut
ocornut commented 2016-04-14 08:47:11 +00:00 (Migrated from github.com)

I'll keep this open if you don't mind because I intend to fix this :)

I'll keep this open if you don't mind because I intend to fix this :)
ocornut commented 2016-04-23 12:24:50 +00:00 (Migrated from github.com)

Should be fixed now.
Rounding the floating point values to ensure user-side operations yield to correct results.

Should be fixed now. Rounding the floating point values to ensure user-side operations yield to correct results.
ocornut commented 2016-04-29 18:53:03 +00:00 (Migrated from github.com)

Realized that the rounding causes issues with negative clipping coordinates.
Although it doesn't make sense to use negative values in the typical case, I'm rendering my game via imgui and sometimes transports world-space coordinates in those fields so this is causing problem. It might be more relevant to not transform the data in the PushClipRect() function and rely on caller doing the right thing.

Realized that the rounding causes issues with negative clipping coordinates. Although it doesn't make sense to use negative values in the typical case, I'm rendering my game via imgui and sometimes transports world-space coordinates in those fields so this is causing problem. It might be more relevant to not transform the data in the PushClipRect() function and rely on caller doing the right thing.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#582
No description provided.