シーングラフ - QML下のVulkan

Qt Quick シーン下で Vulkan を直接レンダリングする方法を示します。

注: この例をコンパイルするには SDK が必要です。インストール方法については、Vulkan Integrationを参照してください。

概要

この例では、QQuickWindow::beforeRendering() とQQuickWindow::beforeRenderPassRecording() シグナルを使用して、Qt Quick シーン下でカスタム Vulkan コンテンツを描画します。QMLは、上にテキストラベルをレンダリングするために使用されます。

この例は、OpenGL Under QMLDirect3D 11 Under QMLMetal Under QMLの例とほとんど同じです。

QMLを利用することの詳細は、カスタムVulkanレンダリングの詳細を掘り下げることなく、このドキュメントでカバーされます。

QMLからのVulkanレンダリングへの影響

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

しきい値t を QML に公開するために、VulkanSquircle の定義で、Q_OBJECTQ_PROPERTYQML_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つのシグナルがあります。

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

解決策: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コンテンツをレンダリングするもう1つの方法は、QQuickWindow::afterRendering ()とQQuickWindow::afterRenderPassRecording ()シグナルに接続することです。

サンプルプロジェクト @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。