Qt6.1教程:Qt Quick3D渲染实例

QtQuick3D在Qt 6.1中引入了对实例渲染的支持。这是图形处理器(GPU)的一项功能,可以极大地提高性能。实例化渲染可以通过一次绘制调用来渲染大量项目。

Qt组件推荐:

  • QtitanRibbon| 下载试用: 遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
  • QtitanChart | 下载试用 :是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。并且支持所有主要的桌面

QtQuick3D在Qt 6.1中引入了对实例渲染的支持。这是图形处理器(GPU)的一项功能,可以极大地提高性能。实例化渲染可以通过一次绘制调用来渲染大量项目。(对于熟悉低级OpenGL的人来说,函数glDrawElementsInstanced是一个示例。)

一个简单的实例渲染示例,显示了20000个金属甜甜圈形状。

在我的开发机器上使用这个新的实例功能,QtQuick3D可以以每秒60帧(FPS)的速度渲染一百万个立方体,仅使用2%的CPU时间。同样的场景在Qt 6.0中使用API重新创建,使用Repeater3D生成立方体,在一万个立方体时开始挣扎:只能管理42 FPS,并且使用100%的CPU。

下面是上图所示的简单例子的源代码,创建一个场景,显示20000个位置、颜色和旋转随机的金属甜甜圈形状。

import QtQuick3Dimport QtQuick3D.Helpersimport QtQuickWindow {    width: 800    height: 450    visible: true    View3D {        anchors.fill: parent        camera: camera        environment: SceneEnvironment {            backgroundMode: SceneEnvironment.SkyBox            lightProbe: Texture {                source: "skybox.hdr"            }            probeExposure: 3        }        PerspectiveCamera {            id: camera            position: Qt.vector3d(0, 300, 500)            eulerRotation.x: -25        }        DirectionalLight {            eulerRotation.x: -30            eulerRotation.y: -70        }        RandomInstancing {            id: randomTable            instanceCount: 20000            position: InstanceRange { from: Qt.vector3d(-5000, -2000, -9000); to: Qt.vector3d(5000, 200, 500) }            rotation: InstanceRange { from: Qt.vector3d(20, 0, -45); to: Qt.vector3d(60, 0, 45) }            color: InstanceRange { from: Qt.rgba(0.1, 0.1, 0.1, 1); to: Qt.rgba(1, 1, 1, 1) }        }        Model {            instancing: randomTable            source: "torus.mesh"            materials: PrincipledMaterial { metalness: 1.0; roughness: 0.2; baseColor: "#ffffff" }        }          }}

API

实例化API的主要原理是明确的。它不会尝试自动检测现有API中实例化的机会。

起点是Instancing对象:一个定义如何呈现每个副本的表。修改是变换(位置,旋转和比例);颜色(与模型材料混合);以及可用于自定义材料的自定义数据。在6.1中,有两种现成的QML类型:

  • InstanceList允许您枚举所有实例并绑定到每个实例的属性。

  • 如上所示,RandomInstancing提供了一种快速测试和原型化的方法。

其他种类的实例表可以使用C ++ API轻松定义。我们将在以后的版本中添加其他QML实例化表。可能包括由数据模型定义的表,以及从外部源读取的表。

一旦定义了表,就可以通过设置其实例化属性将其应用于模型。单个表可以同时与多个不同模型一起使用。

通过编写自定义着色器代码,可以使用实例化 来控制其他属性,例如基于物理的渲染的变量,骨骼动画权重,变形或可以用自定义材质表达的任何其他内容。当前,实例化表中的自定义数据被限制为四个浮点数。

Qt 6.1中的custominstancing示例使用自定义材料和用C ++实现的实例表来绘制一个复杂的场景,该场景仅包含一个重复了多次的单个多维数据集:

自定义实例化示例显示了如何将实例化渲染与自定义材质结合在一起。

权衡取舍

谁不希望性能提高100倍们应该把所有事情实例化吗然,实例化并非万能的灵丹妙药,它也不总是适合这项工作的合适工具。以下是一些注意事项:

  • 首先:实例化是指使用定义明确的修改来渲染同一模型的大量副本。当绘制少量非常不同的东西时,它将无济于事。

  • 主要的改进是在CPU和内存使用方面。GPU的性能好坏参半:我们通过减少绘制调用的次数以及可能的数据量来获得改进,但是顶点着色器更加复杂,因为它需要在每个实例中进行多次转换。

  • 渲染单个模型时,QtQuick3D将分别对不透明和半透明的对象进行排序,并以最佳顺序对其进行渲染。使用实例化时,GPU将按照实例化表指定的顺序进行渲染,而QtQuick3D不会为您对该表进行排序。这样可以节省大量CPU时间,但有两个后果:

    • 不透明的对象将不会以最佳顺序进行渲染,这意味着同一像素可能会被多次写入,从而导致片段着色器进行更多工作,并可能使性能变差

    • 对于半透明的对象,仅当项目从前向后渲染时,混合才是正确的。如果副本之间的重叠不太多,或者每个副本的不透明度很低,那么这可能不是一个大问题。但是,在最坏的情况下,它可能看起来像这样:

      不透明度2

技术预览

Qt 6.1中的技术预览中提供了实例化,Qt 6.2中将完全支持实例化。我们不打算对API进行重大更改,但是根据您的反馈可能会进行较小的更改。二进制兼容性可能不会保留:最有可能更改的部分是,当前GPU实例化表的二进制布局已反映在公共C ++ API中。
如果您正在考虑将实例渲染与Qt 6.2一起使用,那么现在是开始的最佳时机。您的代码最多只需要很小的修改,您的反馈就可以帮助我们改进Qt 6.2,从而更好地支持您的用例。

具有实例化功能的QtQuick3D Benchmark应用程序

Qt6.1教程:Qt Quick3D渲染实例

标签:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年1月1日
下一篇 2021年1月1日

相关推荐

发表回复

登录后才能评论