このページでは

シーングラフ - QML での Vulkan

Qt Quick のシーン内でVulkanを使用して直接レンダリングする方法を説明します。

Qt Quickのシーン内でVulkanを使用してレンダリングされたアニメーション付きスクエクルに、テキストを重ねたもの

注: このサンプルをコンパイルするにはSDKが必要です 。インストールすべきものについては、「Vulkanの統合」を参照してください。

概要

この例では、QQuickWindow::beforeRendering() およびQQuickWindow::beforeRenderPassRecording() シグナルを利用して、Qt Quick シーン内でカスタムVulkanコンテンツを描画します。QMLを使用して、その上にテキストラベルをレンダリングします。

このサンプルは、多くの点で「OpenGL Under QML」、「Direct3D 11 Under QML」、および「Metal Under QML」の各サンプルと同等であり、これらはすべて、異なるネイティブ API を使用しているだけで、同じカスタムコンテンツをレンダリングします。

本ドキュメントでは、カスタムVulkanレンダリングの詳細には立ち入らず、QMLの利用方法について解説します。

QML から Vulkan レンダリングに影響を与える

この例では、QML に公開された値を使用して Vulkan レンダリングを制御する方法を示しています。

しきい値t をQMLに公開するために、VulkanSquircle の定義において、Q_OBJECT 、Q_PROPERTY 、およびQML_ELEMENT マクロを次のように使用します。

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

続いて、publicおよびprivateの項目を宣言します:

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;

続いて、main.qml 内で、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

このt 変数は、最終的にスクイクルを描画するSPIR-Vシェーダープログラムで使用されます。

シグナルを使用したカスタム Vulkan コンテンツのレンダリング

ここで使用されるのは、QQuickWindow::beforeRendering() およびQQuickWindow::beforeRenderPassRecording() シグナルです。

QQuickWindow::beforeRendering() シグナルは、各フレームの開始時、シーングラフがレンダリングを開始する前に発火します。つまり、このシグナルに応答して行われる Vulkan ドローコールはすべて、Qt Quick 項目の下にスタックされます。カスタム Vulkan コマンドは、シーングラフが使用するのと同じコマンドバッファに記録されるため、2 つのシグナルが存在します。

beforeRendering() 関数だけではこれには不十分です。なぜなら、この関数はフレームの開始時に発行されるため、vkCmdBeginRenderPass を使用してrenderpass インスタンスの記録を開始する前になってしまうからです。

解決策:beforeRenderPassRecording() に接続することで、アプリケーション独自のコマンドとシーングラフの骨格が正しい順序で処理されるようになります。

シグナルの接続は、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);

Qt Quick シーンの上にVulkanコンテンツをレンダリングする別の方法として、QQuickWindow::afterRendering()およびQQuickWindow::afterRenderPassRecording()シグナルに接続する方法があります。

サンプルプロジェクト @ 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.