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() 可覆盖此设置。
注意: 单个小部件窗口 只能使用一个QRhi 后端,因此只能使用一种3D图形API。如果窗口的小部件层次结构中,两个QRhiWidget或QQuickWidget 小部件请求了不同的API,则只有其中一个能正常工作。
注意:虽然 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 的值绑定,那么只需将滑块的值变化信号连接到一个槽或lambda表达式,该槽或lambda表达式会转发新值并调用update()即可。
顶点着色器和片段着色器以 Vulkan 风格的 GLSL 形式提供,必须先由 Qt 着色器基础设施进行处理。这可以通过手动运行qsb 命令行工具,或使用 CMake 中的qt_add_shaders()函数来实现。 QRhiWidget 的实现会加载随应用程序一起提供的这些经过预处理的.qsb 文件。有关 Qt 着色器转换基础设施的更多信息,请参阅QtShader 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);
}生成的控件显示效果如下:

如需查看完整、简约的入门示例,请参阅“简单 RHI 控件示例”。
如需功能更丰富且演示更多概念的示例,请参阅“立方体 RHI 控件示例”。
QRhiWidget 始终将渲染结果渲染到后备纹理中,而非直接渲染到窗口(即窗口系统为原生窗口提供的表面或图层)上。这使得内容能够与基于小部件的其余用户界面正确合成,并提供简单紧凑的 API,便于入门。 所有这些优势都需要消耗额外的资源,并可能对性能产生影响。在实际应用中,这通常是可以接受的,但高级用户应权衡不同方法的利弊。有关这两种方法的详细信息,请参考“RHI 窗口示例”并将其与“简单 RHI 控件示例”进行对比。
将 QRhiWidget 重新添加到属于另一个窗口(顶级控件)的控件层次结构中,或者将 QRhiWidget 本身设为顶级控件(通过将父控件设置为 `nullptr`),这涉及更改关联的 `QRhi `(并可能销毁旧的 ` `),而 QRhiWidget 本身则会继续正常运行。 为了支持这一点,稳健的 QRhiWidget 实现还应重写releaseResources() 虚拟函数,并在其中像在析构函数中那样释放其QRhi 资源。Cube RHI Widget 示例在实践中演示了这一点。
虽然这不是主要用例,但 QRhiWidget 还允许集成直接使用 Vulkan、Metal、Direct 3D 或 OpenGL 等 3D 图形 API 的渲染代码。 有关在QRhi 渲染通过中记录原生命令的详细信息,请参阅QRhiCommandBuffer::beginExternal();有关如何封装现有原生纹理并在后续渲染通过中将其与QRhi 配合使用的方法,请参阅QRhiTexture::createFrom()。 但请注意,底层图形 API 的可配置性(其设备或上下文特性、图层、扩展等)将受到限制,因为 QRhiWidget 的主要目标是提供一个适合基于QRhi 的渲染代码的环境,而非支持任意且可能复杂的第三方渲染引擎。
另请参阅 QRhi 、QShader 、QOpenGLWidget 、简单 RHI 控件示例以及立方体 RHI 控件示例。
成员类型文档
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) |
通知器信号:
| void | colorBufferFormatChanged(QRhiWidget::TextureFormat format) |
fixedColorBufferSize : QSize
QRhiWidget 关联纹理的固定大小(以像素为单位)。 当需要设置一个不依赖于控件大小的固定纹理尺寸时,此参数才相关。该尺寸不会影响控件的几何属性(即其在顶级窗口中的大小和位置),这意味着纹理内容会在控件区域内呈现拉伸(放大)或缩小效果。
例如,将大小设置为小部件(像素)大小的整整两倍,实际上会执行 2 倍过采样(以两倍的分辨率进行渲染,然后在为窗口中对应小部件的四边形贴图时隐式缩小)。 另一方面,将大小设置为控件大小的一半,实际上会以一半的分辨率进行渲染,然后将结果放大。
默认情况下,该值为空的 `QSize`。空或未指定的 `QSize ` 表示纹理的大小遵循 `QRhiWidget` 的大小。(texture size =widget size *device pixel ratio )。
注意:设备像素比 (系统合成器的缩放因子)可能会对性能产生重大影响,因为缩放因子为 2 (200%)意味着以两倍的分辨率进行渲染,即开发者与UI设计师所感知的小部件尺寸的两倍,随后再对内容进行有效的缩放处理——这与在设备像素比为1的系统上,将该属性设置为小部件像素尺寸两倍时的情况类似。 因此,预计该属性很少会用于大于控件像素大小的尺寸,因为当系统本身使用大于 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) |
通知器信号:
| 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() 将再次变为有效。 此外,当采样数大于 1 时(即启用了 MSAA),resolveTexture() 将返回一个有效的(非多采样)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 不同,该纹理始终可用,并由QRhiWidget 管理,与autoRenderTarget 的值无关。
注意:当 sampleCount 大于1(即启用了多采样抗锯齿)时, 返回值为nullptr 。此时,请通过调用msaaColorBuffer()来查询QRhiRenderBuffer 。
注意: 还可以通过renderTarget() 返回的QRhiRenderTarget 来查询底层纹理的大小 和采样数。与从QRhiTexture 或QRhiRenderBuffer 查询相比,这种方法可能更方便且更简洁,因为它无论是否启用了多采样都能正常工作。
另请参阅 msaaColorBuffer()、depthStencilBuffer()、renderTarget() 以及resolveTexture()。
[protected] QRhiRenderBuffer *QRhiWidget::depthStencilBuffer() const
返回小部件渲染所使用的深度-模板缓冲区。
仅允许从initialize()和render()中调用。
仅当autoRenderTarget 为true 时才可用。否则,返回值为nullptr ,此时由initialize()的重新实现负责创建和管理深度-模板缓冲区以及QRhiTextureRenderTarget 。
另请参见 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 返回。
当发生错误时,将返回一个空的QImage 。
返回的QImage 将采用QImage::Format_RGBA8888 、QImage::Format_RGBA16FPx4 、QImage::Format_RGBA32FPx4 或QImage::Format_BGR30 格式,具体取决于colorBufferFormat()。
QRhiWidget 无法得知渲染器对混合和合成采用的具体方法,因此无法确定输出中的 RGB 颜色值是否已预乘了透明度(alpha)。因此,即使在适用情况下,返回的QImage 也绝不会采用_Premultiplied 或QImage 格式。调用方应根据自身需求对生成的数据进行重新解释。
注意: 当QRhiWidget 未被添加到属于屏幕顶级窗口的小部件层次结构中时,也可以调用此 函数。这允许从屏幕外的 3D 渲染中生成图像。
该函数命名为 grabFramebuffer(),是为了与QOpenGLWidget 和QQuickWidget 保持一致。这并非从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 。另一种更常见的情况是,当控件被重新父化,从而属于一个新的顶级窗口时。 在这种情况下,在后续调用此函数时,QRhi 以及由QRhiWidget 管理的所有相关资源都将与之前不同。此时,必须销毁子类之前创建的所有现有QRhi 资源,因为它们属于之前的QRhi ,而该窗口不应再被该小部件使用。
当autoRenderTarget 的值为true (这是默认值)时,系统会自动创建并管理与colorTexture()(或msaaColorBuffer())及深度-模板缓冲区关联的深度-模板QRhiRenderBuffer 和QRhiTextureRenderTarget 。initialize()和render()的重写实现可通过depthStencilBuffer()和renderTarget()查询这些对象。当autoRenderTarget 设置为false 时,这些对象将不再被自动创建和管理。 相反,将由 `initialize()` 的实现根据需要创建缓冲区并设置渲染目标。当手动管理渲染目标的额外颜色或深度-模板附件时,其大小和采样数必须始终遵循 `colorTexture()` / `msaaColorBuffer()` 的大小和采样数,否则可能会发生渲染或 3D API 验证错误。
子类创建的图形资源应在子类的析构函数中释放。
cb 是小部件当前帧的QRhiCommandBuffer 。该函数在录制帧时被调用,但此时没有活动的渲染通道。提供该命令缓冲区主要是为了允许将resource updates 加入队列,而无需交由render()处理。
另请参阅 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 等对象),这与在析构函数中应执行的操作类似。此外,还必须将资源清零、使用智能指针或设置resources-invalid 标志,因为随后最终会调用initialize()。 但请注意,将资源释放推迟到后续的initialize()中是错误的。如果调用了此函数,必须在返回之前释放资源。另请注意,实现此函数并不能替代类的析构函数(或智能指针):图形资源仍必须在这两者中都得到释放。
请参阅“Cube RHI 控件示例”以了解实际应用。在该示例中,用于切换QRhiWidget 状态的按钮(使其在“作为子控件”(因拥有父控件)与“作为顶级控件”(因无父控件)之间切换),将触发此函数的调用,因为关联的顶级控件、本机窗口、 以及QRhi 在QRhiWidget 的生命周期内均会发生变化,此时先前使用的QRhi 将被销毁,这意味着由仍存活的QRhiWidget 管理的关联资源会被提前释放。
调用此函数的另一种情况是,当grabFramebuffer() 与未添加到可见窗口的QRhiWidget 配合使用时,即渲染在屏幕外进行。 如果随后将该QRhiWidget 设为可见,或将其添加到可见的小部件层次结构中,则关联的QRhi 将从用于离屏渲染的临时窗口切换为该窗口的专用窗口,从而也会触发此函数。
另请参阅 initialize()。
[virtual protected] void QRhiWidget::render(QRhiCommandBuffer *cb)
当控件内容(即纹理的内容)需要更新时调用此函数。
在调用此函数之前,总会至少调用一次initialize()。
若要请求更新,请调用 `QWidget::update()`。在 `render()` 内部调用 `update()` 将导致持续更新,其频率受垂直同步(vsync)限制。
cb 是小部件当前帧的QRhiCommandBuffer 。该函数在录制帧时被调用,但此时没有活动的渲染通道。
另请参阅 initialize()。
[signal] void QRhiWidget::renderFailed()
每当小部件应将其内容渲染到其底层纹理时(无论是由于widget update 还是由于调用了grabFramebuffer()),但小部件没有可用的QRhi 时(这很可能是由于图形配置相关的问题),就会发出此信号。
当出现问题时,该信号可能会被多次发出。请勿假设它只会发出一次。如果错误处理代码只需被通知一次,请将其连接至Qt::SingleShotConnection 。
[protected] QRhiRenderTarget *QRhiWidget::renderTarget() const
返回一个渲染目标对象,该对象必须在render()的重写版本中与QRhiCommandBuffer::beginPass()配合使用。
仅可从initialize() 和render() 中调用。
仅当autoRenderTarget 为true 时才可用。否则,返回值为nullptr ,此时由initialize()的重写实现负责创建和管理深度-模板缓冲区以及QRhiTextureRenderTarget 。
创建graphics pipelines 时,需要一个QRhiRenderPassDescriptor 。可以通过调用renderPassDescriptor(),从返回的QRhiTextureRenderTarget 中查询该信息。
另请参阅 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.