QSGRenderNode Class
QSGRenderNode 类表示一组针对场景图使用的图形 API 的自定义渲染命令。更多
Header: | #include <QSGRenderNode> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Quick) target_link_libraries(mytarget PRIVATE Qt6::Quick) |
qmake: | QT += quick |
继承: | QSGNode |
公共类型
struct | RenderState |
enum | RenderingFlag { BoundedRectRendering, DepthAwareRendering, OpaqueRendering, NoExternalRendering } |
flags | RenderingFlags |
enum | StateFlag { ViewportState, ScissorState, DepthState, StencilState, ColorState, …, RenderTargetState } |
flags | StateFlags |
公共函数
virtual | ~QSGRenderNode() override |
virtual QSGRenderNode::StateFlags | changedStates() const |
const QSGClipNode * | clipList() const |
(since 6.6) QRhiCommandBuffer * | commandBuffer() const |
virtual QSGRenderNode::RenderingFlags | flags() const |
qreal | inheritedOpacity() const |
const QMatrix4x4 * | matrix() const |
(since 6.0) virtual void | prepare() |
(since 6.5) const QMatrix4x4 * | projectionMatrix() const |
virtual QRectF | rect() const |
virtual void | releaseResources() |
virtual void | render(const QSGRenderNode::RenderState *state) = 0 |
(since 6.6) QRhiRenderTarget * | renderTarget() const |
详细说明
QSGRenderNode 允许创建场景图节点,这些节点可通过QRhi (Qt 6.6 以来的常用方法)、直接通过 3D 图形 API(如 OpenGL、Vulkan 或 Metal)或在使用software
后端时通过QPainter 执行自己的自定义渲染。
QSGRenderNode 是将自定义 2D/3D 渲染集成到Qt Quick 场景的三种方法之一。另外两种方法是在Qt Quick 场景中执行渲染before
或after
,或者针对专用渲染目标(纹理)生成一个独立的渲染通道,然后让场景中的一个项目显示纹理。基于 QSGRenderNode 的方法与前者类似,不涉及额外的渲染传递或渲染目标,并允许在Qt Quick 场景自身渲染的 "内联 "注入自定义渲染命令。有关这三种方法的进一步讨论,请参见Qt Quick Scene Graph。
另请参阅 场景图 - 自定义 QSGRenderNode。
成员类型文档
枚举 QSGRenderNode::RenderingFlag
flags QSGRenderNode::RenderingFlags
从flags() 返回的位掩码的可能值。
常量 | 值 | 说明 |
---|---|---|
QSGRenderNode::BoundedRectRendering | 0x01 | 表示render() 的实现不会在rect() 以项坐标报告的区域之外进行渲染。根据场景图后台的不同,这种节点实现可以提高渲染效率。例如,当场景中的所有渲染节点都设置了此标记时,software 后端可以继续使用更优化的部分更新路径。 |
QSGRenderNode::DepthAwareRendering | 0x02 | 表示render() 的实现符合场景图的预期,只在场景坐标中生成一个 Z 值为 0 的节点,然后通过从RenderState::projectionMatrix() 和matrix() 获取的矩阵进行转换,如render() 的注释所述。根据场景图后台的不同,这种节点实现方式可以提高渲染效率。例如,当场景中的所有渲染节点都设置了该标记时,批处理 OpenGL 渲染器可以继续使用更优化的路径。 |
QSGRenderNode::OpaqueRendering | 0x04 | 表示render() 的实现为rect() 报告的整个区域写出不透明像素。默认情况下,渲染器必须假定render() 也能输出半透明或全透明像素。在某些情况下,设置此标志可以提高性能。 |
QSGRenderNode::NoExternalRendering | 0x08 | 表示prepare() 和render() 的实现只使用QRhi 系列 API,而不是直接调用 OpenGL、Vulkan 或 Metal 等 3D API。 |
RenderingFlags 类型是QFlags<RenderingFlag> 的类型定义。它存储 RenderingFlag 值的 OR 组合。
另请参见 render()、prepare()、rect() 和QRhi 。
枚举 QSGRenderNode::StateFlag
flags QSGRenderNode::StateFlags
此枚举包含从changedStates() 返回的位掩码中可能使用的值。
常量 | 值 | 说明 |
---|---|---|
QSGRenderNode::ViewportState | 0x40 | 视口 |
QSGRenderNode::ScissorState | 0x04 | 剪切测试启用状态,剪切矩形 |
QSGRenderNode::DepthState | 0x01 | 此值在 Qt 6 中无效。 |
QSGRenderNode::StencilState | 0x02 | 此值在 Qt 6 中没有影响。 |
QSGRenderNode::ColorState | 0x08 | 此值在 Qt 6 中没有影响。 |
QSGRenderNode::BlendState | 0x10 | 此值在 Qt 6 中没有影响。 |
QSGRenderNode::CullState | 0x20 | 此值在 Qt 6 中没有影响。 |
QSGRenderNode::RenderTargetState | 0x80 | 此值在 Qt 6 中无影响。 |
StateFlags 类型是QFlags<StateFlag> 的类型定义。它存储 StateFlag 值的 OR 组合。
成员函数文档
[override virtual noexcept]
QSGRenderNode::~QSGRenderNode()
销毁呈现节点。派生类应执行与releaseResources() 类似的清理。
对于QRhi 和QRhiBuffer 、QRhiTexture 、QRhiGraphicsPipeline 等资源,使用智能指针(如 std::unique_ptr)通常是一种好的做法,这样通常可以避免实现析构函数的需要,并使源代码更加紧凑。不过,请记住,实现releaseResources() 仍然很重要,因为它很可能包含对 unique_ptrs 的大量 reset() 调用。
另请参见 releaseResources()。
[virtual]
QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
该函数应返回一个掩码,其中每个位都代表由render() 函数改变的图形状态。
注意: 在 Qt XML 6 和基于QRhi 的渲染中,唯一相关的值是ViewportState 和ScissorState 。其他值也可以返回,但在实际应用中会被忽略。
常量 | 说明 |
---|---|
ViewportState | 视口 |
ScissorState | 剪刀测试启用状态,剪刀矩形 |
DepthState | 此值在 Qt 6 中无效。 |
StencilState | 此值在 Qt 6 中无影响。 |
ColorState | 此值在 Qt 6 中没有影响。 |
BlendState | 此值在 Qt 6 中没有影响。 |
CullState | 此值在 Qt 6 中没有影响。 |
RenderTargetState | 此值在 Qt 6 中没有影响。 |
默认实现返回 0,表示render() 中没有更改相关状态。
注意: 此函数可在render() 之前调用。
const QSGClipNode *QSGRenderNode::clipList() const
返回当前剪辑列表。
[since 6.6]
QRhiCommandBuffer *QSGRenderNode::commandBuffer() const
返回当前的命令缓冲区。
此函数在 Qt 6.6 中引入。
另请参阅 renderTarget()。
[virtual]
QSGRenderNode::RenderingFlags QSGRenderNode::flags() const
返回描述此呈现节点行为的标志。
默认实现返回 0。
另请参阅 RenderingFlag 和rect()。
qreal QSGRenderNode::inheritedOpacity() const
返回当前的有效不透明度。
const QMatrix4x4 *QSGRenderNode::matrix() const
返回当前模型视图矩阵的指针。
[virtual, since 6.0]
void QSGRenderNode::prepare()
在帧准备阶段调用。每次调用render() 之前都会调用该函数。
与render() 不同,该函数会在场景图开始在底层命令缓冲区记录当前帧的渲染传递之前调用。这在使用 Vulkan 等图形应用程序接口进行渲染时非常有用,因为在这些应用程序接口中,需要在渲染传递之前记录复制类型的操作。
默认实现为空。
在实现使用QRhi 渲染的QSGRenderNode 时,可通过QQuickWindow::rhi() 从QQuickWindow 查询QRhi 对象。要获取用于提交工作的QRhiCommandBuffer ,请调用commandBuffer() 。要查询活动呈现目标的信息,请调用renderTarget() 。详情请参阅{Scene Graph - Custom QSGRenderNode}示例。
此函数在 Qt 6.0 中引入。
[since 6.5]
const QMatrix4x4 *QSGRenderNode::projectionMatrix() const
返回当前投影矩阵的指针。
在render() 中,该矩阵与RenderState::projectionMatrix() 返回的矩阵相同。该获取器的存在是为了让prepare() 也能查询投影矩阵。
在使用现代图形 API 或 Qt XML 自身的图形抽象层时,人们很可能希望将*projectionMatrix() * *matrix()
加载到统一缓冲区中。但这需要在prepare() 中完成,因此不在渲染传递的记录范围内。这就是为什么在prepare() 和render() 中可以直接从QSGRenderNode 中查询这两个矩阵的原因。
该函数在 Qt 6.5 中引入。
[virtual]
QRectF QSGRenderNode::rect() const
返回render() 所触及区域的项目坐标矩形边界。该值仅在flags() 包括BoundedRectRendering 时使用,否则将被忽略。
结合BoundedRectRendering 报告矩形对于software
后端尤为重要,否则场景中的呈现节点将触发全屏更新,从而跳过所有部分更新优化。
对于覆盖相应QQuickItem 整个区域的呈现节点,返回值将为(0, 0, item->width(), item->height())。
注: 由于场景图节点不受QQuickItem 几何图形的限制,因此节点也可以在项目宽度和高度指定的边界之外自由渲染,只要此函数正确报告即可。
另请参阅 flags().
[virtual]
void QSGRenderNode::releaseResources()
当需要立即释放该节点分配的所有自定义图形资源时,将调用此函数。如果节点没有通过正在使用的图形 API 直接分配图形资源(缓冲区、纹理、渲染目标、栅栏等),则无需在此做任何操作。
如果不释放所有自定义资源,在某些系统上会导致图形设备丢失情况下的不正确行为,因为图形系统的后续重新初始化可能会失败。
注意: 某些场景图后端可能选择不调用此函数。因此,预计QSGRenderNode 实现会在析构函数和 releaseResources() 中执行清理。
与析构函数不同的是,在调用 releaseResources() 之后调用render() 时,预计它可以重新初始化所需的所有资源。
对于 OpenGL,调用析构函数和该函数时,场景图的 OpenGL 上下文都是当前的。
[pure virtual]
void QSGRenderNode::render(const QSGRenderNode::RenderState *state)
该函数由渲染器调用,应通过QRhi 直接调用命令或直接通过底层图形 API(OpenGL、Direct3D 等)绘制该节点。
有效不透明度可通过inheritedOpacity() 获取。
投影矩阵可通过state 获取,而模型视图矩阵可通过matrix() 获取。组合矩阵就是投影矩阵乘以模型视图矩阵。投影矩阵可确保场景中项目的正确堆叠。
在使用所提供的矩阵时,顶点数据的坐标系遵循通常的QQuickItem 约定:左上角为(0,0),右下角为相应QQuickItem 的宽度()和高度()减 1。例如,假设每个顶点的坐标布局为两个浮点(x-y),那么一个覆盖半个项目的三角形可按逆时针方向指定为(宽-1,高-1)、(0,0)、(0,高-1)。
注: QSGRenderNode 是实现自定义 2D 或 2.5DQt Quick 项目的一种方法。它并非用于将真正的 3D 内容集成到Qt Quick 场景中。整合自定义渲染的其他方法可以更好地支持这种用例。
注: QSGRenderNode 的性能明显优于基于纹理的方法(如QQuickRhiItem ),尤其是在片段处理能力有限的系统上。这是因为它避免了渲染到纹理后再绘制纹理四边形。相反,QSGRenderNode 允许记录绘制调用,与场景图的其他命令保持一致,避免了额外的渲染目标和可能昂贵的纹理和混合。
剪切信息会在调用函数前计算出来。希望将剪切考虑在内的程序可以根据state 中的信息设置剪切或模版。模版缓冲区中会填充必要的剪辑形状,但模版测试的实现取决于实现。
有些场景图后端,特别是软件,不使用剪刀或模板。在这些软件中,剪辑区域是作为普通的QRegion 提供的。
在实现使用QRhi 渲染的QSGRenderNode 时,可通过QQuickWindow::rhi() 从QQuickWindow 查询QRhi 对象。要获取用于提交工作的QRhiCommandBuffer ,请调用commandBuffer() 。要查询活动呈现目标的信息,请调用renderTarget() 。详情请参阅{Scene Graph - Custom QSGRenderNode}示例。
使用 Qt 6 及其基于QRhi 的场景图渲染器,调用此函数时,即使正在使用 OpenGL,也不应假设活动(OpenGL)状态。调用此函数时,对命令列表/缓冲区上绑定的流水线和动态状态不做任何假设。
注意: 应禁用深度写入。启用深度写入可能会导致意想不到的结果,这取决于所使用的场景图后端和场景中的内容,因此请谨慎使用。
注意: 在 Qt XML 6 中,changedStates() 的用途有限。更多信息,请参阅changedStates() 文档。
对于某些图形 API,包括直接使用QRhi 时,可能还需要重新实现prepare() 或连接到QQuickWindow::beforeRendering() 信号。在命令缓冲区记录渲染过程的开始(Vulkan 时为 vkCmdBeginRenderPass,Metal 时为通过 MTLRenderCommandEncoder 开始编码)之前,会调用/发送这些信号。使用此类 API 时,无法在 render() 内进行记录复制操作。相反,应在prepare() 或连接到 beforeRendering(使用 DirectConnection)的插槽中进行此类操作。
另请参见 QSGRendererInterface 和QQuickWindow::rendererInterface()。
[since 6.6]
QRhiRenderTarget *QSGRenderNode::renderTarget() const
返回当前的呈现目标。
提供该功能主要是为了使prepare() 和render() 的实现能够使用QRhi 访问QRhiRenderTarget 的renderPassDescriptor 或pixel size 。
要构建QRhiGraphicsPipeline (这意味着必须提供QRhiRenderPassDescriptor ),请从呈现目标中查询 renderPassDescriptor。不过,请注意,在自定义QQuickItem 和QSGRenderNode 的生命周期内,呈现目标可能会发生变化。例如,考虑一下在项目或其祖先上动态设置layer.enabled: true
时会发生什么:这会触发呈现到纹理中,而不是直接呈现到窗口中,这意味着QSGRenderNode 从此将使用不同的呈现目标。新的呈现目标可能具有不同的像素格式,这可能会导致已构建的图形管道不兼容。这可以通过以下逻辑来处理:
if (m_pipeline && renderTarget()->renderPassDescriptor()->serializedFormat() != m_renderPassFormat) { delete m_pipeline; m_pipeline = nullptr; } if (!m_pipeline) { // Build a new QRhiGraphicsPipeline. // ... // Store the serialized format for fast and simple comparisons later on. m_renderPassFormat = renderTarget()->renderPassDescriptor()->serializedFormat(); }
此函数在 Qt 6.6 中引入。
另请参阅 commandBuffer()。
© 2025 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.