优化 3D 性能

剔除

Godot会自动执行视图视锥剔除, 以防止渲染视窗外的物体. 这对于发生在小范围内的游戏来说效果很好, 然而在较大的关卡中, 事情很快就会变得很麻烦.

遮挡剔除

比如走在一个小镇上, 你可能只能看到你所在的街道上的几栋建筑, 以及天空和几只飞过头顶的鸟. 然而就一个天真的渲染器而言, 你仍然可以看到整个小镇. 它不会只渲染你前面的建筑, 它会渲染那后面的街道, 与那条街上的人, 那后面的建筑. 你很快就会遇到这样的情况: 你试图渲染比可见的东西多10倍或100倍的东西.

事情并没有看上去那么糟糕,因为 Z 缓冲通常只允许 GPU 完全遮挡在前面的物体。这被称为深度预处理(depth prepass),在使用 GLES3 渲染器时,Godot 默认启用。然而,不需要的对象仍然在降低性能。

一种可能的减少渲染量的方法,就是利用遮挡信息。

例如, 在我们的城市街道场景中, 你可能会事先计算出, 从街道 A 只能看到另外两条街道, BC. DZ 的街道是隐藏的. 为了利用遮挡的优势, 你所要做的就是计算出什么时候你的观察者在街道 A 中(也许使用Godot区域), 然后你就可以隐藏其他街道.

这个例子就是手动版本的所谓潜在可见集。用这种技术来加速渲染非常有效。你还可以用它来把物理和 AI 限制在局部区域,从而和渲染一并加速。

Portal 渲染

然而,有一种更简单的方法可以实现遮挡。 Godot 具有先进的 Portal 渲染系统,可以从相机和灯光执行遮挡剔除。参阅 房间和入口

虽然这个系统并不是全自动的,需要一些手动设置,但是却能带来显著的性能提升。

备注

在某些情况下,你可以通过调整你的关卡设计来增加更多的遮挡机会。例如,你可以增加更多的墙来防止玩家看得太远,否则就会因为失去了遮挡机会而降低性能。

其他遮挡技术

除了入口系统和手动操作之外,还有诸如基于光栅的遮挡剔除等剔除技术。其中有一些可以通过插件实现,有一些会在将来的 Godot 核心中实现。

透明物体

Godot通过 MaterialShader 对对象进行排序以提高性能. 然而, 这对透明物体来说是不可能的. 透明物体从后往前渲染, 以便与后面的物体混合. 因此, 尽量少使用透明对象 . 如果一个物体有一小部分是透明的, 尽量让这部分成为一个独立的表面, 有自己的材质.

更多信息请参阅 GPU 优化 文档。

细节程度(LOD)

在某些情况下, 特别是在远处, 用简单的版本**代替复杂的几何图形可能是个好主意. 最终用户可能看不出什么区别. 考虑看看远处的大量树木. 有几种策略可以替换不同距离的模型. 您可以使用较低的多边形模型, 或者使用透明度来模拟更复杂的几何体.

Billboard 和 imposter

使用透明度来处理LOD的最简单版本是广告牌. 例如, 你可以用一个单一的透明四边形来表示一棵树的距离. 这可以是非常便宜的渲染, 当然, 除非前面有很多树. 在这种情况下, 透明度可能会开始吞噬填充率(关于填充率的更多信息, 请参见 GPU 优化).

另一种方法是不只渲染一棵树, 而是将一些树作为一组来渲染. 如果你能看到一个区域, 但在游戏中不能实际接近它, 这可能是特别有效的.

你可以通过预先渲染对象的不同角度的视图来制作冒牌货. 或者你甚至可以更进一步, 周期性地将一个物体的视图重新渲染到一个纹理上, 作为一个冒牌货使用. 在远处, 你需要将观察者移动相当长的距离, 视角才会发生显著变化. 这可能是复杂的工作, 但可能是值得的, 这取决于你正在制作的项目类型.

使用实例化(MultiMesh)

如果必须在同一地点或附近绘制多个相同的对象, 请尝试使用 MultiMesh 来代替.MultiMesh允许以很小的性能代价来绘制成千上万的对象, 这使得它非常适合用于绘制羊群, 草地, 粒子以及其他任何有成千上万相同对象的地方.

另请参阅 Using MultiMesh 文档.

烘焙照明

对物体进行照明是最昂贵的渲染操作之一. 实时光照, 阴影(尤其是很多灯光)和 GI 都特别昂贵. 对于低功率的移动设备来说, 它们可能根本无法处理.

考虑使用烘焙照明 , 尤其是移动端, 这看起来很棒, 但有一个缺点, 那就是它不是动态的, 有时, 这需要做出的权衡.

一般来说, 如果几个灯光需要影响一个场景, 最好使用 烘焙光照贴图 . 烘焙也可以通过增加间接光的反弹来提高场景的质量.

动画和皮肤

在某些平台上, 动画和顶点动画(如换肤和变形)可能非常昂贵. 你可能需要大大降低动画模型的多边形数量, 或者任何时候限制屏幕上的模型数量.

庞大的世界

如果您要制作大型游戏, 则与小型游戏可能会有所不同.

大型的世界可能需要用碎片建立, 可以在你在世界中移动时按需加载, 这可以防止内存使用失控, 也可以将所需的处理限制在局部区域.

在大型世界中, 由于浮点错误, 也可能会出现渲染和物理故障, 你可能会使用一些技术, 比如将世界围绕着玩家的方向(而不是相反), 或者定期移动原点以保持以 Vector3(0, 0, 0) 为中心.