-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Window shadows #1329
Comments
It's not supported at the moment but here's a few ideas. The most simple / basic approach would be to draw a transparent rounded rectangle under the window shape. You can hardcore this in Adding a gradient would look better but requires more work setting up the vertices. There's also the question that you may not want the shadow to actually draw behind the window because that is a waste of fill-rate, and solving this (especially as anti-aliased rounded borders are involved) makes the geometry more complex to create. |
I have been playing exactly with shadows lately 😃 A few approaches that I have been trying:
You can see all of them here: Approach 1) is great but you need to handle textures and generate a new one every time you need a different combination of sigma (shadow kernel) and rectangle size. And probably you will need to merge them inside the main font texture to avoid too many draw calls. You're also wasting some fill rate as pointed out by Omar. You can get really nice looking shadow with very small texture (even 32x32 is great). You could potentially generate only a single corner and re-use it everywhere playing with UV coordinates to even lower down the memory usage. Approach 2) is probably the best so far, for a small shadow you can do very good approximation with about ~23 triangles for each rectangle with shadow. It's also very easy to implement and you have zero fill rate waste. For a larger sigma you need more triangles, potentially even double them but should be ok with most triangle budgets unless you plan to shadow everything in your UI. Approach 3) looks great but wastes too many triangles, approach 2) can do the same with a lot less. If you need a formula to generate the correct shadow for a rounded rectangle, you could take a look at http://madebyevan.com/shaders/fast-rounded-rectangle-shadows/ Beware, there's a typo in the formulas referenced in this article!
The line
should really be
|
Thank you for taking your time for such an exhaustive explanation. I had in mind a lot of ideas but all of them included shaders which I'm trying to avoid for the reasons you said. This post pointed me into the right direction. |
Thanks @Pagghiu for looking into this, amazing stuff. I see you have a [ ] Linear Spread checkbox. Wouldn't a simple distance + power curve give good enough results compared to that function you linked above? |
Thanks Omar, sure, if I will try to find time to cleanup it a little bit and share. The linear checkbox activates a linear approximation of the shadow falloff, and it's indistinguishable from the "correct" one for small sigmas. For bigger sigma, the linear approximation is not good, the results are clearly banded and clamped incorrectly. |
I have not been able to spend additional time cleaning and optimising the shadow mesh generation, or adding other features like generation for rounded boxes but as I've been promising, here is the code. There's a self contained sample in the opengl2_example folder Hope this is useful to someone! |
Beautiful shot, it looks quite similar to native macOS windows shadowing. I hope this makes its way inside the master someday! 😄 |
It will definitively, this is still an early draft and I would like to focus on finishing Docking/Viewport before moving to new pastures, then steer the internals to make those changes possible (refactor the Render functions, etc.). |
+1 for shadows in master! |
Pushed a branch with work by @ShironekoBen on a different approach for shadows. https://github.com/ocornut/imgui/commits/features/shadows (A) (B) [edit] If we limit the amount of real-time tweaking or limit the scope of (B) or leave it to the app to reload, we can commit most of (A) ahead of time. Doing the full version of (B) will allow for dynami tweaking of shadow settings and be the building block for other features. Shots Previous "hacked style" with those shadows (replicating screenshots above) With regular "Light" style as-is from master (same shadows, just a less sexy style) There's probably more work to provide here. The irony is that this may over time become somehow less useful for apps transitioning to use more of the platform/multi-viewport feature. However one of the aim for this is to also provide a low-level ImDrawList API which can be also used for custom widgets. |
Noticed the window shadows feature branch is gone (https://github.com/ocornut/imgui/commits/features/shadows is a dead link now), and the changes have not been pulled into master. |
@camplowell We've been working on this, I only removed it from public repo to avoid pushing to two locations as I forgot I mentioned it here. Pushed again now. |
Note that We're still working on the API, but the |
that's seriously beautiful 😃 |
Makes you want the docking/viewport thing to be done already!!! |
I haven't tested this branch yet or looked at the API for it, but would this also allow adding shadows to text rendered via eg. drawlists? |
Hm, in it's current state, only if the text was being drawn with convex primitives as opposed to the font texture... and even then I wouldn't be surprised if trying to deal with text brought out all the worst kinds of edge-cases! |
I have made a merge request for text and window shadows using SDF, see MR 4056. In that MR rounded rectangle shadows (such as for windows) are also calculated with SDF and same shaders as used for text glyphs. Another upside from this is that there are no artifacts (as can be the case with some pre-generated shadow solutions). |
This would really take dear imgui to the next level! |
It’s not as impactful as I hoped for three reasons:
|
I'd agree. If we allow shadows on other stuff like headers buttons that becomes more interesting but windows only makes sense if we are in control of drawing a large portion of the screen or if we're rending over a game which is still the prime use-case. In docking they can be nice if you do like tiling window managers do and force spacing between window tiles. However, that's not currently how docking works as far as I know and I doubt anybody wants to redo the docking component one more time for something like this. |
Shadows in imGUI are very cool ! @ocornut, do you think it would be a good idea ? I have just 2 problems for the moment :
Thanks a lot ! |
I haven't looked but I'm guessing that the shadow geometry is not taking rounding into account. |
Tried shadow branch and it's working amazingly well on my window components ! Thank you ! |
If anybody is looking for a quick and dirty way of doing this with minimal set up you can use this 9 slice (technically 8 slice) method. Preview: From my gist (which includes the texture I'm using): /*
* This function assumes the existence of an active Dear ImGui window
*/
void RenderDropShadow(ImTextureID tex_id, float size, ImU8 opacity)
{
ImVec2 p = ImGui::GetWindowPos();
ImVec2 s = ImGui::GetWindowSize();
ImVec2 m = {p.x + s.x, p.y + s.y};
float uv0 = 0.0f; // left/top region
float uv1 = 0.333333f; // leftward/upper region
float uv2 = 0.666666f; // rightward/lower region
float uv3 = 1.0f; // right/bottom region
ImU32 col = (opacity << 24) | 0xFFFFFF;
ImDrawList* dl = ImGui::GetWindowDrawList();
dl->PushClipRectFullScreen();
dl->AddImage(tex_id, {p.x - size, p.y - size}, {p.x, p.y }, {uv0, uv0}, {uv1, uv1}, col);
dl->AddImage(tex_id, {p.x, p.y - size}, {m.x, p.y }, {uv1, uv0}, {uv2, uv1}, col);
dl->AddImage(tex_id, {m.x, p.y - size}, {m.x + size, p.y }, {uv2, uv0}, {uv3, uv1}, col);
dl->AddImage(tex_id, {p.x - size, p.y }, {p.x, m.y }, {uv0, uv1}, {uv1, uv2}, col);
dl->AddImage(tex_id, {m.x, p.y }, {m.x + size, m.y }, {uv2, uv1}, {uv3, uv2}, col);
dl->AddImage(tex_id, {p.x - size, m.y }, {p.x, m.y + size}, {uv0, uv2}, {uv1, uv3}, col);
dl->AddImage(tex_id, {p.x, m.y }, {m.x, m.y + size}, {uv1, uv2}, {uv2, uv3}, col);
dl->AddImage(tex_id, {m.x, m.y }, {m.x + size, m.y + size}, {uv2, uv2}, {uv3, uv3}, col);
dl->PopClipRect();
} You can call this after your window's |
It was mentioned that shadows are less relevant for dark themes, however: what about reusing this effort to also be able to render a "glow" behind the window? |
@dromer - precisely my usecase. |
This is exactly what shadows are doing. This cannot be finished and merged until #3761 is done, and the polygon clipper of current shadow impl. is ihmo too complex for its own good. Without further resources I can't expect this to be usable anytime soon. |
Does anyone know what would be the best approach to render drop shadow behind the windows?
The text was updated successfully, but these errors were encountered: