imgui
imgui copied to clipboard
Setting background alpha for specific viewports in glfw and win32/dx11 [SOLVED]
I want to create a transparent / overlay viewport. With the following code it is correctly semi-transparent when over the main viewport (ie can see the main viewport through it). However as soon as it is dragged outside the main viewport and becomes a single-window viewport it immediately becomes opaque. I've tried these three variations for setting the alpha I've tried with glfw and win32 dx11,dx12 with identical results win32/ogl3 is the odd one out as the window appears to entirely disappear if it is in the main viewport (but is still opaque if it's outside the bounds)
ImVec4 overlayColour = ImVec4(1.0f, 0.4f, 0.4f, 0.25f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, overlayColour); // 1 (outside begin)
ImGui::SetNextWindowBgAlpha(0.25f); // 2
if (ImGui::Begin("alpha", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse)) {
ImGui::PushStyleColor(ImGuiCol_WindowBg, overlayColour); //3 (inside begin)
ImGui::PopStyleColor();
}
ImGui::End();
ImGui::PopStyleColor();
Dear ImGui currently does not support secondary viewports with transparent backgrounds. (Alpha is explicitly ignored for viewport-owned windows)
See also https://github.com/ocornut/imgui/pull/2766
win32/ogl3 is the odd one out as the window appears to entirely disappear if it is in the main viewport (but is still opaque if it's outside the bounds)
This sounds like a bug, but I cannot reproduce it on my machine with example_win32_opengl3
on latest docking (a88e5be7f478233e74c72c72eabb1d5f1cb69bb5).
Oh sorry I think I may have been unclear / still struggling with the window naming terminology - I'm totally happy with the behaviour of the owned viewports I was referring specifically to the effect after dragging an ImGui Window outside the boundaries of a Host Viewport when it becomes/is a Single-Window Viewport
I want this: https://github.com/ocornut/imgui/pull/2766
but it looks like this isn't currently supported as per this: https://github.com/ocornut/imgui/issues/5218
Regarding your helpful response (which provided me the path to clarify that issue had already been described) Correct me if I'm wrong, but the issue is not this section of code explicitly preventing transparency in single-window viewports
If that were the case it should be possible to force everything to be transparent with something like the following at approx L6349. However this doesn't work
bg_col = (ImU32)(255 | 100 << 8 | 100 << 16 | 50 << 24);;
bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
I've made a bit of (maybe) progress - in that I can now make the main viewport transparent - but it doesn't work for single-window viewports BTW the following requires GLFW 3.3.8 - it doesn't work with the 3.2 shipped with ImGui
Inside the client bounds of the main-viewport it's perfect
But if it is moved outside those bounds the transparency fails The blue is the background of the Visual studio window behind From the menu bar down (with green semitransparency is the main viewport The red is the still opaque :-( single window (supposed to be a transparent overlay)
Getting this far only requires a small change to core code
// transparency hint goes before glfwCreateWindow
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
window = glfwCreateWindow(1650, 900, "ABCInsights", NULL, NULL);
// alpha is respected
ImVec4 clear_color = ImVec4(0.0f, 1.0f, 0.0f, 0.25f);
incidentally for those not sure it only takes a minute to upgrade - you just download glfw replace the following files and change the linker target to lib-vc2022 (or whatever version you're using). https://www.glfw.org/download.html
Finally got a couple of hours to get back to this question. I can now set and/or change the transparency for any chosen single viewport to an arbitrary value at my whim :-) Unfortunately I couldn't do it without a (very minor) modification to the core imgui code and a global :-( If the transparent viewport is created over the main viewport it will inherit the main viewport alpha until it is at least once dragged outside the main viewport bounds - but I don't really care about that so haven't bothered to try and fix it. Otherwise I'm pretty happy with it :-) NB I'm using Win10 so this is a platform specific solution.
in "imgui_impl_opengl3.h"
in "imgui_impl_opengl3.cpp" remove static from the declaration so it becomes
void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
//New functions
std::map <ImGuiID, int> windowIDToAlpha;
void addWindowToMap(ImGuiID windowID, int alpha) {
windowIDToAlpha[windowID] = alpha;
}
void makeWindowTransparent(GLFWwindow* window, int alpha = 255)
{
HWND hwnd = glfwGetWin32Window(window);
if (hwnd)
{
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
}
}
// ImGui platform interface allows to set a hook for viewport creation
// This hook is called as each viewport is created
void ImGuiPlatform_CreateWindow_WithTransparency(ImGuiViewport* viewport) {
ImGui_ImplGlfw_CreateWindow(viewport); // Create window with default platform_create_window
// Set transparency for the window if it is in the map
if (windowIDToAlpha.contains(viewport->ID)) {
int viewPortAlpha = windowIDToAlpha[viewport->ID]; // 0 = transparent, 255 = opaque
makeWindowTransparent((GLFWwindow*)viewport->PlatformHandle, viewPortAlpha); // Make the window transparent as well
}
}
In the main setup code flow
// Setup Platform/Renderer backends
...
// ImGui platform interface allows to set a hook for viewport creation
// Overwrite the platform interface function to create a window
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = ImGuiPlatform_CreateWindow_WithTransparency;
In the rendering loop
// Create an ImGui window
if (ImGui::Begin("Transparent Viewport"))
{
static bool init = true;
if (init) {
init = true;
addWindowIDToAlphaMap(ImGui::GetCurrentWindow()->Viewport->ID, 25);
}
ImGui::Text("This is a special transparent viewport\n(unless it's docked when it inherits parent transparency)");
}
ImGui::End();
@dgm3333 I tried your solution on my directx9 win32 app. It gave me IM_ASSERT error and crashed when i dragged the window outside of the main viewport.