Add support for transparent backbuffers to GLFW contexts (OpenGL3 and Vulkan)
This PR adds support for the transparent backbuffers provided by ImGui.
It expands on the fix proposed in #2693
This is partially a bug-fix and partially a new feature. These changes fix alpha blending issues when drawing ImGui displays over transparent backbuffers, and also adds support for transparent viewports when using the viewport system.
Note that this also updates GLFW to version 3.3.
Example Image

Transparent framebuffer support is added via the ImGuiConfigFlags_TransparentBackbuffers flag.
When used in conjunction with GLFW_TRANSPARENT_FRAMEBUFFER, this flag will bypass some constraints that forced a viewport window's alpha to be 1, and allows for windows to be created that support transparent backbuffers.
The color and transparency of the backbuffer come from the style, specifically ImGuiCol_WindowBg, where w will represent the alpha value of the window being created.
In addition to these changes, there is a small tweak to how the OpenGL3 and Vulkan implementations handle alpha blending to ensure proper blending with a transparent backbuffer.
These tweaks can be easily applied to other APIs that GLFW supports, the only change is to update the blend mode and get the clear color from the style instead of being hard coded.
WARNING the x64 lib for glfw3.lib was not built for vc2010, instead it was built for vc2012. The 32 bit version is still 2010
Hello Shawn,
Writing down some notes for myself, though I think it should not necessarily for you to rework the PR right now (we have all the info we need in the PR, thanks!).
-
Changing
dstAlphaBlendFactorfromVK_BLEND_FACTOR_ZEROtoVK_BLEND_FACTOR_ONEis incurring a cost perhaps that could be done based on that flag. -
The examples would need to be made to compile without support for that flag. So maybe the main.cpp code would need some ifdef, or maybe since we don't really need to ship the example with this enabled by default, we can simply comment those lines out in the final version which we will merge into master.
-
We can support the feature without updating GLFW in the repository (thanks for making it a separate commit as we can easily strip it out). Embedding those binaries in the first place was slightly questionable but also very intentful as it allowed us to provide examples that "just works". Later we'll try to adopt another strategy while preserving the "it just works" property. Short-term there's no need to burden the git history with binary data.
What you could help with:
- Provide the commit to make this work with SDL back-end.
- Provide the commit to make this work with Win32 and variety of DX back-ends.
Thank you!
We've now merged the blending fixes to multiple backends and premulitiplied clear color in examples, see bda12e5 and 6a161b8.
However there's some remaining related work and various ideas of this PR are not fulfilled yet.
Some thoughts:
- This PR will now conflict but don't worry about it. We're keeping the PR open mostly as a reminder of the things to do.
- Vulkan: In our testing I couldn't get any effect with altering
compositeAlpha, andcap.supportedCompositeAlphaalways only had the VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR bit set. - We won't need to update GLFW in the repository (increasingly aiming at people using their own version of GLFW, now that
vcpkgis a thing).
What I think we will do later:
- Add a Backend flags to let know of support for this (e.g.
ImGuiBackendFlags_PlatformHasTransparency). - Add support for it in backends. GLFW: Easy. Win32: Easy-ish, need to work out the helper that doesn't requires recent SDK nor runtime dependency on recent windows (got this half done).
- Add a Config flag to allow application to enable this (e.g.
io.ConfigViewportsAllowTransparentnowadays we add new config fields inioas they are more flexible). - Add a Viewport flag to let Backend know of a request to make the window support composition, e.g.
ImGuiViewportFlags_Transparent. Technically backend could pollio.ConfigViewportsAllowTransparentbut it will be more flexible and future-proof to copy this to the viewport. - Figure out what to do with Vulkan's
compositeAlpha. - Figure out how to test this with DX12 (supposedly setting
DXGI_SWAP_CHAIN_DESC1'sAlphaModetoDXGI_ALPHA_MODE_PREMULTIPLIEDorDXGI_ALPHA_MODE_STRAIGHTbut couldn't get it to work). - Decide on a standardized way to pass on clear color to the backend. I feel it may be simpler to add in a ImVec4 in ImGuiViewport for that. May remove the hardcoded (0,0,0,1) change to use one provided by ImGuIViewport struct, instead of polling WindowBG there.
- Figure out how this may or not interact with whole-window alpha settings e.g. support for
platform_io.Platform_SetWindowAlpha()andio.ConfigDockingTransparentPayload.
If this feature gets implemented, it would also allow adding a transparent blur effect to ImGui Windows. Here is how it looks using Acrylic on Windows:

Resizing the window is laggy, but unfortunately, that's a bug in Windows's function SetWindowCompositionAttribute, which is used to achieve this effect.
Alternatively, a less "aggressive" blur could be used, which doesn't have issues with resizing (banding is due to compression, natively the blur is smooth):

Even without a blur effect, the transparent background looks quite cool, though hardly readable:

Edit: I am not suggesting that this should be implemented on the side of ImGui. I only wanted to show off what could be achieved on the user side if transparent viewport framebuffers were a thing.
In relation to the previous comment, a feature that could be implemented by ImGui if transparent viewport framebuffers would be implemented is rounded window borders.
Currently they are always squared off when the window leaves the host viewport, while with transparent framebuffers, the border could be rounded using the alpha channel.
Alternatively, a less "aggressive" blur could be used, which doesn't have issues with resizing (banding is due to compression, natively the blur is smooth):
Wow, so cool. How did this happen?