Transparent window example
I recently revisited the implementation of transparent windows and noticed that in the wgpu documentation (https://docs.rs/wgpu-types/27.0.1/wgpu_types/instance/struct.Dx12BackendOptions.html ), the D3D12 backend provides a presentation_system option that allows selecting a SwapchainKind. According to the documentation, using DxgiFromVisual enables transparent window support.
However, wgpu-native does not currently expose this configuration and instead always uses DxgiFromHwnd. I modified the wgpu-native code locally and built a customized version (https://github.com/panxinmiao/wgpu-native/tree/Dx12SwapchainKind) for testing, and the transparent window functionality works correctly.
The only issue is that the initial window content leaves a white background artifact. As shown in the video:
https://github.com/user-attachments/assets/95a7b8d9-6f08-47d7-bfc1-9aa99e996f5b
After resizing the window, the newly exposed regions become properly transparent, but the original region (the part not affected by resizing) keeps showing a white background.
It seems like the leftover data comes from the system-provided initial window framebuffer, which is outside the control of wgpu. In the wgpu render loop, each frame performs a clear operation (clear_value = (0, 0, 0, 0)), so in theory the entire surface should be cleared, but the initial white region remains unaffected.
I have not yet found a solution to this issue.
Additionally, we may need to consider adding API support for transparent windows and transparent rendering in RenderCanvas and pygfx.
Relaated: https://github.com/pygfx/rendercanvas/issues/29
If someone wants to test it, here is the wgpu_native.dll build that I compiled.
wgpu_native-release.zip
This is a fun feature, reminds me of shader glass: https://github.com/mausimus/ShaderGlass, not sure how they access the swap chain texture below.
side note: I believe transparent canvas works in pyodide already.. Might try that later.
side note: I believe transparent canvas works in pyodide already.. Might try that later.
If I’m not mistaken, the Pyodide environment likely uses an off-screen style rendering setup, where the actual render target is a custom WGPU texture framebuffer rather than a system surface swapchain texture. As a result, transparency should be supported naturally.
If I’m not mistaken, the Pyodide environment likely uses an off-screen style rendering setup
Yeah, it's really just a texture provided by the browser. Which is then composited by the browser with the other content to produce the final browser content. Which is actually stored in a texture, provided by the OS, and which is then composited with the other windows on the desktop, and then rendered to screen :)
I found that when using borderless mode with:
glfw.window_hint(glfw.DECORATED, False)
the transparent window works perfectly.
https://github.com/user-attachments/assets/7ea07f71-ac31-48f8-80c4-5a2c7331d7cf
However, when the window is decorated, the initial white background issue persists. I’ve tried various approaches, but it seems impossible to resolve so far.
Additionally, it seems that the Qt backend does not support transparent windows. I tried using:
canvas.setAttribute(QtCore.Qt.WidgetAttribute.WA_TranslucentBackground, True)
Similar to the GLFW case, the initial region shows a white background, but the area after resizing remains non-transparent and appears black instead:
https://github.com/user-attachments/assets/4d8e4279-7eb1-459c-a0f0-7a483f4a8478
And when I add:
canvas.setWindowFlags(QtCore.Qt.FramelessWindowHint)
(which I believe corresponds to glfw.window_hint(glfw.DECORATED, False)),
the application runs but no window content is visible at all.