Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ripple effect Clipping/Overdrawing/Adavced poly to avoid overdraw. #3997

Open
Gringoniceguy opened this issue Apr 1, 2021 · 6 comments
Open

Comments

@Gringoniceguy
Copy link

Gringoniceguy commented Apr 1, 2021

Version/Branch of Dear ImGui:

Version: Current
Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_directx9.cpp + imgui_impl_win32.cpp (or specify if using a custom engine/back-end)
Compiler: msvc (if the question is related to building or platform specific features)
Operating System: window 10

My Issue/Question:

Hello, i am trying to create a ripple effect in Dear ImGui.
Now the issue is that i cannot avoid the circle drawing over the corners of the rounded rect, i have solved this using the inverted rect method mention here.
The issue with this is that it does not anti-alias, it does not do this due to it cutting off all alpha is there a alternative to this?
I cannot see how this problem can be solved with out allowing the circle to also fill that area, i do thought have a few suggestions for a alternative/fix

  1. Circle and rounded clipping, you said that this was not going to happen so mostly likely not viable.
  2. Some how make the anti-alias run after the overdraw.
  3. Instead of using a circle we can use a polygon and only allow it to fill the rect, i think this is super hard as it would require some advanced math.

Is any of this a good idea or should i go back to the drawing board?

Screenshots/Video

This is the thing i want todo
unnamed

Standalone, minimal, complete and verifiable example: (see #2261)

Dont really see how this fits, would have made it a discussion as it is not really a issue.

EDIT:
Not very good example in reality i wont be using a border else i could just draw it above.

@ocornut
Copy link
Owner

ocornut commented Apr 6, 2021

I don't have an easy answer to this, when you involve transparency and rounded shapes things tend to become tricky.

Answer (3) seemingly is the right solution. Actually @ShironekoBen did implement arbitrary clipping as part of the experimental shadow branch (#1329). It does work but it is rather complicated code and that complexity was one of the reason I was hesitant to merge it (the other and main reason being remaining backend work which is also in the work, see #3761, when that's done we will come back to the shadow stuff).

Your request is interesting because it shows a different use of that clipping function and as thus gives us another reason to merge that clipping code.

See AddSubtractedRect(), ClipPolygonShape(), AddSubtractedRect() functions in imgui_draw.cpp
https://github.com/ocornut/imgui/compare/features/shadows#diff-cae83989d4c25e9856fcccd946a85f9276f60655964430213b41230401931c8a

@Gringoniceguy
Copy link
Author

Gringoniceguy commented Apr 17, 2021

Hello, sorry for the late response i was focusing on some other parts of the project.
I was not able to make this work, this might be due to me not really being that advanced in math.
As i have understood it the function AddSubtractedRect() subtracts a path from a rectangle, so much like drawing a inverse rounded rectangle.
I cant see how this wound not be affected by antialiasing either.

I was not able to make this work and just got really weird results, this is what i got
billede
this is with pathing a full circle.

I don't believe i know enough to attempt to write my own function building on ClipPolygonShape(), so i am stuck here.

Is there something i seriously misunderstood or is it something else.
EDIT: I found out that the rect needs to be twice the y for some reason now it draws the full circle, yet with still the same issue.

@givemesomecake
Copy link

I visited the link you shared and found the shared function, but it was not very good and it was not doing my job well enough so I was able to make it what I wanted by doing a few changes on this function and I wanted to share it with you.

void ImDrawList::AddInvertedRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{
    if ((col & IM_COL32_A_MASK) == 0)
        return;
    if (rounding > 0.0f)
        PathInvertedRect(p_min, p_max, col, rounding, rounding_corners);
}
void ImDrawList::PathInvertedRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{
    rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f) - 1.0f);
    rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f) - 1.0f);

    if (rounding <= 0.0f || rounding_corners == 0)
        return;
    else
    {
        const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f;
        const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f;
        const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f;
        const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f;
        PathLineTo(a);
        PathArcTo(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, -3.0, -1.5);
        PathFillConvex(col);

        PathLineTo(ImVec2(b.x, a.y));
        PathArcTo(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, -1.5, -0.205);
        PathFillConvex(col);

        PathLineTo(ImVec2(b.x, b.y));
        PathArcTo(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 1.5, 0.205);
        PathFillConvex(col);

        PathLineTo(ImVec2(a.x, b.y));
        PathArcTo(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3.0, 1.5);
        PathFillConvex(col);
    }
}

The float values ​​I use here are not completely perfect, but they draw more efficiently than the shared PathArcToFast function. I leave a visual of the results below

aa

@Gringoniceguy
Copy link
Author

I dont know how you even managed to make this run, as it trigger a assert due to a_min being bigger than a_max. Anyways it still does not address the anti alias issue and only helps rounding(on the shadows branch as master already has good rounding with the new PathArcToFast).

@ocornut
Copy link
Owner

ocornut commented Apr 23, 2021

I dont know how you even managed to make this run, as it trigger a assert due to a_min being bigger than a_max.

See #4030

@Gringoniceguy
Copy link
Author

Oops, sadly still does not fix anti-aliasing not working only makes the rounding better on the old version[Of Dear ImGui] as the new version[Of Dear ImGui] looks just fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
@ocornut @Gringoniceguy @givemesomecake and others