在 Qt C++ 中,场景图(Scene Graph)架构主要用于Qt Quick(QML)的底层渲染系统。自 Qt 5 起,Qt Quick 使用一个名为Scene Graph的图形渲染架构来高效地绘制 UI 元素。
场景图是一个保留模式(retained-mode)的渲染系统,它将 QML 元素转换为一系列低级的图形节点(nodes),然后交由 GPU 渲染。这套架构主要由以下几类核心类组成:
一、核心 Scene Graph 类(位于QtQuick模块)
1.QSGNode
- 场景图中所有节点的基类。
- 定义了节点类型(GeometryNode、TransformNode、ClipNode 等)和父子关系。
- 不直接用于绘图,而是组织结构。
2.QSGGeometryNode
- 继承自
QSGNode。 - 包含几何数据(顶点、索引)和材质(
QSGMaterial)。 - 是实际用于渲染可视内容的节点。
3.QSGMaterial
- 描述如何渲染几何体(着色器、uniform 变量等)。
- 需配合
QSGMaterialShader使用。 - 可自定义以实现特殊视觉效果。
4.QSGMaterialShader
- 封装 OpenGL(或 Vulkan/Metal)着色器代码。
- 与
QSGMaterial配对使用,负责编译和绑定 shader。
5.QSGTexture
- 表示纹理资源。
- 可从 QImage、OpenGL 纹理 ID 或 FBO 创建。
- 常用于
QSGOpaqueTextureMaterial或QSGTextureMaterial。
6.QSGTransformNode
- 表示空间变换(平移、旋转、缩放)。
- 影响其子节点的坐标。
7.QSGClipNode
- 定义裁剪区域(scissor 或 stencil 裁剪)。
- 子节点只在裁剪区域内可见。
8.QSGRootNode
- 场景图的根节点。
- 每个 QQuickItem 对应一个子场景图,最终挂载到根节点下。
二、与 QML/Quick 集成的类
9.QQuickItem
- 所有可视 QML 元素(如 Rectangle、Image)的 C++ 基类。
- 可重写
updatePaintNode()来自定义场景图节点(这是集成自定义渲染的主要入口)。
class MyItem : public QQuickItem { Q_OBJECT public: MyItem() { setFlag(ItemHasContents, true); } protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; };10.QSGRendererInterface
- 提供对底层图形 API(OpenGL、Vulkan、Metal、Direct3D)的抽象。
- 在高级自定义渲染中使用。
11.QSGRenderNode(Qt 5.8+)
- 允许完全绕过标准场景图渲染流程,插入自定义 OpenGL/Vulkan 渲染命令。
- 适用于复杂 3D 内容或高性能需求。
三、辅助类
- QSGVertex/QSGGeometry:用于定义顶点格式和几何数据。
- QSGSimpleRectNode/QSGSimpleTextureNode:便捷类,快速创建矩形或纹理节点。
- QSGFlatColorMaterial/QSGTextureMaterial:预定义材质,简化开发。
四、线程模型相关
- 场景图通常在渲染线程(render thread)中运行,与 GUI 线程分离。
- 自定义
QQuickItem时需注意线程安全:updatePaintNode()在渲染线程调用。- 数据同步需通过
QQuickItem::update()触发,并在updatePaintNode中安全读取。
总结:常用类关系简图
QQuickItem └── (owns) → QSGNode (via updatePaintNode) ├── QSGGeometryNode ──┬── QSGGeometry │ └── QSGMaterial ── QSGMaterialShader ├── QSGTransformNode ├── QSGClipNode └── QSGRenderNode (optional)应用场景
- 自定义高性能 UI 控件(如波形图、粒子效果)。
- 混合 2D/3D 渲染(如嵌入 OpenGL 内容)。
- 优化复杂动画性能。
如需深入了解,可参考 Qt 官方文档:
- Qt Quick Scene Graph
- Custom Geometry in Scene Graph
如果你有具体需求(比如“如何在 QML 中嵌入自定义 OpenGL 渲染”),也可以告诉我,我可以提供完整示例。