- class QQuickRhiItem#
QQuickRhiItem
类是QQuickFramebufferObject
的另一种便携式替代品,它不依赖于 OpenGL,而是允许通过 Qt Quick 与 QRhi API 集成渲染。 更多…新版本 6.7。
摘要#
属性#
方法#
def
__init__()
def
alphaBlending()
def
sampleCount()
虚函数#
信号#
备注
此文档可能包含自动从C++转换为Python的片段。我们始终欢迎对片段翻译的贡献。如果您发现翻译问题,您也可以通过在https:/bugreports.qt.io/projects/PYSIDE上创建票据来告知我们。
详细描述#
警告
本节包含自动从C++转换为Python的片段,可能包含错误。
备注
QQuickRhiItem
在Qt 6.7中处于技术预览状态。API处于开发中,可能会发生变化。QQuickRhiItem
是Qt Quick世界中的QRhiWidget的对应物。这两个都可以被继承,它们都允许记录面向离屏颜色缓冲区的基于QRhi的渲染。然后,生成的2D图像与Qt Quick场景的其余部分进行合成。备注
虽然
QQuickRhiItem
是一个公共的 Qt API,Qt Gui 模块中的 QRhi 类家族,包括 QShader 和 QShaderDescription,提供有限的兼容性保证。对于这些类没有源代码或二进制兼容性保证,这意味着 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
类中。为了避免来自两个线程的竞态条件和读写问题,确保渲染器和项目不要读写共享变量非常重要。项目与渲染器之间的通信应主要通过QQuickRhiItem
::synchronize()函数进行。此函数将在渲染线程上调用,同时GUI线程被阻塞。对于项目与渲染器之间的通信,也可以使用入队连接或事件。应用程序必须同时派生自
QQuickRhiItem
和QQuickRhiItemRenderer
。纯虚函数createRenderer()
必须被重新实现,以返回一个QQuickRhiItemRenderer
子类的新实例。与QRhiWidget类似,
QQuickRhiItem
会自动管理颜色缓冲区,通常是一个二维纹理(QRhiTexture)或者当使用多采样时是一个QRhiRenderBuffer。(某些3D API在纹理和渲染缓冲区之间进行区分,而在其他某些API中,底层原生资源是相同的;渲染缓冲区主要用于允许OpenGL ES 3.0进行多采样)默认情况下,纹理的大小将自适应于项目的大小(考虑了
device pixel ratio
)。如果项目大小改变,会将纹理重新创建为正确的尺寸。如果更喜欢固定大小,将fixedColorBufferWidth
和fixedColorBufferHeight
设置为非零值。QQuickRhiItem
是一个纹理提供器
,可以直接用于 ShaderEffects 以及其他使用纹理提供器的类。虽然不是主要用途,
QQuickRhiItem
还允许引入直接使用 3D 图形 API(如 Vulkan、Metal、Direct 3D 或 OpenGL)的渲染代码。有关在 QRhi 渲染过程中记录本地命令的详细信息,请参阅 QRhiCommandBuffer::beginExternal(),有关将现有本地纹理包装并随 QRhi 在后续渲染过程中使用的详细信息,请参阅 QRhiTexture::createFrom()。关于配置本地 3D API 环境(例如设备扩展)的信息也请见QQuickGraphicsConfiguration
,注意可以在足够早的时候通过调用 QWindow::setVulkanInstance() 将自定义 QVulkanInstance 与QQuickWindow
相关联。备注
QQuickRhiItem
总是使用与QQuickWindow
相同的 QRhi 实例(以及更广泛的,相同的 OpenGL 上下文、Vulkan 设备等)。为了选择哪个底层 3D 图形 API 被使用,请在足够早的时候在QQuickWindow
上调用setGraphicsApi()
。在场景图初始化后无法更改,并且场景中所有QQuickRhiItem
实例都将使用相同的 3D API 进行渲染。一个简单的示例
以下是一个
QQuickRhiItem
的子类的示例。以下是它的完整形式。它使用透视投影渲染一个三角形,三角形的旋转基于自定义项目的angle
属性。(这意味着它可以被动画如来自 QML 的 NumberAnimation 驱动。)class ExampleRhiItemRenderer(QQuickRhiItemRenderer): # public def initialize(cb): def synchronize(item): def render(cb): # private m_rhi = None std.unique_ptr<QRhiBuffer> m_vbuf std.unique_ptr<QRhiBuffer> m_ubuf std.unique_ptr<QRhiShaderResourceBindings> m_srb std.unique_ptr<QRhiGraphicsPipeline> m_pipeline m_viewProjection = QMatrix4x4() m_angle = 0.0f class ExampleRhiItem(QQuickRhiItem): Q_OBJECT QML_NAMED_ELEMENT(ExampleRhiItem) Q_PROPERTY(float angle READ angle WRITE setAngle NOTIFY angleChanged) # public QQuickRhiItemRenderer createRenderer() override float angle() { return m_angle; } def setAngle(a): # signals def angleChanged(): # private m_angle = 0.0f QQuickRhiItemRenderer ExampleRhiItem.createRenderer() return ExampleRhiItemRenderer() def setAngle(self, a): if m_angle == a: return m_angle = a angleChanged.emit() update() def synchronize(self, rhiItem): item = ExampleRhiItem(rhiItem) if item.angle() != m_angle: m_angle = item.angle() def getShader(name): f = QFile(name) return f.open(QIODevice.ReadOnly) if QShader.fromSerialized(f.readAll()) else QShader() 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, def initialize(self, cb): if m_rhi != rhi(): m_pipeline.reset() m_rhi = rhi() if not 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(":/shaders/color.vert.qsb") }, { QRhiShaderStage.Fragment, getShader(":/shaders/color.frag.qsb") } }) inputLayout = QRhiVertexInputLayout() 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() resourceUpdates = m_rhi.nextResourceUpdateBatch() resourceUpdates.uploadStaticBuffer(m_vbuf.get(), vertexData) cb.resourceUpdate(resourceUpdates) 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) def render(self, cb): resourceUpdates = m_rhi.nextResourceUpdateBatch() modelViewProjection = m_viewProjection modelViewProjection.rotate(m_angle, 0, 1, 0) resourceUpdates.updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData()) clearColor = QColor.fromRgbF(0.4f, 0.7f, 0.0f, 1.0f) cb.beginPass(renderTarget(), clearColor, { 1.0f, 0 }, resourceUpdates) cb.setGraphicsPipeline(m_pipeline.get()) outputSize = renderTarget().pixelSize() cb.setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height())) cb.setShaderResources() QRhiCommandBuffer.VertexInput vbufBinding(m_vbuf.get(), 0) cb.setVertexInput(0, 1, vbufBinding) cb.draw(3) cb.endPass()
值得注意的是,这个简单的类几乎与 QRhiWidget 介绍中所示的代码完全相同。顶点和片元着色器的代码与那里显示的相同。
一旦将我们的自定义项目公开给 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 } }
有关更复杂的示例,请参阅 场景图 - RHI 纹理项目。
另见
QQuickRhiItemRenderer
场景图 - RHI纹理项 场景图和渲染- class TextureFormat#
备注
可以在使用
from __feature__ import true_property
时直接使用属性,否则通过访问函数使用。- property alphaBlending: bool#
控制是否在绘制使用
QQuickRhiItem
和其渲染器生成的内容纹理的矩形时始终启用混合。默认值是
false
。这是出于性能考虑:如果没有半透明效果,因为QQuickRhiItemRenderer
清除到不透明颜色,并且永远不会渲染 alpha 值小于 1 的片段,那么启用混合就没有意义。如果
QQuickRhiItemRenderer
子类绘制时涉及半透明,则将此属性设置为 true。备注
在特定情况下,即使此属性的值为 false,也会执行混合。例如,如果项的
opacity
(更确切地说,从父级链继承的合成不透明度)小于 1,即使此属性设置为 false,也会自动启用混合。备注
Qt Quick 场景图依赖于并期望预乘 alpha。例如,如果要在渲染器中将背景清除到 alpha 值为 0.5,则务必将红色、绿色和蓝色清除颜色值乘以 0.5。否则,混合结果将是不正确的。
- property colorBufferFormat: QQuickRhiItem.TextureFormat#
此属性控制用作颜色缓冲区的纹理的纹理格式。默认值是 TextureFormat::RGBA8。
QQuickRhiItem
仅支持渲染到 QRhiTexture 支持的格式子集。仅应指定 QRhi::isTextureFormatSupported() 报告为支持的格式,否则渲染将无法正常工作。备注
当项及其渲染器已经被初始化并渲染完毕时,设置新的格式意味着由渲染器创建的所有 QRhiGraphicsPipeline 对象可能变得不可用,如果关联的 QRhiRenderPassDescriptor 现在由于不同的纹理格式而失效。类似于动态改变
sampleCount
,这意味着 initialize() 或 render() 的实现必须注意释放现有的管路并创建新的。此属性暴露了底层颜色缓冲区(QRhiTexture 或 QRhiRenderBuffer)的尺寸(以像素为单位)。它在 GUI(主)线程上提供使用,用于 QML 绑定或 JavaScript。
备注
QQuickRhiItemRenderer
实现不应使用此属性。它们应该查询render target
的大小。备注
从主线程的角度来看,值异步可用,即当渲染线程发生渲染时值发生变化。这意味着此属性主要用于 QML 绑定。应用代码不应假设当
QQuickRhiItem
对象被构造时值已经是最新的。这是一个只读属性。
- 属性 fixedColorBufferHeight: int#
这项关联纹理的固定高度(以像素为单位)。当需要一个不依赖于项大小的固定纹理大小时,与此相关。此大小对项的几何形状没有影响(其大小和场景中的位置),这意味着纹理的内容将拉伸(放大)或缩小到项的区域上。
例如,将大小设置为项的大小(像素)的两倍,相当于执行了 2 倍的超采样(以两倍分辨率渲染,然后在纹理 quad 时隐式缩放)。
默认值为
0
。值为 0 意味着纹理的大小遵循项大小。(纹理大小
=项大小
*设备像素比率
)。- 属性 fixedColorBufferWidth: int#
项目中关联的纹理或渲染缓冲区的固定宽度,单位为像素。当需要固定的颜色缓冲区大小,而不依赖于项目大小时适用。这个大小对项目(其在场景中的大小和位置)的几何形状没有影响,这意味着纹理的内容将在项目区域上拉伸(放大)或缩小。
例如,将大小设置为项的大小(像素)的两倍,相当于执行了 2 倍的超采样(以两倍分辨率渲染,然后在纹理 quad 时隐式缩放)。
默认值为
0
。值为 0 意味着纹理的大小遵循项大小。(纹理大小
=项大小
*设备像素比率
)。- 属性 mirrorVertically: bool#
该属性控制绘制纹理四边形时是否翻转纹理UV。它对离屏颜色缓冲区的内容以及由
QQuickRhiItemRenderer
实现的渲染没有影响。默认值是
false
。- 属性 sampleCount: int#
该属性控制多采样抗锯齿的样本计数。默认值是
1
,表示关闭MSAA。有效值是 1、4、8,有时是 16 和 32。可以使用 QRhi::supportedSampleCounts() 在运行时查询支持的样本计数,但通常应用程序应请求 1(无MSAA)、4x(普通MSAA)或 8x(高MSAA)。
备注
设置新值意味着渲染器创建的 QRhiGraphicsPipeline 对象必须从那时起使用相同的样本计数。使用不同样本计数创建的现有 QRhiGraphicsPipeline 对象不再可以使用。当值发生变化时,所有颜色和深度-模板缓冲区将自动销毁和重新创建,并且再次调用
initialize()
。然而,当isAutoRenderTargetEnabled()
为false
时,管理此内容(与深度-模板缓冲区或额外的颜色缓冲区相关)将由应用程序负责。将样本计数从默认的1更改为更高的值意味着
colorTexture()
变为None
,而msaaColorBuffer()
开始返回一个有效的对象。切换回1(或0)意味着相反:在下一次调用initialize()时,msaaColorBuffer()将返回None
,而colorTexture()将再次变回有效。此外,只要样本计数大于1(即使用MSAA),resolveTexture()
返回一个有效的(非多采样)QRhiTexture。- __init__([parent=None])#
- 参数:
parent –
QQuickItem
用给定的 parent 构造一个新的 QQuickRhiItem。
- alphaBlending()#
- 返回类型:
bool
属性
alphaBlendingᅟ
的获取器。- alphaBlendingChanged()#
属性
alphaBlendingᅟ
的通知信号。- autoRenderTargetChanged()#
- colorBufferFormat()#
- 返回类型:
另见
属性
colorBufferFormatᅟ
的获取器。- colorBufferFormatChanged()#
属性
colorBufferFormatᅟ
的通知信号。- 摘要 createRenderer()#
- 返回类型:
重写此函数以创建并返回一个
QQuickRhiItemRenderer
子类的实例。此函数将在渲染线程上调用,同时GUI线程被阻塞。
属性
effectiveColorBufferSizeᅟ
的获取器。- effectiveColorBufferSizeChanged()#
属性
effectiveColorBufferSizeᅟ
改变的通知信号。- fixedColorBufferHeight()#
- 返回类型:
int
属性
fixedColorBufferHeightᅟ
的获取器。- fixedColorBufferHeightChanged()#
属性
fixedColorBufferHeightᅟ
改变的通知信号。- fixedColorBufferWidth()#
- 返回类型:
int
属性
fixedColorBufferWidthᅟ
的获取器。- fixedColorBufferWidthChanged()#
属性
fixedColorBufferWidthᅟ
改变的通知信号。- isAutoRenderTargetEnabled()#
- 返回类型:
bool
返回当前自动深度-模板缓冲区和渲染目标管理设置。
默认情况下此值为
true
。- isMirrorVerticallyEnabled()#
- 返回类型:
bool
属性
mirrorVerticallyᅟ
的获取器。- mirrorVerticallyChanged()#
属性
mirrorVerticallyᅟ
的通知信号。- sampleCount()#
- 返回类型:
int
属性
sampleCountᅟ
的获取器。- sampleCountChanged()#
属性
sampleCountᅟ
的通知信号。- setAlphaBlending(enable)#
- 参数:
enable – bool
属性
alphaBlendingᅟ
的设置器。- setAutoRenderTarget(enabled)#
- 参数:
enabled – bool
控制项是否自动创建和维持深度-模板 QRhiRenderBuffer 和 QRhiTextureRenderTarget。默认值是
true
。例如,从派生类的构造函数中尽早调用此函数,并将enabled
设置为false
以禁用此功能。在自动模式下,深度-模板缓冲区的大小和样本计数遵循颜色缓冲纹理的设置。在非自动模式下,renderTarget() 和 depthStencilBuffer() 总是返回
None
,此时初始化() 函数的实现取决于应用程序,以负责设置和管理这些对象。- setColorBufferFormat(format)#
- 参数:
format –
TextureFormat
另见
属性
colorBufferFormatᅟ
的设置器。- setFixedColorBufferHeight(height)#
- 参数:
height – int
另见
属性
fixedColorBufferHeightᅟ
的设置器。- setFixedColorBufferWidth(width)#
- 参数:
width – int
属性
fixedColorBufferWidthᅟ
的设置器。- setMirrorVertically(enable)#
- 参数:
enable – bool
设置属性
mirrorVertically属性
的值。- setSampleCount(samples)#
- 参数:
samples – int
设置属性
sampleCount属性
的值。