翻译 | 入门级硬件的实时3D优化

作者:Richard Lin | Jul 11, 2019 10:19:22 AM

本文翻译:Optimizing Real-Time 3D for Entry Level Hardware

原文作者:Kimmo Leppälä
校审:Kenny Zhang, Richard Lin

随着越来越多的汽车配备数字仪表盘,以满足目标用户体验为前提,降低所需电子器件的硬件成本变得越来越重要。在量产阶段,10、50或是100美金硬件成本之间的差异关乎成败——因此研究如何最高效地在SoC上运行软件是一件非常有价值的事儿。如今的用户都会期望高质量的图形和流畅的动画,在诸如数字仪表盘这样的系统中,确保持续高性能表现也跟安全性息息相关。在这篇博文中,我们将演示如何利用Qt Quick和Qt 3D Studio在Renesas R-Car D3入门级的SoC平台上实现顺滑流畅的、稳定60 FPS的画面渲染效果。

项目要求

我们选择了Renesas R-Car D3入门级SoC作为本项目的硬件。其他制造商也提供类似性能的入门级SoC,我们过去也完成了NXP入门级SoC的项目。这次我们想尝试一下Renesas R-Car D3,它配备了Imagination PowerVR GE 8300入门级GPU 和一个ARM CortexA53 CPU内核。

我们的外观设计师设计了一个相当典型的现代数字仪表盘,作为本项工作的基础。该UI包含了两个不同样式的表盘,以及中间一个实时3D的ADAS(高级驾驶辅助系统)视图。目标就是在选定的低端硬件(Renesas R-Car D3入门级SoC)上在1280x480分辨率下实现稳定的60 FPS的刷新。该设计概念包含了实时3D的元素(ADAS视图),以及通过OpenGL着色器进行2D渲染的元素,其视觉设计实现了平滑的3D体验(实际上不能算作实时3D渲染)。

概念设计的页面结构

初步设置和发现

在使用Qt 3D Studio完成初始原型之后,我们将其部署到R-Car D3开发板上,运行Qt 5.12来分析性能。即使画面不是很复杂,未经优化的设计也只能渲染约10帧/秒。在我们优化了项目素材之后,情况有所改善,达到了约20帧/秒,但依旧离60 FPS的目标相去甚远。显然,我们必须做进一步的分析,研究应用程序的总体架构。

分析从使用PVRTrace工具开始,它能帮助我们更深入了解D3 SoC以及痛点所在。很快,我们就了解到在OpenGL中使用大的FBO(帧缓冲对象)或渲染目标缓冲区会极大降低硬件的表现。我们在仅使用一个全屏FBO的情况下,就测出了10 ms的开销,如果要达到60fps,每帧间隔最长也只有16.6ms,这里就占去了10ms。

测试过的架构

为了获得D3硬件最大能力作为我们项目的性能参考,我们测试了各种不同的应用程序架构,同时我们也测量了Qt Quick + 纯OpenGL 实现的ADAS视图。我们用Qt Quick实现了所有可能的东西,并使用纯OpenGL命令绘制了ADAS。通过这样的操作,我们达到了60 FPS,这就证实了我们的目标是可以实现的。

然后,我们转到Qt Quick+Qt 3D Studio。表盘部分采用Qt Quick实现,中间的ADAS视图作为Qt 3D Studio的一个部件。这种方法使用了一个FBO。3D内容使用了一个独立的渲染层(单层穿透),因此不需要第二个FBO。通过纹理压缩的方法可以进一步节省内存空间。这种结构设置同样能够呈现出稳定的60 FPS渲染。

最优架构

在尝试了不同的方法之后,采用Qt Quick实现2D元素,ADAS视图使用Qt 3D Studio运行时的方案显然能够让我们获得最佳性能。通过在运行时实现的一个后台绘制补丁,我们能够每秒多挤出几个帧,并降低CPU消耗。

Qt Quick实现的仪表盘和基于Qt 3D Studio的3D ADAS视图

通常情况下,当您想将3D Studio创建的3D场景与Qt Quick创建的2D内容相结合时,需要将两者窗口合成在一起。在这种情况下,Qt Quick负责组合,但是由于Qt Quick是一个2D渲染器,因此有必要将场景中的任何3D内容展平。默认方法是先把3D内容渲染到一个离屏(off-screen)纹理,但正如我们前面提到的,目标硬件在进行离屏表面渲染时会带来巨大的性能损失。因此,必须避免这种默认的做法。幸运的是,Qt Quick是相当灵活的,并且允许一些变通的方法。

我们的解决方法是在帧渲染一开始的时候就将Qt 3D Studio场景直接渲染到window,然后在window中再渲染Qt Quick UI 。在这种情况下,Qt Quick UI中呈现3D场景的元素就是一个透明的孔,这样您就可以看到已经呈现到屏幕上的低层3D内容。执行此操作时,切记在渲染时不要清除窗口,可以通过在QML中将窗口颜色设置为“透明”的方法来实现。

当然这种方法确实有一些设计上的局限。但在当前例子中没有这个限制,可以在不做任何更改的情况下实现现在的概念设计。您可以选择在渲染Qt Quick UI之前或之后渲染3D内容,这意味着3D内容总是在上方或下方。由于我们选择在Qt Quick UI之前绘制,也就是位于Qt Quick UI绘制的控件之下,因此我们可以在3D用户界面的上层绘制控件(尽管在我们的例子中不是这样),但是我们无法混合3D视图下的任何内容。

如果我们需要将3D视图与3D视图下的一些2D内容混合,我们可以在2D内容渲染之后再渲染3D内容。但是,不可以在3D内容的下方和上方同时渲染内容。这只有通过使用离屏材质来实现,因此在为这些目标设计时要记住这一点。值得考虑的是,混合渲染具有较高的资源利用率,特别是在资源有限的低端硬件上,因此,尽管我们对这个特定项目没有这样的限制,但在设计阶段的早期,混合是否有必要也是值得考虑的事情。

3D部件的最终设计优化

像往常研究实时3D应用程序一样,我们也会进一步如何优化图形素材。很多时候,最初从设计者那里获得的3D模型和其他素材没有针对目标应用程序和硬件环境进行优化。例如,模型的细节展现可能比人眼从屏幕上所能感知到的要高。当GPU和CPU性能需要精打细算时,图形素材的优化也就变得至关重要了。使用正确的技巧,可以显著降低系统负载,而不会对用户造成任何明显的体验降低。

道路网格(mesh)的优化

我们创建了一个道路的顶点网格,使用顶点颜色混合道路纹理的方式。这样,道路可以混合到黑色背景而不需要渲染透明度,或者使用额外的纹理创建遮盖式渐变。

顶点颜色混合道路纹理

我们通过移动模型的纹理坐标,实现道路的移动。

运动的道路

使用了低资源消耗的“抗锯齿”特效:道路材质边缘使用背景色(黑色)绘制。

汽车网格(mesh)优化

汽车模型优化的第一步是创建低多边形的版本,原始版是具有多个纹理和材质的高多边形模型。在Zbrush中用不同数量的多边形生成了一些低多边形模型,并在应用中对这些低多边形模型进行了测试,以确定最低能接受的多边形数量。最后一个低多边形汽车模型是用Autodesk Maya的Quad Draw工具创建的。

从高多边形到低多边形的汽车模型

最终的汽车网格有多个材质,包含了详细的纹理,这些材质被合并到单个纹理贴图中,删除了一半的汽车和三个轮子的皮肤。为汽车左侧和其中一个车轮创建了UV纹理布局,基于高多边形模型处理纹理。在此之后,几何图形被复制并镜像,车轮也被复制,以创建汽车的右侧。这样,我们的模型在保持相同纹理大小的同时,在几何体上增加了50%的像素。

创建纹理映射

屏幕上汽车的最大尺寸是200*150像素,所以我们将纹理的大小缩小到256*256像素。

减少纹理尺寸。汽车表面像素A的大小和实际渲染B中的像素大小相似,最后的尺寸C 仍然保留了足够的细节。

2D组件优化

我们基于可重用纹理来构建2D UI,以减少内存使用和启动时间。在本例中,我们将大约15000像素加载到内存中,最终基于这些资源将大约20万像素呈现到屏幕上。由于重用,我们加载的素材只有最终输出大小的7.5%。

重用2D元素

优化过的概念验证应用程序

您可以从https://git.qt.io/public-demos/qt3dstudio/下载所有的源码和素材

以下视频显示了在Renesas R-Car D3上运行的应用程序。

 

小结

要获得理想的视觉效果,使用实时3D渲染并恒定运行在60FPS是一个挑战,但Qt提供了一个伟大的框架和工具,即使在低端硬件也可以实现惊人的性能。为了实现最大的性能,必须考虑并确定哪些组件必须是实时3D的,哪些组件可以用2.5D(视觉上看起来是3D,但不在3D空间上渲染)完成。这有助于实现计算上的最优架构,并且它是获得最大性能的先决条件。所有的图形素材都应该经过仔细的优化,特别是3D模型和纹理,考虑到用人眼可以感受到什么,因为它们很容易就变得过于复杂。在使用OpenGL着色器时,必须确保这些着色器适合目标硬件并进行优化。随着体系结构和素材成形之后,剩下的工作是使用完善的Qt编程技术,并定期使用分析工具来识别和分析可能的性能问题可能来自何处。

如果您有正在计划或开发的项目,而且需求是在低端硬件上运行高性能图形,我们可以提供相关的帮助。联系我们获取专业服务和更多信息。