Skip to content

Instantly share code, notes, and snippets.

@kpcftsz
Last active January 6, 2024 17:52
Show Gist options
  • Save kpcftsz/b044b43213564f2fb32e8685a50daf6a to your computer and use it in GitHub Desktop.
Save kpcftsz/b044b43213564f2fb32e8685a50daf6a to your computer and use it in GitHub Desktop.
K.I.S.S. Dear ImGui drop shadows - dead simple

K.I.S.S. Dear ImGui drop shadows

This is a stupid simple method of implementing drop shadows in Dear ImGui.

First make a 9-slice texture that'll serve as your drop shadow. Here is the one I'm using for example:

alt

Load it however you like. I'm not going to spoonfeed this since texture loading methods vary based on what graphics back-end ImGui is using. In any case, you'll need to have an ImTextureID available.

Usage Example

if (ImGui::Begin("Example"))
{
  RenderDropShadow(shadow_tex, 24.0f, 100);
  // Rest of your contents here...
  ImGui::End();
}

If you want to abstract things further, you can implement your own Begin() and use it in place of ImGui's. This will make it easier to do other style adjustments as well (for instance I like changing the border color, and I have some rules for when I can and cannot draw a drop shadow, e.g. docking)

namespace MyGui {

bool Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
  bool active = ImGui::Begin(name, p_open, flags);
  RenderDropShadow(...);
  return active;
}

} // namespace MyGui
void Render()
{
  if (MyGui::Begin())
  {
    // Rest of your contents here...
    ImGui::End();
  }
}
/*
* 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();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment