PySide6.QtQuick.QQuickRhiItem

class QQuickRhiItem

QQuickRhiItem 类是 QQuickFramebufferObject 的可移植替代方案,它不依赖于 OpenGL,而是允许将渲染与 QRhi API 集成到 Qt Quick 中。更多

PySide6.QtQuick.QQuickRhiItem 的继承图

在版本6.7中添加。

概要

属性

方法

虚拟方法

信号

注意

本文档可能包含从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

QQuickRhiItem 是旧版 QQuickFramebufferObject 类的替代品。后者本质上与 OpenGL / OpenGL ES 绑定,而 QQuickRhiItem 则与 QRhi 类一起工作,允许使用 Vulkan、Metal、Direct 3D 11/12 和 OpenGL / OpenGL ES 运行相同的渲染代码。在概念和功能上它们非常接近,从 QQuickFramebufferObject 迁移到 QQuickRhiItem 是直接的。QQuickFramebufferObject 仍然可用,以确保与直接使用 OpenGL API 的现有应用程序代码的兼容性。

注意

QQuickRhiItem 在使用 Qt Quick 场景图的 software 适配时将无法正常工作。

在大多数平台上,场景图渲染,以及由QQuickRhiItem执行的渲染,将在一个专用线程上进行。因此,QQuickRhiItem类强制实施了项目实现(QQuickItem子类)和实际渲染逻辑之间的严格分离。所有项目逻辑,如暴露给QML的属性和UI相关的辅助函数,必须位于QQuickRhiItem子类中。与渲染相关的所有内容必须位于QQuickRhiItemRenderer类中。为了避免两个线程之间的竞争条件和读写问题,渲染器和项目永远不应读取或写入共享变量。项目和渲染器之间的通信应主要通过QQuickRhiItem::synchronize()函数进行。此函数将在渲染线程上调用,而GUI线程被阻塞。使用队列连接或事件进行项目和渲染器之间的通信也是可能的。

应用程序必须同时继承QQuickRhiItemQQuickRhiItemRenderer。必须重新实现纯虚函数createRenderer(),以返回QQuickRhiItemRenderer子类的新实例。

与QRhiWidget一样,QQuickRhiItem自动管理颜色缓冲区,通常是一个2D纹理(QRhiTexture),或者在使用多重采样时是一个QRhiRenderBuffer。(一些3D API区分纹理和渲染缓冲区,而其他一些API的底层原生资源是相同的;渲染缓冲区主要用于允许在OpenGL ES 3.0中使用多重采样。)

纹理的大小默认会根据项目的大小进行调整(考虑到了device pixel ratio)。如果项目大小发生变化,纹理会以正确的大小重新创建。如果希望使用固定大小,可以将fixedColorBufferWidthfixedColorBufferHeight设置为非零值。

QQuickRhiItem 是一个 texture provider,可以直接用于 ShaderEffects 和其他消耗纹理提供者的类中。

虽然不是主要用例,QQuickRhiItem 也允许集成直接使用3D图形API(如Vulkan、Metal、Direct 3D或OpenGL)的渲染代码。有关在QRhi渲染过程中记录原生命令的详细信息,请参见QRhiCommandBuffer::beginExternal(),以及QRhiTexture::createFrom(),该方法可以包装现有的原生纹理,然后在后续的渲染过程中与QRhi一起使用。另请参见QQuickGraphicsConfiguration,了解如何配置原生3D API环境(例如设备扩展),并注意通过尽早调用QWindow::setVulkanInstance(),可以将QQuickWindow与自定义的QVulkanInstance关联。

注意

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介绍中显示的代码完全相同。顶点和片段着色器也是相同的。这些以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 }
}

查看 场景图 - RHI 纹理项 以获取更复杂的示例。

另请参阅

QQuickRhiItemRenderer 场景图 - RHI 纹理项 场景图和渲染

class TextureFormat

注意

当使用from __feature__ import true_property时,属性可以直接使用,否则通过访问器函数使用。

property alphaBlendingᅟ: bool

控制在绘制由QQuickRhiItem及其渲染器生成的内容纹理的四边形时,是否始终启用混合。

默认值为false。这是出于性能考虑:如果不涉及半透明,因为QQuickRhiItemRenderer清除为不透明颜色并且从不渲染alpha小于1的片段,那么启用混合就没有意义。

如果QQuickRhiItemRenderer子类渲染时涉及半透明,请将此属性设置为true。

注意

在某些条件下,无论此属性的值如何,混合仍然会发生。例如,如果项目的opacity(更准确地说,是从父链继承的组合不透明度)小于1,即使此属性设置为false,混合也会自动启用。

注意

Qt Quick 场景图依赖于并期望预乘的 alpha。例如,如果意图是在渲染器中清除背景到 alpha 值为 0.5,那么确保将红色、绿色和蓝色的清除颜色值也乘以 0.5。否则,混合结果将不正确。

Access functions:
property colorBufferFormatᅟ: QQuickRhiItem.TextureFormat

此属性控制用作颜色缓冲区的纹理的纹理格式。默认值为TextureFormat::RGBA8。QQuickRhiItem支持渲染到QRhiTexture支持的格式子集。只有通过QRhi::isTextureFormatSupported()报告为支持的格式才应指定,否则渲染将无法正常工作。

注意

当项目及其渲染器已经初始化并渲染时,设置新的格式意味着如果由于不同的纹理格式导致关联的QRhiRenderPassDescriptor现在不兼容,则渲染器创建的所有QRhiGraphicsPipeline对象可能变得不可用。类似于动态更改sampleCount,这意味着initialize()或render()实现必须负责释放现有的管道并创建新的管道。

Access functions:
property effectiveColorBufferSizeᅟ: QSize

此属性公开了底层颜色缓冲区(QRhiTexture 或 QRhiRenderBuffer)的大小(以像素为单位)。它用于在 GUI(主)线程、QML 绑定或 JavaScript 中使用。

注意

QQuickRhiItemRenderer 实现,在场景图渲染线程上操作时,不应使用此属性。这些实现应该从 render target 中查询大小。

注意

从主线程的角度来看,该值是异步可用的,这意味着当渲染线程进行渲染时,该值会发生变化。这意味着此属性主要在QML绑定中有用。应用程序代码不能假设在构造QQuickRhiItem对象时该值已经是最新的。

这是一个只读属性。

Access functions:
property fixedColorBufferHeightᅟ: int

项目关联纹理的固定高度,以像素为单位。当需要一个不依赖于项目大小的固定纹理大小时,此属性相关。此大小不会影响项目的几何形状(其在场景中的大小和位置),这意味着纹理的内容将显示为拉伸(放大)或缩小到项目的区域上。

例如,设置一个正好是项目(像素)大小两倍的尺寸,实际上执行了2倍超采样(以两倍分辨率渲染,然后在纹理化场景中与项目对应的四边形时隐式缩小)。

默认值为0。值为0表示纹理的大小跟随项目的大小。(texture size = item size * device pixel ratio)。

Access functions:
property fixedColorBufferWidthᅟ: int

项目关联纹理或渲染缓冲区的固定宽度,以像素为单位。当需要一个不依赖于项目大小的固定颜色缓冲区大小时,此属性相关。此大小对项目的几何形状(其在场景中的大小和位置)没有影响,这意味着纹理的内容将显示为拉伸(放大)或缩小到项目的区域上。

例如,设置一个正好是项目(像素)大小两倍的尺寸,实际上执行了2倍超采样(以两倍分辨率渲染,然后在纹理化场景中与项目对应的四边形时隐式缩小)。

默认值为0。值为0表示纹理的大小跟随项目的大小。(texture size = item size * device pixel ratio)。

Access functions:
property mirrorVerticallyᅟ: bool

此属性控制在绘制纹理四边形时是否翻转纹理UV。它对离屏颜色缓冲区的内容和由QQuickRhiItemRenderer实现的渲染没有影响。

默认值为false

Access functions:
property 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。

Access functions:
__init__([parent=None])
Parameters:

父级QQuickItem

使用给定的parent构造一个新的QQuickRhiItem

alphaBlending()
Return type:

布尔

另请参阅

setAlphaBlending()

属性 alphaBlendingᅟ 的获取器。

alphaBlendingChanged()

属性 alphaBlendingᅟ 的通知信号。

autoRenderTargetChanged()
colorBufferFormat()
Return type:

TextureFormat

另请参阅

setColorBufferFormat()

属性 colorBufferFormatᅟ 的获取器。

colorBufferFormatChanged()

属性 colorBufferFormatᅟ 的通知信号。

abstract createRenderer()
Return type:

QQuickRhiItemRenderer

重新实现此函数以创建并返回QQuickRhiItemRenderer子类的新实例。

此函数将在GUI线程被阻塞时在渲染线程上调用。

effectiveColorBufferSize()
Return type:

QSize

属性 effectiveColorBufferSizeᅟ 的获取器。

effectiveColorBufferSizeChanged()

属性 effectiveColorBufferSizeᅟ 的通知信号。

fixedColorBufferHeight()
Return type:

整数

属性 fixedColorBufferHeightᅟ 的获取器。

fixedColorBufferHeightChanged()

属性 fixedColorBufferHeightᅟ 的通知信号。

fixedColorBufferWidth()
Return type:

整数

属性 fixedColorBufferWidthᅟ 的获取器。

fixedColorBufferWidthChanged()

属性 fixedColorBufferWidthᅟ 的通知信号。

isAutoRenderTargetEnabled()
Return type:

布尔

返回当前的自动深度-模板缓冲区和渲染目标管理设置。

默认情况下,此值为 true

另请参阅

setAutoRenderTarget()

isMirrorVerticallyEnabled()
Return type:

布尔

属性 mirrorVerticallyᅟ 的获取器。

mirrorVerticallyChanged()

属性 mirrorVerticallyᅟ 的通知信号。

sampleCount()
Return type:

整数

另请参阅

setSampleCount()

属性 sampleCountᅟ 的获取器。

sampleCountChanged()

属性 sampleCountᅟ 的通知信号。

setAlphaBlending(enable)
Parameters:

enable – 布尔值

另请参阅

alphaBlending()

属性 alphaBlendingᅟ 的设置器。

setAutoRenderTarget(enabled)
Parameters:

enabled – 布尔值

控制是否由项目自动创建和维护深度模板QRhiRenderBuffer和QRhiTextureRenderTarget。默认值为true。早期调用此函数,例如从派生类的构造函数中调用,将enabled设置为false以禁用此功能。

在自动模式下,深度-模板缓冲区的大小和样本计数遵循颜色缓冲区纹理的设置。在非自动模式下,renderTarget() 和 depthStencilBuffer() 总是返回 None,然后由应用程序的 initialize() 实现来负责设置和管理这些对象。

setColorBufferFormat(format)
Parameters:

格式TextureFormat

另请参阅

colorBufferFormat()

属性 colorBufferFormatᅟ 的设置器。

setFixedColorBufferHeight(height)
Parameters:

height – int

属性 fixedColorBufferHeightᅟ 的设置器。

setFixedColorBufferWidth(width)
Parameters:

width – 整数

属性 fixedColorBufferWidthᅟ 的设置器。

setMirrorVertically(enable)
Parameters:

enable – 布尔值

属性 mirrorVerticallyᅟ 的设置器。

setSampleCount(samples)
Parameters:

样本 – int

另请参阅

sampleCount()

属性 sampleCountᅟ 的设置器。