作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

简介

在 Qt widget 中的渲染方式是传统的命令式绘图系统,使用 QPainter 依次为每个界面元素渲染,不断地重复渲染状态。而在 Qt Quick 中修改了界面的渲染方式,自 Qt Quick 2 起统一使用 OpenGL ES 2.0 或 OpenGL 2.0 来渲染界面。这样做的好处是,所有要渲染的界面元素均在最后统一提供给 OpenGL,极大减少状态切换时间和渲染时间。就像写文件,把要写的内容存在缓存后统一写入文件,会比每次写入都重复打开关闭文件要快很多

Scene Graph 场景图与 Qt Quick 2.0 紧密相关,不能单独使用,场景图由 QQuickWindow 类管理和渲染。如果想在 c++ 中把自定义的 Item 添加到场景中,那么就需要继承 QQuickItem 并调用 setFlag(ItemHasContents, true);QQuickItem::updatePaintNode()。本文主要介绍场景图的使用和一些基础元素,这里会涉及到一些图形学的基本概念,例如:材质、纹理、光栅化、图元等,建议参考相关资料,这里不做深入解释

场景结构

场景图由许多预定义的节点类型组成,每种类型都有专门的用途。尽管我们将其称为场景图,但其本质是由继承于 QQuickItem 的类型的节点组成的节点树。该树根据场景中的 QQuickItem 类型构建,然后在内部对该场景进行渲染,最终呈现该场景。只要用户使用 QML 的 Item 及其子类来构建界面,QQuickWindow 就获得场景树,会维护这个场景树,并最终回收资源。场景树对于只使用 QML 和 Javascript 的开发人员来说是完全透明的

节点

类名 描述
QSGNode 场景中所有节点的基类
QSGGeometryNode 表达几何信息(形状、材质)的节点
QSGClipNode 表达裁剪信息的节点
QSGOpacityNode 表达透明信息的节点
QSGTransformNode 表达矩阵操作信息(旋转、平移、缩放)的节点

用户最常用的场景结点是 QSGGeometryNode。它可以实现自定义图形中的几何形体和光学材质。使用 QSGGeometry 可以定义几何坐标,并描述形状或者图元网格。材质定义了像素被如何填充

更多详情请参考官方文档:Scene Graph - Custom Geometry

预处理

节点具有虚函数QSGNode::preprocess(),该函数将在渲染之前被调用。节点子类可以设置标志QSGNode::UsePreprocess并重写QSGNode::preprocess()函数以对其节点进行预处理,为渲染做准备

节点所有权

节点的所有权归创建者,或者设置标志QSGNode::OwnedByParent后归场景图。通常我们会将所有权分配给场景图,因为这样开发人员可以不必关心资源回收的问题

材质

材质描述如何填充 QSGGeometryNode 中几何图形的内部。它封装了一段 OpenGL 着色代码 (Shader Program),提供了足够的灵活性让开发人员决定如何着色。仅管目前大多数 Item 对象使用了非常基本的材质,例如纯色和纹理填充。如果开发人员想修改材质,在QML代码中使用 ShaderEffect 就可以实现一些特定效果。更高级地需使用C++代码

类名 描述
QSGFlatColorMaterial 单色材质类
QSGMaterial 保存着色程序状态的类
QSGMaterialShader OpenGL着色代码类
QSGMaterialType 和QSGMaterial配合使用时的唯一标识符
QSGOpaqueTextureMaterial 不透明纹理材质类
QSGSimpleMaterial 和QSGSimpleMateralShader配合使用时的着色状态保存类的模板类
QSGSimpleMaterialShader 场景着色程序的基类
QSGTextureMaterial 纹理材质类
QSGVertexColorMaterial 顶点材质类

更多详情请参考官方文档:Scene Graph - Simple Material

便捷的节点

场景图 API 是一套偏底层的接口,专注于性能而不是易用性。从头开始编写自定义的几何图形和材质,即使是最基本的几何图形和材质,也需要大量的代码。因此场景图 API 包含了一些节点类,使得常用的自定义节点可以快速开发

类名 描述
QSGSimpleRectNode 继承于QSGGeometryNode,定义了一个被赋予单色材质的矩形图形的节点类
QSGSimpleTextureNode 继承于QSGGeometryNode,定义了一个被赋予纹理材质的矩形图形的节点类

场景图渲染

场景图的渲染发生在 QQuickWindow 类的内部,外部无法访问。但在渲染管线上有几个点可以供开发人员插入自定义节点代码或直接访问OpenGL

更多详情请参考官方文档:Qt Quick Scene Graph Default Renderer

渲染循环

场景渲染有三种方式:基本渲染循环(basic),窗口渲染循环(windows) 和线程渲染循环(threaded)。其中 basic 和 windows 是单线程,而 threaded 是指定线程内渲染。Qt会根据情况自动选择使用哪种方式。当性能不满足,或者出于测试考虑时,可以强制启动QSG_RENDER_LOOP。想知道具体是哪种方式,需要在启动应用时添加参数将QSG_INFO设置为1。要验证使用哪个渲染循环,请启用qt.scenegraph.general日志类别

注意: windows 和 threaded 方式非常依赖于 OpenGL 将交换间隔设定为1。一些显卡驱动允许用户覆盖或关闭这个值,并忽略Qt的修改请求。但如果没有这个设置,会导致交换间隔太短,CPU满负荷运转。如果知道系统不能自动调整vsync-based,请手动设置QSG_RENDER_LOOP=basic来启动 basic 渲染方式

使用 QQuickRenderControl 自定义渲染控制

如果不想使用系统渲染,开发人员可以使用QQuickRenderControl来完全控制渲染过程。此时,美化、同步和渲染都由应用来控制

混合使用场景和OpenGL

场景提供两种方式来整合 OpenGL 内容:直接使用 OpenGL 代码或者直接在场景中添加纹理节点
注意:不管理采用哪种方式,都要保存使用同一个OpenGL环境,否则将产生未知错误
注意:渲染代码要做到线程安全,因为渲染线程很可能不在主(GUI)线程中

直接使用OpenGL代码

通过槽连接QQuickWindow::beforeRendering()QQuickWindow::afterRendering(),让 OpenGL 在场景渲染前或后来执行 OpenGL 代码。其结果就是 OpenGL 内容在场景内容下(被覆盖)或者在其上。这种方式的优点是不需额外使用帧缓存或者内存,缺点是 OpenGL 渲染时机固定。这种方式不能手动 update 元素内容,只能通过在这个元素区域内有其他元素发生变化(比如在QML中调用这个元素区域内一个不可见元素的 visible 属性变一变)才会更新,这是其一大缺点

更多详情请参考官方文档:Scene Graph - OpenGL Under QML

向场景添加纹理节点

这种方式需借助于QQuickFramebufferObject类,场景会将此节点添加到其中。只要给当前元素设置QQuickItem::setFlag(ItemHasContents),Scene Graph 就会调用 updatePainedNode更新这个元素内容。这种方式与Scene Graph的结合性最好

更多详情请参考官方示例:Scene Graph - Rendering FBOs in a thread

日志

类名 描述
qt.scenegraph.time.texture 纹理上传的耗时
qt.scenegraph.time.compilation 编译着色器耗时
qt.scenegraph.time.renderer 渲染器不同步骤耗时
qt.scenegraph.time.renderloop 渲染循环不同阶段耗时
qt.scenegraph.time.glyph 准备字形的距离场耗时
qt.scenegraph.info 场景图和图形栈中的常规信息
qt.scenegraph.renderloop 渲染循环相关的信息。这个日志模式是Qt开发者主要使用的

Qt Quick 渲染之 Scene Graph 详解相关推荐

  1. qt on android qml,Qt on Android: Qt Quick 之 Hello World 图文详解

    在上一篇文章,<Qt on Android:QML 语言基础>中,我们介绍了 QML 语言的语法,在最后我们遗留了一些问题没有展开,这篇呢,我们就正式开始撰写 Qt Quick 程序,而那 ...

  2. Qt Quick 渲染机制

    作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 Scene Graph 的优势 在Qt5中推出了一个新的渲染底层 Scene Graph,来替代Qt4时 ...

  3. 数据结构--图(Graph)详解(四)

    数据结构–图(Graph)详解(四) 文章目录 数据结构--图(Graph)详解(四) 一.图中几个NB的算法 1.普里姆算法(Prim算法)求最小生成树 2.克鲁斯卡尔算法(Kruskal算法)求最 ...

  4. 数据结构--图(Graph)详解(三)

    数据结构–图(Graph)详解(三) 文章目录 数据结构--图(Graph)详解(三) 一.深度优先生成树和广度优先生成树 1.铺垫 2.非连通图的生成森林 3.深度优先生成森林 4.广度优先生成森林 ...

  5. 数据结构--图(Graph)详解(二)

    数据结构–图(Graph)详解(二) 文章目录 数据结构--图(Graph)详解(二) 一.图的存储结构 1.图的顺序存储法 2.图的邻接表存储法 3.图的十字链表存储法 4.图的邻接多重表存储法 二 ...

  6. 数据结构--图(Graph)详解(一)

    数据结构–图(Graph)详解(一) 文章目录 数据结构--图(Graph)详解(一) 一.图的基本概念 1.图的分类 2.弧头和弧尾 3.入度和出度 4.(V1,V2) 和 < V1,V2 & ...

  7. C++框架_之Qt的信号和槽的详解

    目录 C++_之Qt的信号和槽的详解 1.概述 1.1对象树(子对象动态分配空间不需要释放) 2.信号和槽 Qt5 的书写方式:(推荐的使用)★★★★★ Qt4 的书写方式: 3.自定义信号槽 3.1 ...

  8. echart关系树状图_echart——关系图graph详解

    VueEchart组件见上一篇 export default { data () { const title = { // show: true, //是否显示 text: "画布关系图&q ...

  9. Qt图形视图框架:QGraphicsScene详解

    一.描述 1.场景提供了一个用于管理大量2D图形项的平面.该类充当图形项的容器. 它与视图一起用于可视化2D曲面上的图形图形项. 2.场景没有自己的视觉外观,只负责管理图形项. 3.场景的最大优势之一 ...

最新文章

  1. visual-reasoning 笔记
  2. 综述|工业金属平面材料表面缺陷自动视觉检测的研究进展
  3. 微信小程序刷新webview页面问题
  4. 阿里云物联网生活平台简介
  5. phpcms v9 的表单向导功能的使用方法
  6. 浪潮服务器u盘安装系统未找到任何驱动器,u盘重装win10时找不到任何驱动器
  7. ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)
  8. 物理搬砖问题_人物专访|从“搬砖烧炉工”到MIT物理PhD, 很普通、很坚持、很热爱...
  9. 多线程(一) NSThread
  10. 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为MP4)
  11. 计算机网络——数据通信系统(三)
  12. 【sm2算法】基于mbedtls开源库国密算法的使用(二)
  13. 安装排版软件latex
  14. kubernetes device or resource busy的问题
  15. Java学完了仍不会写项目
  16. CCF认证 2018-09 卖菜
  17. 计算机技术与软件业余资格测验证书,在大学能否领到网络工程师资格证?网络工程师考核..._出版资格_帮考网...
  18. @Transient 实体类临时变量
  19. 不得不看的经典软件测试面试问题
  20. 信息学奥赛一本通题库1005 地球人口承载力估计

热门文章

  1. aecc2019能装saber吗_【2018年10月重磅】After Effects CC2019 分享新功能介绍
  2. 超星高级语言程序设计实验作业 (实验04 数组及其在程序设计中的应用)(二)
  3. 数据分析·零散知识点
  4. 不用插件,如何将tif格式的影像精准导入到CAD中?
  5. 力扣LeetCode-哈希表
  6. 爬虫工程师必备技术栈——加密解密以及字符编码原理
  7. 【CDOJ 1323】柱爷的下凡
  8. RQNOJ 篝火晚会
  9. matlab最优轨迹规划,matlab机器人轨迹规划
  10. Java数组初始化长度