QRhiWidget Class
QRhiWidget クラスは、Vulkan、Metal、Direct 3D などのアクセラレーション対応グラフィックス API を通じて 3D グラフィックスをレンダリングするためのウィジェットです。詳細...
| ヘッダー: | #include <QRhiWidget> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Widgets) target_link_libraries(mytarget PRIVATE Qt6::Widgets) |
| qmake: | QT += widgets |
| 以下のように: | Qt 6.7 |
| 継承元: | QWidget |
パブリック型
| enum class | Api { Null, OpenGL, Metal, Vulkan, Direct3D11, Direct3D12 } |
| enum class | TextureFormat { RGBA8, RGBA16F, RGBA32F, RGB10A2 } |
プロパティ
|
|
パブリック関数
| QRhiWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {}) | |
| virtual | ~QRhiWidget() override |
| QRhiWidget::Api | api() const |
| QRhiWidget::TextureFormat | colorBufferFormat() const |
| QSize | fixedColorBufferSize() const |
| QImage | grabFramebuffer() const |
| bool | isDebugLayerEnabled() const |
| bool | isMirrorVerticallyEnabled() const |
| int | sampleCount() const |
| void | setApi(QRhiWidget::Api api) |
| void | setColorBufferFormat(QRhiWidget::TextureFormat format) |
| void | setDebugLayerEnabled(bool enable) |
| void | setFixedColorBufferSize(QSize pixelSize) |
| void | setFixedColorBufferSize(int w, int h) |
| void | setMirrorVertically(bool enabled) |
| void | setSampleCount(int samples) |
シグナル
| void | colorBufferFormatChanged(QRhiWidget::TextureFormat format) |
| void | fixedColorBufferSizeChanged(const QSize &pixelSize) |
| void | frameSubmitted() |
| void | mirrorVerticallyChanged(bool enabled) |
| void | renderFailed() |
| void | sampleCountChanged(int samples) |
保護関数
| QRhiTexture * | colorTexture() const |
| QRhiRenderBuffer * | depthStencilBuffer() const |
| virtual void | initialize(QRhiCommandBuffer *cb) |
| QRhiRenderBuffer * | msaaColorBuffer() const |
| virtual void | releaseResources() |
| virtual void | render(QRhiCommandBuffer *cb) |
| QRhiRenderTarget * | renderTarget() const |
| QRhiTexture * | resolveTexture() const |
| QRhi * | rhi() const |
| void | setAutoRenderTarget(bool enabled) |
再実装された保護関数
| virtual bool | event(QEvent *e) override |
| virtual void | paintEvent(QPaintEvent *e) override |
| virtual void | resizeEvent(QResizeEvent *e) override |
詳細な説明
QRhiWidget は、QWidget ベースのアプリケーション内で、QRhi API を通じてレンダリングされた 3D コンテンツを表示するための機能を提供します。 多くの点で、これはQOpenGLWidget の移植可能な対応版であり、単一の3DグラフィックスAPIに縛られることなく、QRhi がサポートするすべてのAPI(Direct 3D 11/12、Vulkan、Metal、OpenGLなど)で機能します。
QRhiWidgetはサブクラス化されることを想定しています。QRhiWidgetによって暗黙的に作成・管理される2Dテクスチャにレンダリングを行うには、サブクラスは仮想関数initialize()およびrender()を再実装する必要があります。
テクスチャのサイズは、デフォルトではウィジェットのサイズに合わせて調整されます。固定サイズを希望する場合は、setFixedColorBufferSize() を呼び出して、ピクセル単位で指定した固定サイズを設定してください。
テクスチャがカラーバッファとして機能することに加え、深度/ステンシルバッファ、およびこれらを結合するレンダリングターゲットも暗黙的に維持されます。
ウィジェットの最上位ウィンドウの `QRhi ` は、デフォルトでプラットフォーム固有のバックエンドおよびグラフィックス API を使用するように設定されています。macOS および iOS では Metal、Windows では Direct 3D 11、それ以外の場合は OpenGL です。これを上書きするには、`setApi()` を呼び出してください。
注:1つのウィジェットウィンドウで使用できる QRhi バックエンドは1つだけであり、したがって使用できる3DグラフィックスAPIも1つだけです。ウィンドウのウィジェット階層内にある2つのQRhiWidgetまたはQQuickWidget ウィジェットが異なるAPIを要求した場合、そのうちの1つだけが正しく機能します。
注: QRhiWidgetは Qtの公開APIですが 、Qt GUIモジュールに含まれるQRhi クラス群(QRhi 、QShader 、QShaderDescription など)については、互換性の保証は限定的です。これらのクラスについては、ソースコードおよびバイナリの互換性が保証されておらず、APIはアプリケーションが開発された際のQtバージョンでのみ動作が保証されます。 ただし、ソース互換性を損なう変更は最小限に抑えることを目指しており、マイナーリリース(6.7、6.8など)でのみ行われます。qrhiwidget.h には、QRhi に関連するヘッダーファイルは直接含まれていません。 QRhiWidget のサブクラスを実装する際にこれらのクラスを使用するには、Qt::GuiPrivate にリンクし(CMake を使用している場合)、rhi というプレフィックスが付いた適切なヘッダー(例:#include <rhi/qrhi.h> )をインクルードしてください。
三角形を描画する簡単な QRhiWidget サブクラスの例は以下の通りです:
class ExampleRhiWidget : public QRhiWidget
{
public:
ExampleRhiWidget(QWidget *parent = nullptr) : QRhiWidget(parent) { }
void initialize(QRhiCommandBuffer *cb) 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_rotation = 0.0f;
};
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,
};
QShader getShader(const QString &name)
{
QFile f(name);
return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
}
void ExampleRhiWidget::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(":/shader_assets/color.vert.qsb")) },
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/shader_assets/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 = colorTexture()->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 ExampleRhiWidget::render(QRhiCommandBuffer *cb)
{
QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
m_rotation += 1.0f;
QMatrix4x4 modelViewProjection = m_viewProjection;
modelViewProjection.rotate(m_rotation, 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 = colorTexture()->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();
update();
}これは、表示レート(画面のリフレッシュレートに依存する vsync)によって制御され、継続的に更新を要求するウィジェットです。継続的なレンダリングが不要な場合は、render() 内のupdate() の呼び出しを削除し、代わりにレンダリングされたコンテンツの更新が必要な場合にのみ実行するようにしてください。 例えば、立方体の回転をQSlider の値に連動させる場合、スライダーの値変更シグナルを、新しい値を転送してupdate()を呼び出すスロットまたはラムダに接続するだけで十分です。
頂点シェーダーとフラグメントシェーダーは Vulkan 形式の GLSL として提供されており、まず Qt のシェーダーインフラストラクチャによって処理される必要があります。これは、qsb コマンドラインツールを手動で実行するか、CMake のqt_add_shaders()関数を使用することで実現されます。 QRhiWidgetの実装では、アプリケーションに同梱されている、これらの前処理済みの.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);
}その結果、次のようなウィジェットが表示されます:

完全かつ最小限の入門用サンプルについては、「Simple RHI Widget Example」を参照してください。
より多くの機能を備え、さらなる概念を解説した例については、「Cube RHI Widget Example」を参照してください。
QRhiWidget では、ウィンドウ(ウィンドウシステムがネイティブウィンドウ用に提供するサーフェスやレイヤー)に直接描画するのではなく、常にバッキングテクスチャへのレンダリングが行われます。これにより、コンテンツをウィジェットベースの UI の他の部分と適切に合成できるほか、シンプルでコンパクトな API が提供されるため、簡単に使い始めることができます。 その代償として、追加のリソースが必要となり、パフォーマンスに影響が出る可能性があります。実際には多くの場合、これは全く問題ありませんが、上級ユーザーは、異なるアプローチの長所と短所を念頭に置いておく必要があります。2つのアプローチの詳細については、「RHI Window Example」を参照し、「Simple RHI Widget Example」と比較してください。
QRhiWidgetを、別のウィンドウに属するウィジェット階層(トップレベルウィジェット)に再配置したり、QRhiWidget自体をトップレベルにしたり(親をnullptr に設定することで)するには、QRhiWidgetが引き続き正常に動作している間に、関連するQRhi を変更(場合によっては古いものを破棄)する必要があります。 これをサポートするため、堅牢なQRhiWidgetの実装では、releaseResources()仮想関数も再実装し、デストラクタ内と同様にQRhi リソースを解放することが期待されます。Cube RHI Widget Exampleでは、この動作を実例で示しています。
主なユースケースではありませんが、QRhiWidget では、Vulkan、Metal、Direct 3D、OpenGL などの 3D グラフィックス API を直接使用するレンダリングコードを組み込むことも可能です。QRhi のレンダリングパス内でネイティブコマンドを記録する方法の詳細についてはQRhiCommandBuffer::beginExternal()を参照し、既存のネイティブテクスチャをラップして、その後のレンダリングパスでQRhi と共に使用する方法についてはQRhiTexture::createFrom()を参照してください。 ただし、QRhiWidgetの主な目的は、QRhi ベースのレンダリングコードに適した環境を提供することであり、任意の、潜在的に複雑な、外部のレンダリングエンジンを有効にすることではないため、基盤となるグラフィックスAPIの構成可能性(デバイスやコンテキストの機能、レイヤー、拡張機能など)は制限される点に注意してください。
QRhi 、QShader 、QOpenGLWidget 、Simple RHI Widget Example、およびCube RHI Widget Exampleも参照してください 。
メンバ型のドキュメント
enum class QRhiWidget::Api
使用する3D APIおよびQRhi バックエンドを指定します
| 定数 | 値 |
|---|---|
QRhiWidget::Api::Null | 0 |
QRhiWidget::Api::OpenGL | 1 |
QRhiWidget::Api::Metal | 2 |
QRhiWidget::Api::Vulkan | 3 |
QRhiWidget::Api::Direct3D11 | 4 |
QRhiWidget::Api::Direct3D12 | 5 |
「QRhi」も参照してください 。
enum class QRhiWidget::TextureFormat
QRhiWidget がレンダリングするテクスチャの形式を指定します。
| 定数 | 値 | 説明 |
|---|---|---|
QRhiWidget::TextureFormat::RGBA8 | 0 | 「QRhiTexture::RGBA8 」を参照してください。 |
QRhiWidget::TextureFormat::RGBA16F | 1 | 「QRhiTexture::RGBA16F 」を参照してください。 |
QRhiWidget::TextureFormat::RGBA32F | 2 | QRhiTexture::RGBA32F を参照してください。 を参照してください。 |
QRhiWidget::TextureFormat::RGB10A2 | 3 | QRhiTexture::RGB10A2 を参照してください。 |
QRhiTextureも参照してください 。
プロパティのドキュメント
autoRenderTarget : bool
深度・ステンシルバッファおよびレンダリングターゲットの自動管理に関する現在の設定です。
デフォルトでは、この値はtrue です。
colorBufferFormat : TextureFormat
このプロパティは、カラーバッファとして使用されるテクスチャ(またはレンダリングバッファ)のテクスチャ形式を制御します。デフォルト値はTextureFormat::RGBA8 です。QRhiWidget は、QRhiTexture がサポートする形式の一部へのレンダリングをサポートしています。QRhi::isTextureFormatSupported()によってサポートされていると報告された形式のみを指定してください。それ以外の場合、レンダリングは機能しません。
注: ウィジェットがすでに初期化され、レンダリングが完了している状態で新しいフォーマットを設定すると 、テクスチャフォーマットの違いにより関連するQRhiRenderPassDescriptor が互換性を失った場合、レンダラーによって作成されたすべてのQRhiGraphicsPipeline オブジェクトが使用不能になる可能性があります。sampleCount を動的に変更する場合と同様に、これはinitialize()またはrender()の実装において、既存のパイプラインを解放し、新しいパイプラインを作成する処理を適切に行う必要があることを意味します。
アクセス関数:
| QRhiWidget::TextureFormat | colorBufferFormat() const |
| void | setColorBufferFormat(QRhiWidget::TextureFormat format) |
Notifierシグナル:
| void | colorBufferFormatChanged(QRhiWidget::TextureFormat format) |
fixedColorBufferSize : QSize
QRhiWidget に関連付けられたテクスチャの固定サイズ(ピクセル単位)。 ウィジェットのサイズに依存しない固定のテクスチャサイズを設定したい場合に適用されます。このサイズはウィジェットのジオメトリ(トップレベルウィンドウ内でのサイズや配置)には影響を与えないため、テクスチャの内容はウィジェットの領域に合わせて引き伸ばされた(拡大された)状態、あるいは縮小された状態で表示されます。
たとえば、ウィジェットの (ピクセル) サイズのちょうど 2 倍のサイズを設定すると、実質的に 2 倍のスーパーサンプリングが行われます (2 倍の解像度でレンダリングし、ウィンドウ内のウィジェットに対応するクワッドにテクスチャを適用する際に暗黙的に縮小します)。 一方、ウィジェットの半分のサイズに設定すると、実質的に半分の解像度でレンダリングを行い、その結果をアップスケーリングすることになります。
デフォルトでは、この値は nullQSize です。null または空のQSize は、テクスチャのサイズがQRhiWidget のサイズに従うことを意味します。(texture size =widget size *device pixel ratio )。
注:デバイスピクセル比 (システムコンポジターのスケーリング係数)は 、パフォーマンスに大きな影響を与える可能性があります。スケーリング係数が 2 (200%)の場合、解像度が2倍になることを意味し、開発者やUIデザイナーがウィジェットのサイズとして認識しているものの2倍でレンダリングされ、その後、コンテンツが実質的に縮小されることになります。これは、デバイスピクセル比が1のシステムで、このプロパティをウィジェットのピクセルサイズの2倍に設定した場合に起こる現象と同様です。 したがって、システムで 1 より大きいデバイス・ピクセル・レシオが使用されている場合、多くの最新のデスクトップ・システムでは、その必要性もパフォーマンスの余裕もないため、このプロパティがウィジェットのピクセルサイズよりも大きいサイズで使用されることはほとんどないと思われます。 その代わりに、このプロパティの主なユースケースは、ウィンドウのジオメトリがどれほど大きくても、それを盲目的に追従するのではなく、妥当な低解像度でレンダリングするために、より小さいサイズを設定することです。
アクセス関数:
| QSize | fixedColorBufferSize() const |
| void | setFixedColorBufferSize(QSize pixelSize) |
| void | setFixedColorBufferSize(int w, int h) |
通知シグナル:
| void | fixedColorBufferSizeChanged(const QSize &pixelSize) |
mirrorVertically : bool
有効にすると、QRhiWidget のバッキングテクスチャをトップレベルウィンドウ内のその他のウィジェットコンテンツと合成する際に、画像をX軸を中心に反転させます。
デフォルト値は `false` です。
アクセス関数:
| bool | isMirrorVerticallyEnabled() const |
| void | setMirrorVertically(bool enabled) |
Notifierシグナル:
| void | mirrorVerticallyChanged(bool enabled) |
sampleCount : int
このプロパティは、マルチサンプルアンチエイリアシング(MSAA)のサンプル数を制御します。デフォルトの値は1 であり、これはMSAAが無効になっていることを意味します。
有効な値は 1、4、8、場合によっては 16 および 32 です。QRhi::supportedSampleCounts() を使用すると、実行時にサポートされているサンプル数を照会できますが、通常、アプリケーションでは 1(MSAA なし)、4x(標準 MSAA)、または 8x(高 MSAA)を指定する必要があります。
注: 新しい値を設定すると 、それ以降、レンダラーによって作成されるすべてのQRhiGraphicsPipeline オブジェクトは、同じサンプル数を使用する必要があります。 異なるサンプル数で作成された既存のQRhiGraphicsPipeline オブジェクトは、それ以降使用してはなりません。値が変更されると、すべてのカラーバッファおよび深度・ステンシルバッファは自動的に破棄され、再作成され、initialize()が再度呼び出されます。ただし、autoRenderTarget がfalse の場合、深度・ステンシルバッファや追加のカラーバッファに関しては、アプリケーション側でこれを管理する必要があります。
サンプル数をデフォルトの 1 からより大きな値に変更すると、colorTexture() はnullptr となり、msaaColorBuffer() は有効なオブジェクトを返すようになります。1(または 0)に戻すと、その逆の挙動になります。つまり、次にinitialize() を呼び出した際、msaaColorBuffer() はnullptr を返す一方、colorTexture() は再び有効なオブジェクトを返すようになります。 さらに、resolveTexture()は、サンプル数が1より大きい場合(つまり、MSAAが使用されている場合)、有効な(マルチサンプルではない)QRhiTexture を返します。
アクセス関数:
| int | sampleCount() const |
| void | setSampleCount(int samples) |
通知信号:
| void | sampleCountChanged(int samples) |
msaaColorBuffer() およびresolveTexture()も参照してください 。
メンバ関数のドキュメント
[explicit] QRhiWidget::QRhiWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {})
parent の子となるウィジェットを作成し、ウィジェットのフラグをf に設定します。
[override virtual noexcept] QRhiWidget::~QRhiWidget()
デストラクタ。
QRhiWidget::Api QRhiWidget::api() const
現在設定されているグラフィックスAPI(QRhi バックエンド)を返します。
setApi()も参照してください 。
[protected] QRhiTexture *QRhiWidget::colorTexture() const
ウィジェットのカラーバッファとして機能するテクスチャを返します。
initialize() およびrender() からのみ呼び出さなければなりません。
深度・ステンシルバッファやQRhiRenderTarget とは異なり、このテクスチャは常に利用可能であり、autoRenderTarget の値に関係なく、QRhiWidget によって管理されます。
注: sampleCount が1より大きく、マルチサンプルアンチエイリアシングが有効になっている場合 、戻り値はnullptr となります。その場合は、msaaColorBuffer()を呼び出してQRhiRenderBuffer を照会してください。
注:バッキングテクスチャのサイズ とサンプル数は 、renderTarget() から返されるQRhiRenderTarget を通じて照会することも可能です。これは、マルチサンプリングの使用の有無にかかわらず機能するため、QRhiTexture やQRhiRenderBuffer からの照会よりも便利で簡潔な場合があります。
msaaColorBuffer()、depthStencilBuffer()、renderTarget()、およびresolveTexture()も参照してください 。
[protected] QRhiRenderBuffer *QRhiWidget::depthStencilBuffer() const
ウィジェットのレンダリングで使用される深度・ステンシルバッファを返します。
initialize() およびrender() からのみ呼び出す必要があります。
autoRenderTarget がtrue である場合にのみ利用可能です。それ以外の場合、戻り値はnullptr となり、深度・ステンシルバッファおよびQRhiTextureRenderTarget の作成と管理は、initialize()の再実装に委ねられます。
colorTexture() およびrenderTarget()も参照してください 。
[override virtual protected] bool QRhiWidget::event(QEvent *e)
QWidget::event(QEvent *event) を再実装します。
[signal] void QRhiWidget::frameSubmitted()
このシグナルは、ウィジェットの最上位ウィンドウのコンポジションが完了し、submitted a frame となった後に発火します。
QImage QRhiWidget::grabFramebuffer() const
新しいフレームをレンダリングし、テクスチャの内容を読み取り、それをQImage として返します。
エラーが発生した場合は、nullのQImage が返されます。
返されるQImage のフォーマットは、colorBufferFormat()の指定に応じて、QImage::Format_RGBA8888 、QImage::Format_RGBA16FPx4 、QImage::Format_RGBA32FPx4 、またはQImage::Format_BGR30 のいずれかになります。
QRhiWidget は、レンダラーのブレンディングや合成の処理方法を把握していないため、出力にRGB色値としてアルファ値が事前乗算されているかどうかを判断できません。したがって、たとえ適切である場合でも、返されるQImage に対しては、_Premultiplied やQImage 形式は決して使用されません。結果のデータをどのように再解釈するかは、呼び出し側の判断に委ねられます。
注:この関数は 、QRhiWidget が画面上の最上位ウィンドウに属するウィジェット階層に追加されていない場合でも呼び出すことができます。これにより、オフスクリーンでの 3D レンダリングから画像を生成することが可能になります。
この関数の名前は、QOpenGLWidget およびQQuickWidget との一貫性を保つため、grabFramebuffer()と命名されています。QRhiWidget のコンテンツからCPU側の画像データを取得する方法はこれだけではありません。QRhiWidget またはその祖先オブジェクトに対してQWidget::grab()を呼び出す方法も機能します(QPixmap を返します)。QImage を直接操作できることに加え、grabFramebuffer()のもう一つの利点は、QWidget の残りのインフラストラクチャを経由する必要がなく、すぐに新しいフレームのレンダリングをトリガーして読み出しを行えるため、パフォーマンスが若干向上する可能性があることです。
setColorBufferFormat()も参照してください 。
[virtual protected] void QRhiWidget::initialize(QRhiCommandBuffer *cb)
この関数は、ウィジェットが初めて初期化されたとき、関連付けられたテクスチャのサイズ、フォーマット、またはサンプル数が変更されたとき、あるいは何らかの理由でQRhi やテクスチャが変更されたときに呼び出されます。この関数は、render()内のレンダリングコードで使用されるグラフィックリソースを維持する(まだ作成されていない場合は作成し、サイズが変更された場合は調整および再構築する)ことが求められます。
QRhi 、QRhiTexture 、およびその他の関連オブジェクトを取得するには、rhi()、colorTexture()、depthStencilBuffer()、およびrenderTarget()を呼び出します。
ウィジェットのサイズが変更された場合、QRhi オブジェクト、カラーバッファテクスチャ、および深度・ステンシルバッファオブジェクトはすべて以前と同じインスタンス(つまり、ゲッターは同じポインタを返す)ですが、カラーバッファおよび深度・ステンシルバッファは再構築されている可能性が高く、その結果、size および基盤となるネイティブテクスチャリソースは、前回の呼び出し時とは異なる場合があります。
また、この関数の呼び出し間でQRhi オブジェクトやカラーバッファテクスチャが変更される可能性にも備えて、再実装を行う必要があります。オブジェクトが異なることになる特殊なケースの一つは、まだ表示されていないウィジェットに対してgrabFramebuffer()を実行し、その後、そのウィジェットをトップレベルのウィジェット内で画面上に表示する場合です。 この場合、グラブは専用のQRhi を使用して行われ、その後のinitialize()およびrender()の呼び出しにおいて、トップレベルのウィンドウに関連付けられたQRhi に置き換えられます。もう1つの、より一般的なケースは、ウィジェットが親ウィンドウを変更され、新しいトップレベルのウィンドウに属するようになる場合です。 この場合、この関数が次に呼び出された際、QRhi およびQRhiWidget によって管理されるすべての関連リソースは、以前とは異なるインスタンスになります。そのため、サブクラスによって以前に作成された既存のQRhi リソースはすべて破棄することが重要です。これらは以前のQRhi に属しており、ウィジェットではもはや使用すべきではないからです。
autoRenderTarget がtrue (デフォルト値)の場合、colorTexture()(またはmsaaColorBuffer())に関連付けられた深度・ステンシルQRhiRenderBuffer およびQRhiTextureRenderTarget 、ならびに深度・ステンシルバッファが自動的に作成・管理されます。initialize()およびrender()の再実装では、depthStencilBuffer()およびrenderTarget()を介してこれらのオブジェクトを取得できます。autoRenderTarget がfalse に設定されている場合、これらのオブジェクトは自動的に作成・管理されなくなります。 その代わりに、バッファの作成やレンダリングターゲットの設定は、initialize() の実装側で適切に行われることになります。レンダリングターゲットに対して追加の色や深度・ステンシルアタッチメントを手動で管理する場合、それらのサイズとサンプル数は常にcolorTexture() /msaaColorBuffer() のサイズとサンプル数に従わなければなりません。そうしないと、レンダリングエラーや 3D API の検証エラーが発生する可能性があります。
サブクラスによって作成されたグラフィックスリソースは、サブクラスのデストラクタの実装内で解放されることが想定されています。
cb は、ウィジェットの現在のフレームに対するQRhiCommandBuffer です。この関数は、フレームが記録されているが、アクティブなレンダリングパスがない状態で呼び出されます。コマンドバッファは、主にrender() に委譲することなく、resource updates をキューに入れることを可能にするために提供されます。
render()も参照してください 。
bool QRhiWidget::isDebugLayerEnabled() const
使用中のグラフィックスAPIでデバッグまたは検証レイヤーが要求される場合、trueを返します。
setDebugLayerEnabled()も参照してください 。
[protected] QRhiRenderBuffer *QRhiWidget::msaaColorBuffer() const
ウィジェットのマルチサンプルカラーバッファとして機能するレンダリングバッファを返します。
initialize() およびrender() からのみ呼び出す必要があります。
sampleCount が1より大きく、マルチサンプルアンチエイリアシングが有効になっている場合、返されるQRhiRenderBuffer はそれに対応するサンプル数を持ち、カラーバッファとして機能します。このバッファへのレンダリングに使用されるグラフィックスパイプラインは、同じサンプル数で作成されている必要があり、深度・ステンシルバッファのサンプル数も一致している必要があります。 マルチサンプルコンテンツは、resolveTexture()から返されるテクスチャに解決されることが想定されています。autoRenderTarget がtrue の場合、renderTarget()はこれを自動的に行うように設定されます。具体的には、msaaColorBuffer()をカラーアタッチメント0のrenderbuffer として、resolveTexture()をそのresolveTexture として設定します。
MSAAが使用されていない場合、戻り値はnullptr となります。その場合は、代わりにcolorTexture()を使用してください。
基盤となる 3D グラフィックス API によっては、マルチサンプルテクスチャとサンプル数が 1 より大きいカラーレンダーバッファとの間に実質的な違いがない場合があります(QRhi は、両方を同じネイティブリソース型にマッピングするだけかもしれません)。 ただし、一部の古いAPIでは、テクスチャとレンダリングバッファを区別している場合があります。マルチサンプルレンダリングバッファは利用可能ですが、マルチサンプルテクスチャは利用できないOpenGL ES 3.0に対応するため、QRhiWidget は常に、カラーアタッチメントとしてマルチサンプルQRhiRenderBuffer を使用し(マルチサンプルQRhiTexture は決して使用しません)、MSAAを実行します。
注:バッキングテクスチャのサイズ やサンプル数は 、renderTarget() から返されるQRhiRenderTarget を通じて照会することも可能です。これは、マルチサンプリングの使用有無にかかわらず機能するため、QRhiTexture やQRhiRenderBuffer から照会するよりも便利でコンパクトな場合があります。
colorTexture()、depthStencilBuffer()、renderTarget()、およびresolveTexture()も参照してください 。
[override virtual protected] void QRhiWidget::paintEvent(QPaintEvent *e)
QWidget::paintEvent (QPaintEvent *event)を再実装します。
ペイントイベントを処理します。
QWidget::update() を呼び出すと、ペイントイベントe が送信され、その結果、この関数が呼び出されます。イベントの送信は非同期であり、update() から戻った後、ある時点で実行されます。その後、この関数は、いくつかの準備を行った後、仮想関数render() を呼び出し、QRhiWidget に関連付けられたテクスチャの内容を更新します。 その後、ウィジェットの最上位ウィンドウが、そのテクスチャをウィンドウの他の部分と合成します。
[virtual protected] void QRhiWidget::releaseResources()
グラフィックリソースを早期に解放する必要が生じた際に呼び出されます。
通常、QRhiWidget がトップレベルウィジェットの子階層に追加された場合、それ以降は当該 およびトップレベルウィジェットの存続期間中、その位置に留まり続けるため、この状況は発生しません。したがって、多くの場合、この関数を再実装する必要はありません。例えば、アプリケーションが常に単一のトップレベルウィジェット(ネイティブウィンドウ)しか持たない場合などが挙げられます。 しかし、ウィジェット(またはその祖先)の親の変更が関与する場合、堅牢で適切に記述されたQRhiWidget のサブクラスでは、この関数を再実装することが必要になります。
この関数が呼び出された際、実装では、デストラクタ内で行うのと同様に、すべてのQRhi リソース(QRhiBuffer 、QRhiTexture などのオブジェクト)を破棄することが期待されます。また、その後でinitialize()が最終的に呼び出されるため、スマートポインタを使用してリソースをNULLに設定するか、resources-invalid フラグを設定することも必要となります。 ただし、リソースの解放を後続のinitialize()に委ねることは誤りであることに注意してください。この関数が呼び出された場合、リソースは戻り値を返す前に解放されなければなりません。また、この関数を実装しても、クラスのデストラクタ(またはスマートポインタ)に代わるものではない点にも注意してください。グラフィックリソースは、依然として両方で解放する必要があります。
QRhiWidget実際の動作例については、「Cube RHI ウィジェットの例」を参照してください。そこでは、QRhiWidget を、親ウィジェットを持つ「子ウィジェット」と、親ウィジェットを持たない「トップレベルウィジェット」の間で切り替えるボタンが、この関数の呼び出しをトリガーします。これは、関連するトップレベルウィジェット、ネイティブウィンドウ、 およびQRhi がすべて変更されるため、この関数が呼び出されます。これにより、以前に使用されていたQRhi が破棄され、まだ存続しているQRhiWidget によって管理されている関連リソースが早期に解放されることになります。
この関数が呼び出されるもう一つのケースは、grabFramebuffer()が、表示中のウィンドウに追加されていないQRhiWidget に対して使用された場合、すなわちレンダリングがオフスクリーンで行われる場合です。 その後、このQRhiWidget が可視化されたり、可視ウィジェット階層に追加されたりすると、関連するQRhi は、オフスクリーンレンダリングに使用されていた一時的なものから、そのウィンドウ専用のものへと変更されるため、この関数も同様に呼び出されます。
initialize()も参照してください 。
[virtual protected] void QRhiWidget::render(QRhiCommandBuffer *cb)
ウィジェットのコンテンツ(つまり、テクスチャの内容)を更新する必要があるときに呼び出されます。
この関数が呼び出される前には、必ず少なくとも1回はinitialize()が呼び出されています。
更新を要求するには、QWidget::update() を呼び出してください。render() 内からupdate() を呼び出すと、vsync によって制御されながら継続的に更新が行われます。
cb は、ウィジェットの現在のフレームに対するQRhiCommandBuffer です。この関数は、フレームが記録されているが、アクティブなレンダリングパスがない状態で呼び出されます。
initialize()も参照してください 。
[signal] void QRhiWidget::renderFailed()
このシグナルは、ウィジェットがバッキングテクスチャにレンダリングを行うべき時(widget update による場合、またはgrabFramebuffer()の呼び出しによる場合)、グラフィック設定に関連する問題などにより、ウィジェットが使用できるQRhi が存在しない場合に発せられます。
問題が発生した場合、このシグナルは複数回発火する可能性があります。1回だけ発火すると想定しないでください。エラー処理コードへの通知を1回のみ行う必要がある場合は、Qt::SingleShotConnection に接続してください。
[protected] QRhiRenderTarget *QRhiWidget::renderTarget() const
render() の再実装において、QRhiCommandBuffer::beginPass() と併用する必要があるレンダリングターゲットオブジェクトを返します。
initialize() およびrender() からのみ呼び出される必要があります。
autoRenderTarget がtrue である場合にのみ利用可能です。それ以外の場合、戻り値はnullptr となり、深度・ステンシルバッファおよびQRhiTextureRenderTarget の作成と管理は、initialize()の再実装に委ねられます。
graphics pipelines を作成する際には、QRhiRenderPassDescriptor が必要です。これは、返されたQRhiTextureRenderTarget に対してrenderPassDescriptor()を呼び出すことで取得できます。
colorTexture() およびdepthStencilBuffer()も参照してください 。
[override virtual protected] void QRhiWidget::resizeEvent(QResizeEvent *e)
QWidget::resizeEvent(QResizeEvent *event) を再実装します。
e のイベントパラメータとして渡されるリサイズイベントを処理します。仮想関数initialize()を呼び出します。
注: 派生クラスでこの関数をオーバーライドすることは避けてください 。やむを得ずオーバーライドする場合は、QRhiWidget の実装も確実に呼び出されるようにしてください。そうしないと、基になるテクスチャオブジェクトおよび関連リソースのサイズ変更が適切に行われず、レンダリングが不正になる可能性があります。
[protected] QRhiTexture *QRhiWidget::resolveTexture() const
マルチサンプルコンテンツが解像される、マルチサンプルではないテクスチャを返します。
マルチサンプルアンチエイリアシングが有効になっていない場合、結果はnullptr となります。
initialize() およびrender() からのみ呼び出す必要があります。
MSAA が有効になっている場合、これは画面上の他のQWidget コンテンツと合成されるテクスチャとなります。ただし、QRhiWidget のレンダリングは、msaaColorBuffer() から返される (マルチサンプル)QRhiRenderBuffer をターゲットにする必要があります。autoRenderTarget がtrue の場合、これはrenderTarget() から返されるQRhiRenderTarget によって処理されます。 それ以外の場合は、カラーバッファと解決済みテクスチャの両方を備えたレンダリングターゲットオブジェクトを正しく設定するのは、サブクラスのコードに委ねられます。
colorTexture()も参照してください 。
[protected] QRhi *QRhiWidget::rhi() const
現在のQRhi オブジェクトを返します。
initialize() およびrender() からのみ呼び出す必要があります。
void QRhiWidget::setApi(QRhiWidget::Api api)
使用するグラフィックスAPIおよびQRhi バックエンドをapi に設定します。
警告:この関数は 、ウィジェットがウィジェット階層に追加され、画面に表示される前に、十分に早い段階で呼び出す必要があります。たとえば、サブクラスのコンストラクタ内でこの関数を呼び出すようにしてください。呼び出しが遅すぎると、この関数は効果を発揮しません。
デフォルト値はプラットフォームによって異なります。macOSおよびiOSではMetal、WindowsではDirect 3D 11、それ以外のプラットフォームではOpenGLが使用されます。
api は、ウィジェットとその最上位ウィンドウに対して一度だけ設定可能です。設定が完了して有効になると、そのウィンドウはレンダリングにそのAPIとQRhi バックエンドのみを使用することになります。別の値を設定しようとしたり、異なるapi を持つ別のQRhiWidget を追加しようとしたりしても、期待どおりに機能しません。
setColorBufferFormat()、setDebugLayerEnabled()、およびapi()も参照してください 。
[protected] void QRhiWidget::setAutoRenderTarget(bool enabled)
ウィジェットによって、深度・ステンシルバッファ(QRhiRenderBuffer )および深度・ステンシルバッファのサンプル数(QRhiTextureRenderTarget )が自動的に作成・維持されるかどうかを制御します。デフォルト値はtrue です。
自動モードでは、深度・ステンシルバッファのサイズとサンプル数は、カラーバッファテクスチャの設定に従います。非自動モードでは、renderTarget() およびdepthStencilBuffer() は常にnullptr を返すため、これらのオブジェクトの設定と管理は、アプリケーション側のinitialize() の実装に委ねられます。
自動モードを無効にするには、例えば派生クラスのコンストラクタ内で、早い段階で `enabled ` を `false ` に設定してこの関数を呼び出してください。
void QRhiWidget::setDebugLayerEnabled(bool enable)
enable がtrueの場合、基盤となるグラフィックスAPIのデバッグまたは検証レイヤーにリクエストを送信します。
警告:この関数は 、ウィジェットがウィジェット階層に追加され、画面に表示される前に、十分に早い段階で呼び出す必要があります。たとえば、サブクラスのコンストラクタ内でこの関数を呼び出すようにしてください。呼び出しが遅すぎると、この関数は効果を発揮しません。
Vulkan および Direct 3D で利用可能です。
デフォルトでは無効になっています。
setApi() およびisDebugLayerEnabled()も参照してください 。
© 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.