Auf dieser Seite

Szenengraph – Vulkan unter QML

Zeigt, wie man unter einer „ Qt Quick “-Szene direkt mit Vulkan rendert.

Animiertes „Squircle“, gerendert mit Vulkan in einer Qt Quick-Szene mit Textüberlagerung

Hinweis: Zum Kompilieren dieses Beispiels ist ein SDK erforderlich. Informationen zur Installation finden Sie unter „Vulkan-Integration “.

Übersicht

Dieses Beispiel nutzt die Signale „ QQuickWindow::beforeRendering()“ und „ QQuickWindow::beforeRenderPassRecording()“, um benutzerdefinierte Vulkan-Inhalte in einer „ Qt Quick “-Szene darzustellen. QML wird verwendet, um darüber eine Textbeschriftung zu rendern.

Das Beispiel entspricht in den meisten Punkten den Beispielen „OpenGL unter QML“, „Direct3D 11 unter QML“ und „Metal unter QML“ – alle rendern denselben benutzerdefinierten Inhalt, lediglich über unterschiedliche native APIs.

Die Einzelheiten zur Verwendung von QML werden in dieser Dokumentation behandelt, ohne dabei näher auf das benutzerdefinierte Vulkan-Rendering einzugehen.

Beeinflussung des Vulkan-Renderings über QML

Das Beispiel zeigt, wie man Werte, die für QML verfügbar gemacht werden, zur Steuerung der Vulkan-Darstellung nutzt.

Um den Schwellenwert „ t “ für QML verfügbar zu machen, verwenden wir in der Definition von „ VulkanSquircle “ die Makros „ Q_OBJECT “, „ Q_PROPERTY “ und „ QML_ELEMENT “ wie folgt:

class VulkanSquircle : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
    QML_ELEMENT

Anschließend deklarieren wir öffentliche und private Elemente:

public:
    VulkanSquircle();

    qreal t() const { return m_t; }
    void setT(qreal t);

signals:
    void tChanged();

public slots:
    void sync();
    void cleanup();

private slots:
    void handleWindowChanged(QQuickWindow *win);

private:
    void releaseResources() override;

    qreal m_t = 0;
    SquircleRenderer *m_renderer = nullptr;

Anschließend animieren wir in „ main.qml “ den Schwellenwert mithilfe eines „ NumberAnimation “.

    VulkanSquircle {
        SequentialAnimation on t {
            NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
            NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
            loops: Animation.Infinite

Die Variable „ t “ wird letztendlich vom SPIR-V-Shader-Programm verwendet, das die „Squircles“ zeichnet.

Verwendung von Signalen zum Rendern benutzerdefinierter Vulkan-Inhalte

Verwendet werden die Signale „ QQuickWindow::beforeRendering()“ und „ QQuickWindow::beforeRenderPassRecording()“.

Das Signal „ QQuickWindow::beforeRendering()“ wird zu Beginn jedes Frames ausgegeben, bevor der Szenengraph mit dem Rendern beginnt. Das bedeutet, dass alle Vulkan-Draw-Calls, die als Reaktion auf dieses Signal ausgeführt werden, unter den „ Qt Quick “-Elementen gestapelt werden. Es gibt zwei Signale, da die benutzerdefinierten Vulkan-Befehle in denselben Befehlspuffer geschrieben werden, der auch vom Szenengraphen verwendet wird.

Die Funktion `beforeRendering()` allein reicht hierfür nicht aus, da sie zu Beginn des Frames ausgelöst wird, also noch bevor der Start einer ` renderpass `-Instanz mithilfe von ` vkCmdBeginRenderPass` aufgezeichnet wird.

Die Lösung: Durch die Anbindung an `beforeRenderPassRecording()` werden die anwendungsspezifischen Befehle und die Struktur des Szenengraphen in der richtigen Reihenfolge angeordnet.

Die Verbindung der Signale erfolgt über die Funktion ` sync() `:

void VulkanSquircle::sync()
{
    if (!m_renderer) {
        m_renderer = new SquircleRenderer;
        // Initializing resources is done before starting to record the
        // renderpass, regardless of wanting an underlay or overlay.
        connect(window(), &QQuickWindow::beforeRendering, m_renderer, &SquircleRenderer::frameStart, Qt::DirectConnection);
        // Here we want an underlay and therefore connect to
        // beforeRenderPassRecording. Changing to afterRenderPassRecording
        // would render the squircle on top (overlay).
        connect(window(), &QQuickWindow::beforeRenderPassRecording, m_renderer, &SquircleRenderer::mainPassRecordingStart, Qt::DirectConnection);
    }
    m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
    m_renderer->setT(m_t);

Eine weitere Möglichkeit, Vulkan-Inhalte über die „ Qt Quick “-Szene hinweg zu rendern, besteht darin, eine Verbindung zu den Signalen „ QQuickWindow::afterRendering()“ und „ QQuickWindow::afterRenderPassRecording()“ herzustellen.

Beispielprojekt @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.