QQuickRhiItem Class

QQuickRhiItem クラスは、QQuickFramebufferObject に代わるポータブルなクラスで、OpenGL に縛られることなく、Qt Quick でQRhi API とレンダリングを統合することができます。詳細...

Header: #include <QQuickRhiItem>
CMake: find_package(Qt6 REQUIRED COMPONENTS Quick)
target_link_libraries(mytarget PRIVATE Qt6::Quick)
qmake: QT += quick
Since: Qt 6.7
Inherits: QQuickItem
Status: Preliminary

このクラスは開発中であり、変更される可能性があります。

プロパティ

パブリック関数

QQuickRhiItem(QQuickItem *parent = nullptr)
virtual ~QQuickRhiItem() override
bool alphaBlending() const
QQuickRhiItem::TextureFormat colorBufferFormat() const
QSize effectiveColorBufferSize() const
int fixedColorBufferHeight() const
int fixedColorBufferWidth() const
bool isMirrorVerticallyEnabled() const
int sampleCount() const
void setAlphaBlending(bool enable)
void setColorBufferFormat(QQuickRhiItem::TextureFormat format)
void setFixedColorBufferHeight(int height)
void setFixedColorBufferWidth(int width)
void setMirrorVertically(bool enable)
void setSampleCount(int samples)

再実装パブリック関数

virtual bool isTextureProvider() const override
virtual QSGTextureProvider *textureProvider() const override

シグナル

保護された関数

virtual QQuickRhiItemRenderer *createRenderer() = 0
bool isAutoRenderTargetEnabled() const
void setAutoRenderTarget(bool enabled)

再実装された保護された関数

virtual bool event(QEvent *e) override
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
virtual void releaseResources() override

詳細説明

注意: QQuickRhiItem は Qt 6.7 の技術プレビューです。APIは開発中であり、変更される可能性があります。

QQuickRhiItemは、Qt Quickの世界ではQRhiWidget 。これらはどちらもサブクラス化されることを意図しており、QRhi をベースとしたレンダリングで、オフスクリーンのカラーバッファをターゲットとしたレコーディングを可能にします。結果として得られる2D画像は、Qt Quickシーンの残りの部分と合成されます。

注意: QQuickRhiItem は Qt のパブリック API ですが、QShaderQShaderDescription を含む Qt Gui モジュールのクラスQRhi ファミリーは、限られた互換性しか保証していません。これらのクラスにはソース互換性もバイナリ互換性も保証されていません。つまり、APIはアプリケーションが開発されたQtバージョンでのみ動作することが保証されています。しかし、ソース互換性のない変更は最小限にとどめることを目的としており、マイナーリリース(6.7、6.8など)でのみ行われます。qquickrhiitem.h は、QRhi 関連のヘッダを直接含みません。QQuickRhiItemのサブクラスを実装する際にこれらのクラスを使用するには、Qt::GuiPrivate (CMakeを使用している場合)にリンクし、rhi のプレフィックスを付けて適切なヘッダをインクルードしてください(例:#include <rhi/qrhi.h> )。

QQuickRhiItemは、従来のQQuickFramebufferObject 。後者は本質的にOpenGL / OpenGL ESと結びついていますが、QQuickRhiItemはQRhi クラスと連携し、Vulkan、Metal、Direct 3D 11/12、OpenGL / OpenGL ESで同じレンダリングコードを実行できます。概念的にも機能的にも非常に近く、QQuickFramebufferObject から QQuickRhiItem への移行は簡単です。QQuickFramebufferObject は、OpenGL API で直接動作する既存のアプリケーションコードとの互換性を確保するために引き続き使用できます。

注意: Qt Quickシーングラフのsoftware を使用している場合、QQuickRhiItemは機能しません。

ほとんどのプラットフォームでは、シーングラフのレンダリング、つまりQQuickRhiItemによって実行されるレンダリングは、専用のスレッドで行われます。このため、QQuickRhiItemクラスは、アイテムの実装(QQuickItem サブクラス)と実際のレンダリングロジックを厳密に分離しています。QMLに公開されるプロパティやUI関連ヘルパー関数などのアイテムロジックは、すべてQQuickRhiItemサブクラスに配置する必要があります。レンダリングに関連するものはすべて、QQuickRhiItemRenderer クラスに配置する必要があります。レースコンディションや2つのスレッドからの読み書きの問題を避けるために、レンダラーとアイテムは共有変数を決して読み書きしないことが重要です。アイテムとレンダラー間の通信は、主に QQuickRhiItem::synchronize() 関数で行います。この関数は、GUI スレッドがブロックされている間にレンダリング スレッドで呼び出されます。アイテムとレンダラー間の通信にキュー接続またはイベントを使用することも可能です。

アプリケーションはQQuickRhiItemとQQuickRhiItemRenderer の両方をサブクラス化する必要があります。純粋仮想のcreateRenderer() 関数は、QQuickRhiItemRenderer サブクラスの新しいインスタンスを返すように再実装する必要があります。

QRhiWidget と同様に、QQuickRhiItem は自動的にカラーバッファを管理します。通常は 2D テクスチャ (QRhiTexture) で、マルチサンプリングが使用されている場合はQRhiRenderBuffer です。(レンダーバッファは主にOpenGL ES 3.0でマルチサンプリングを可能にするために使用されます)。

テクスチャのサイズは、デフォルトでアイテムのサイズに適応します(device pixel ratio を考慮)。アイテムのサイズが変更されると、テクスチャは正しいサイズで再作成されます。固定サイズが望ましい場合は、fixedColorBufferWidthfixedColorBufferHeight をゼロ以外の値に設定してください。

QQuickRhiItemはtexture providerShaderEffects 、テクスチャプロバイダを消費する他のクラスで直接使用できます。

主な使用例ではありませんが、QQuickRhiItemは、Vulkan、Metal、Direct 3D、OpenGLなどの3DグラフィックスAPIを直接使用するレンダリングコードを組み込むこともできます。QRhi レンダーパス内でネイティブコマンドを記録する方法の詳細については、QRhiCommandBuffer::beginExternal()を参照してください。また、既存のネイティブテクスチャをラップし、その後のレンダーパスでQRhi を使用して使用する方法については、QRhiTexture::createFrom()を参照してください。ネイティブ3D API環境の設定(デバイス拡張など)については、QQuickGraphicsConfiguration も参照してください。また、QWindow::setVulkanInstance() を十分に早い段階で呼び出すことで、QQuickWindow をカスタムQVulkanInstance に関連付けることができます。

注意: QQuickRhiItemは常に、QQuickWindow が使用するのと同じQRhi インスタンスを使用します(ひいては、同じOpenGLコンテキスト、Vulkanデバイスなど)。どの3DグラフィックスAPIを使用するかを選択するには、QQuickWindowsetGraphicsApi() を十分に早い段階で呼び出します。シーングラフが初期化されると、それを変更することはできません。シーン内のすべてのQQuickRhiItemインスタンスは、同じ3D APIを使用してレンダリングされます。

簡単な例

次のQQuickRhiItemのサブクラスを見てください。これは完全な形でここに示されています。これは、透視投影で1つの三角形をレンダリングします。この三角形は、カスタムアイテムのangle プロパティに基づいて回転します。(つまり、例えばQMLのNumberAnimation のようなアニメーションで動かすことができます)

class ExampleRhiItemRenderer : public QQuickRhiItemRenderer
{
public:
    void initialize(QRhiCommandBuffer *cb) override;
    void synchronize(QQuickRhiItem *item) override;
    void render(QRhiCommandBuffer *cb) override;

private:
    QRhi *m_rhi = nullptr;
    std::unique_ptr<QRhiBuffer> m_vbuf;
    std::unique_ptr<QRhiBuffer> m_ubuf;
    std::unique_ptr<QRhiShaderResourceBindings> m_srb;
    std::unique_ptr<QRhiGraphicsPipeline> m_pipeline;
    QMatrix4x4 m_viewProjection;
    float m_angle = 0.0f;
};

class ExampleRhiItem : public QQuickRhiItem
{
    Q_OBJECT
    QML_NAMED_ELEMENT(ExampleRhiItem)
    Q_PROPERTY(float angle READ angle WRITE setAngle NOTIFY angleChanged)

public:
    QQuickRhiItemRenderer *createRenderer() override;

    float angle() const { return m_angle; }
    void setAngle(float a);

signals:
    void angleChanged();

private:
    float m_angle = 0.0f;
};

QQuickRhiItemRenderer *ExampleRhiItem::createRenderer()
{
    return new ExampleRhiItemRenderer;
}

void ExampleRhiItem::setAngle(float a)
{
    if (m_angle == a)
        return;

    m_angle = a;
    emit angleChanged();
    update();
}

void ExampleRhiItemRenderer::synchronize(QQuickRhiItem *rhiItem)
{
    ExampleRhiItem *item = static_cast<ExampleRhiItem *>(rhiItem);
    if (item->angle() != m_angle)
        m_angle = item->angle();
}

static QShader getShader(const QString &name)
{
    QFile f(name);
    return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
}

static float vertexData[] = {
    0.0f,   0.5f,   1.0f, 0.0f, 0.0f,
    -0.5f,  -0.5f,   0.0f, 1.0f, 0.0f,
    0.5f,  -0.5f,   0.0f, 0.0f, 1.0f,
};

void ExampleRhiItemRenderer::initialize(QRhiCommandBuffer *cb)
{
    if (m_rhi != rhi()) {
        m_pipeline.reset();
        m_rhi = rhi();
    }

    if (!m_pipeline) {
        m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
        m_vbuf->create();

        m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64));
        m_ubuf->create();

        m_srb.reset(m_rhi->newShaderResourceBindings());
        m_srb->setBindings({
            QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, m_ubuf.get()),
        });
        m_srb->create();

        m_pipeline.reset(m_rhi->newGraphicsPipeline());
        m_pipeline->setShaderStages({
            { QRhiShaderStage::Vertex, getShader(QLatin1String(":/shaders/color.vert.qsb")) },
            { QRhiShaderStage::Fragment, getShader(QLatin1String(":/shaders/color.frag.qsb")) }
        });
        QRhiVertexInputLayout inputLayout;
        inputLayout.setBindings({
            { 5 * sizeof(float) }
        });
        inputLayout.setAttributes({
            { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
            { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
        });
        m_pipeline->setVertexInputLayout(inputLayout);
        m_pipeline->setShaderResourceBindings(m_srb.get());
        m_pipeline->setRenderPassDescriptor(renderTarget()->renderPassDescriptor());
        m_pipeline->create();

        QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
        resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData);
        cb->resourceUpdate(resourceUpdates);
    }

    const QSize outputSize = renderTarget()->pixelSize();
    m_viewProjection = m_rhi->clipSpaceCorrMatrix();
    m_viewProjection.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
    m_viewProjection.translate(0, 0, -4);
}

void ExampleRhiItemRenderer::render(QRhiCommandBuffer *cb)
{
    QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
    QMatrix4x4 modelViewProjection = m_viewProjection;
    modelViewProjection.rotate(m_angle, 0, 1, 0);
    resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData());

    const QColor clearColor = QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f);
    cb->beginPass(renderTarget(), clearColor, { 1.0f, 0 }, resourceUpdates);

    cb->setGraphicsPipeline(m_pipeline.get());
    const QSize outputSize = renderTarget()->pixelSize();
    cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
    cb->setShaderResources();
    const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
    cb->setVertexInput(0, 1, &vbufBinding);
    cb->draw(3);

    cb->endPass();
}

この単純なクラスは、QRhiWidget で紹介したコードとほとんど同じであることが注目されます。頂点シェーダーとフラグメント・シェーダーも同じです。これらはVulkanスタイルのGLSLソースコードとして提供され、最初にQtシェーダーインフラストラクチャで処理する必要があります。これは、qsb コマンドラインツールを手動で実行するか、CMake のqt_add_shaders()関数を使用することで実現できます。QQuickRhiItemは、アプリケーションに同梱されているこれらの事前処理された.qsb ファイルをロードします。Qt のシェーダー変換インフラストラクチャについての詳細はQt Shader Toolsを参照してください。

color.vert

#version 440
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 v_color;
layout(std140, binding = 0) uniform buf {
    mat4 mvp;
};

void main()
{
    v_color = color;
    gl_Position = mvp * position;
}

color.frag

#version 440
layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 fragColor;

void main()
{
    fragColor = vec4(v_color, 1.0);
}

QML(QML_NAMED_ELEMENT )に公開されると、カスタムアイテムはどのシーンでもインスタンス化できるようになります。(CMakeプロジェクトのqt_add_qml_moduleで指定された適切なURI をインポートした後)

ExampleRhiItem {
    anchors.fill: parent
    anchors.margins: 10
    NumberAnimation on angle { from: 0; to: 360; duration: 5000; loops: Animation.Infinite }
}

より複雑な例についてはScene Graph - RHI Texture Itemを参照してください。

QQuickRhiItemRendererScene Graph - RHI Texture ItemQRhiScene Graph and Renderingも参照して ください。

プロパティ ドキュメント

alphaBlending : bool

QQuickRhiItem とそのレンダラーによって生成されたコンテンツでテクスチャされた四角形を描画するときに、ブレンドが常に有効かどうかを制御する。

デフォルト値はfalse です。これはパフォーマンス上の理由からです。QQuickRhiItemRenderer が不透明な色にクリアされ、アルファが 1 より小さいフラグメントをレンダリングすることがないため、半透明が関係ない場合は、ブレンドを有効にする意味がありません。

QQuickRhiItemRenderer サブクラスが半透明を使用してレンダリングする場合は、このプロパティを true に設定します。

注意: 特定の条件下では、このプロパティの値に関係なく、ブレンドが行われます。例えば、アイテムのopacity (正確には、親チェーンから継承された合成不透明度)が1より小さい場合、このプロパティがfalseに設定されていても、ブレンドは自動的に有効になります。

注意: Qt Quick のシーングラフは、あらかじめ乗算されたアルファに依存しています。例えば、レンダラーで背景を0.5のアルファ値にクリアする場合は、赤、緑、青のクリアカラー値にも0.5を掛けてください。そうしないと、ブレンド結果が不正確になります。

アクセス関数

bool alphaBlending() const
void setAlphaBlending(bool enable)

Notifierシグナル:

void alphaBlendingChanged()

colorBufferFormat : TextureFormat

このプロパティは、カラーバッファとして使用されるテクスチャのテクスチャフォーマットを制御します。デフォルト値は TextureFormat::RGBA8 です。QQuickRhiItem は、QRhiTexture でサポートされているフォーマットのサブセットへのレンダリングをサポートしています。QRhi::isTextureFormatSupported() からサポートされていると報告されたフォーマットのみを指定する必要があります。そうでない場合、レンダリングは機能しません。

注意: アイテムとそのレンダラーがすでに初期化され、レンダリングされ ているときに新しいフォーマットを設定すると、関連するQRhiRenderPassDescriptor のテクスチャフォーマットが異なるため互換性がない場合、レンダラーが作成したすべてのQRhiGraphicsPipeline オブジェクトが使用できなくなる可能性があります。sampleCount を動的に変更する場合と同様に、initialize() または render() の実装では、既存のパイプラインを解放して新しいパイプラインを作成する必要があります。

アクセス関数

QQuickRhiItem::TextureFormat colorBufferFormat() const
void setColorBufferFormat(QQuickRhiItem::TextureFormat format)

Notifier シグナル:

void colorBufferFormatChanged()

[read-only] effectiveColorBufferSize : const QSize

このプロパティは、基礎となるカラーバッファ(QRhiTexture またはQRhiRenderBuffer )のサイズをピクセル単位で公開します。GUI(メイン)スレッドやQMLバインディング、JavaScriptで使用するために用意されています。

注意: シーングラフのレンダースレッドで動作するQQuickRhiItemRenderer の実装では、このプロパティを使用しないでください。それらはむしろ、render target からサイズを問い合わせるべきです。

: レンダリングスレッドでレンダリングが行われるときに値が変更されるという意味で、メインスレッドから見て非同期に値が利用可能になります。つまり、このプロパティは主にQMLバインディングにおいて有用です。アプリケーションコードは、QQuickRhiItem オブジェクトが構築された時点で、すでに値が最新であると仮定してはいけません。

このプロパティは読み取り専用です。

アクセス関数です:

QSize effectiveColorBufferSize() const

通知シグナル:

void effectiveColorBufferSizeChanged()

fixedColorBufferHeight : int

アイテムの関連テクスチャの固定高さ(ピクセル単位)。アイテムのサイズに依存しない固定テクスチャサイズが必要な場合に関連する。このサイズはアイテムのジオメトリ(シーン内のサイズと配置)には影響しないので、テクスチャのコンテンツはアイテムの領域に引き伸ばされて(拡大されて)表示されるか、縮小されて表示されます。

たとえば、アイテムの (ピクセル) サイズのちょうど 2 倍のサイズを設定すると、効果的に 2 倍のスーパーサンプリング (2 倍の解像度でレンダリングし、シーン内のアイテムに対応するクワッドをテクスチャリングするときに暗黙的に縮小する) が実行されます。

デフォルト値は0 です。0の値は、テクスチャのサイズがアイテムのサイズに従うことを意味します。(texture size =item size *device pixel ratio) です。

アクセス関数

int fixedColorBufferHeight() const
void setFixedColorBufferHeight(int height)

通知シグナル:

void fixedColorBufferHeightChanged()

fixedColorBufferWidth : int

アイテムの関連テクスチャまたはレンダーバッファの固定幅をピクセル単位で指定します。アイテムのサイズに依存しない固定カラーバッファのサイズが必要な場合に関連する。このサイズはアイテムのジオメトリ(シーン内のサイズと配置)には影響しないので、テクスチャのコンテンツはアイテムの領域に引き伸ばされて(拡大されて)表示されるか、縮小されて表示されます。

たとえば、アイテムの (ピクセル) サイズのちょうど 2 倍のサイズを設定すると、効果的に 2 倍のスーパーサンプリング (2 倍の解像度でレンダリングし、シーン内のアイテムに対応するクワッドをテクスチャリングするときに暗黙的に縮小する) が実行されます。

デフォルト値は0 です。0の値は、テクスチャのサイズがアイテムのサイズに従うことを意味します。(texture size =item size *device pixel ratio) です。

アクセス関数

int fixedColorBufferWidth() const
void setFixedColorBufferWidth(int width)

Notifier シグナル:

void fixedColorBufferWidthChanged()

mirrorVertically : bool

このプロパティは、テクスチャ付きクワッドを描画するときにテクスチャの UV を反転させるかどうかを制御します。オフスクリーンのカラーバッファの内容や、QQuickRhiItemRenderer によって実装されるレンダリングには影響しません。

デフォルト値はfalse です。

アクセス関数

bool isMirrorVerticallyEnabled() const
void setMirrorVertically(bool enable)

Notifier シグナル:

void mirrorVerticallyChanged()

sampleCount : int

このプロパティは、マルチサンプルアンチエイリアシングのサンプルカウントを制御します。デフォルト値は1 で、これは MSAA が無効であることを意味します。

有効な値は1、4、8、場合によっては16と32です。QRhi::supportedSampleCounts()を使用すると、実行時にサポートされているサンプル数を問い合わせることができますが、通常、アプリケーションは1(MSAAなし)、4x(通常のMSAA)、または8x(高MSAA)を要求する必要があります。

注: 新しい値を設定すると、レンダラーによって作成されたすべてのQRhiGraphicsPipeline オブジェクトは、それ以降同じサンプル カウントを使用する必要があります。異なるサンプルカウントで作成された既存のQRhiGraphicsPipeline オブジェクトは、これ以上使用してはなりません。値が変更されると、すべてのカラーバッファとデプスステンシルバッファが自動的に破棄および再作成され、initialize ()が再度呼び出されます。ただし、isAutoRenderTargetEnabled() がfalse の場合、デプス・ステ ン・バッファや追加のカラー・バッファの管理はアプリケーション次第となる。

サンプル・カウントをデフォルトの 1 から高い値に変更すると、colorTexture() がnullptr になり、msaaColorBuffer() が有効なオブジェクトを返すようになります。次の initialize() 呼び出しでは msaaColorBuffer() はnullptr を返すが、colorTexture() は再び有効になる。さらに、resolveTexture()は、サンプル数が1より大きい(つまりMSAAが使用されている)ときは常に、有効な(非マルチサンプル)QRhiTexture を返す。

アクセス関数:

int sampleCount() const
void setSampleCount(int samples)

ノーティファイア・シグナル:

void sampleCountChanged()

QQuickRhiItemRenderer::msaaColorBuffer() およびQQuickRhiItemRenderer::resolveTexture()も参照のこと

メンバ関数ドキュメント

[explicit] QQuickRhiItem::QQuickRhiItem(QQuickItem *parent = nullptr)

与えられたparent で新しい QQuickRhiItem を構築します。

[override virtual noexcept] QQuickRhiItem::~QQuickRhiItem()

デストラクタ。

[pure virtual protected] QQuickRhiItemRenderer *QQuickRhiItem::createRenderer()

この関数を再実装して、QQuickRhiItemRenderer サブクラスの新しいインスタンスを作成し、返します。

この関数は、GUIスレッドがブロックされている間、レンダリングスレッドで呼び出されます。

[override virtual protected] bool QQuickRhiItem::event(QEvent *e)

再実装します:QQuickItem::event(QEvent *ev).

[override virtual protected] void QQuickRhiItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)

再リプリメント:QQuickItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry).

[protected] bool QQuickRhiItem::isAutoRenderTargetEnabled() const

現在の自動深度ステンシルバッファとレンダーターゲットの管理設定を返します。

デフォルトでは、この値はtrue です。

setAutoRenderTarget()も参照してください

[override virtual] bool QQuickRhiItem::isTextureProvider() const

再インプリメント:QQuickItem::isTextureProvider() const.

[override virtual protected] void QQuickRhiItem::releaseResources()

再実装:QQuickItem::releaseResources().

[protected] void QQuickRhiItem::setAutoRenderTarget(bool enabled)

深度ステンシルQRhiRenderBufferQRhiTextureRenderTarget がアイテムによって自動的に作成され、維持されるかどうかを制御します。デフォルト値はtrue です。これを無効にするには、enabledfalse に設定して、派生クラスのコンストラクタなどから、早い段階でこの関数を呼び出します。

自動モードでは、深度ステンシルバッファのサイズとサンプル数は、カラーバッファテクスチャの設定に従います。非自動モードでは、renderTarget() と depthStencilBuffer() は常にnullptr を返し、これらのオブジェクトの設定と管理は、アプリケーションの initialize() の実装に任されます。

[override virtual] QSGTextureProvider *QQuickRhiItem::textureProvider() const

再インプリメント:QQuickItem::textureProvider() const.

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