Floating, draggable QML control panels (ncca.ngl.qml) layered over a live 3D
teapot viewport — the WebGPU version of GUIDemos/QMLOverlayApp.
A QMainWindow stacks two widgets:
- The 3D viewport (
PyNGLScene) ancca.ngl.webgpu.WebGPUWidgetthat renders a diffuse lit teapot offscreen into a numpy buffer and blits it viaQPainter. It exposesset_model_matrix(Mat4),set_view_matrix(Mat4)andset_colour(r, g, b)slots. - A transparent overlay (
OverlayQuickWidget, aQQuickWidget) carrying three floating panels built fromncca.ngl.qml'sTransformWidget,RGBColourWidgetandLookAtWidget, plus a theme picker. Each panel drives the teapot directly through the slots above: model matrix, colour, and the camera's view matrix.
Because the overlay is transparent, clicks that miss every panel are
hit-tested (PanelRegistry) and forwarded down to the WebGPU scene. Panel
positions and the selected theme persist between runs via QML's Settings.
QMLFloatingWidgets tried to render the teapot with a QQuickFramebufferObject
inside a pure Qt Quick scene graph. Under Qt 6's RHI/Metal backend that class
never obtains a valid OpenGL context (its renderer is never invoked, and forcing
the OpenGL backend segfaults on QOpenGLFramebufferObject construction).
QMLOverlayApp worked around this by rendering with a QOpenGLWidget, but that
forces the whole top-level surface to composite via OpenGL, so the overlay
QQuickWidget then also has to be forced onto the OpenGL scene graph backend
(QQuickWindow.setGraphicsApi(OpenGL) + a QSurfaceFormat) or it renders
nothing under Metal.
This demo removes that constraint entirely. WebGPUWidget is a plain
QWidget — it renders with wgpu offscreen and never creates a Qt OpenGL
surface. With no OpenGL top-level surface in play, the overlay QQuickWidget
uses Qt's default RHI/Metal backend directly: no setGraphicsApi, no
QSurfaceFormat, no backend forcing at all.
main.py— builds the window, stacks the WebGPU scene and the transparent QML overlay, wires up mouse-forwarding hit testingPyNGLScene.py— theWebGPUWidgetteapot scene and its matrix/colour slotsTeapotPipeline.py— the diffuse render pipeline and uniform buffersDiffuseShader.wgsl— a minimal single-light diffuse shader (the WebGPU equivalent of PyNGL'sDefaultShader.DIFFUSE)panel_registry.py— screen-rect registry used for click-through hit testingmain.qml— the panels, themes, and layout persistenceDraggablePanel.qml— drag-by-handler chrome with theme-able body
uv run GUIDemos/QMLWebGPUOverlay/main.pyGUIDemos/QMLOverlayApp— the OpenGL version of this same overlay appGUIDemos/QMLFloatingWidgets— the pure-QML attempt kept as a documented reference for the RHI limitation this demo avoids
- QQuickWidget (Qt for Python) — the transparent QML layer over the viewport.
- Qt QML Applications — QML language and application structure.
- wgpu-py documentation — offscreen rendering with the Python WebGPU binding.
