如何减少渲染树的性能影响?


24

我正在制作一款低聚风格的游戏。我的地形上有一些水,我想要很多树木。目前,我已经放置了10,000棵树。每棵树包含不超过200个三角形,因此它们不太费力。

主要问题是有湖泊,而且湖泊很大。您实际上看不到湖另一侧的任何树木,这看起来真的很糟糕,尤其是当您走到那里而突然出现树木时。

要解决此问题,我必须增加树的距离,以便您可以在湖的另一侧看到相当多的树,但这会降低性能至40-50fps,并且游戏中几乎没有其他内容。我正在使用GTX 1080,如果可以的话。

我怎样做才能使游戏在更多树木下运行得更快?


IIRC,Silent Hill使用雾气将截止点隐藏在较远的剪切平面上,这使他们可以开始动态加载刚好在雾气截止点之外的东西。您可能会受益于游戏气氛的变化。
科迪

树木吸引您向窗外看,从而降低了性能。
mbomb007 '17

您是否尝试过运行探查器?如果是这样,瓶颈在哪里?
MikaelHögström'17

您是否正在执行任何一种平截头截头剔除?
Krythic

什么是平截锥体剔除?
mr-matt

Answers:


43

您可以做几件事来提高绘图性能。

  1. 你说他们很远。您可以使用LOD减少这些树的顶点数,从而减少遍历所有绘制顶点所需的时间。即使这很可能不是手头的问题(GTX1080仅包含1万棵树,每棵树有200个tris,gpu的数字很小),我仍然将其包括在内。Billboarding是实现最低LOD级别的有效工具,因为它本质上是始终面向摄像机并带有树的渲染图像的平面。它失去了深度感,这就是为什么它适合最低级别的原因,因为玩家很可能不会注意到差异。

  2. 您启用了批处理功能吗?如果网格的顶点数很少,通常会自动完成动态批处理。也可以通过选中父游戏对象上统一编辑器中的复选框使树变为静态来尝试进行静态批处理。这不适用于动画对象。您需要这些对象共享材料才能完成这项工作。

  3. 自定义批处理允许您通过自己生成块来控制渲染,而不是由统一处理它,并且还可以为较大的网格进行批处理。这可以通过Mesh.CombineMeshes轻松完成。这也不适用于动画对象。您需要这些对象共享材料才能完成这项工作。您可能希望将您的世界划分为某种块,并根据这些块创建批次。这些块的生成方式实际上取决于相机在世界上的移动方式。

  4. 在着色器上启用实例化。实例化使引擎可以通过一个绘制调用来绘制多个对象(具有相同的网格)。您需要使对象具有共享的网格和共享的着色器才能起作用。材质可以变化,但是着色器必须支持所有不同的变化属性。

    为了使引擎更好地创建实例渲染批处理,您可能希望将相同的网格划分到场景中。如果一个网格物体始终具有相同的材质,则还可以使用材质渲染队列来获得良好的效果。在开发当前正在开发的移动游戏期间,我使用它来将测试场景中的抽奖次数减少了一半以上。另外,自Unity 5.6起,请确保Enable Instancing选中材料中的复选框。

  5. 一般情况下,请减少通话和SetPass通话。这些是您的GPU绘制内容的原始调用,而且开销很大。减少抽奖活动(批处理和实例化正在做的事情)将提高您的CPU可以提供的整体性能,因为它需要减少等待时间。SetPass调用是对当前着色器的更改,因此,如果您使用许多不同的材质,则将有多个SetPass调用,这也会导致CPU等待一点时间。

  6. 如果场景很大,并且您的CPU时间花费在浏览场景中的所有对象上,请尝试减少场景中的对象。对一些树进行分组,而不是单独放置它们并将它们作为单个对象。还要确保您没有移动树或父对象,因为这会使Unity放弃缓存的变换并重新计算整个场景树。

  7. 如果场景很大,而您的CPU时间仍然主要花在Unity上,而遍历场景树以列出所有对象,那么您可以做的一件事就是不要让Unity处理渲染。如果您有更好的跟踪可绘制对象的方法,则可以使用CommandBuffer.DrawMeshInstancedGraphics.DrawMeshInstanced手动绘制它们。我不会对此进行详细介绍,因为它要高级得多,并且涉及淘汰自己和其他人。

如果静态或动态批处理无法正常工作(可以通过检查框架调试器看到),则需要确保确实使用了共享材料,并且不要通过调用意外复制材料meshRenderer.material。呼叫.material将复制您的物料并中断批次。使用.sharedMaterial代替。

从Unity 5.6开始,您可以使用Frame Debugger来确定为什么某些drawcall不与先前的drawcall批处理的原因。在尝试减少游戏的吸引声时,这将非常有用。

与静态/动态/自定义批处理相比,实例化具有以下优点:

  • 使用较少的内存,因为网格不必在内存中重复
  • 可以使用多种材质,仅需要共享着色器
  • 物体可以动画

作为缺点,它是Unity中的新功能,可能有点不稳定。同样,较旧的或移动设备的GPU不一定支持实例化。


1.是的,我尝试了LOD,但令我惊讶的是,它实际上使情况变得更糟。我有3种树木的变体,每个变体的顶点数都稍低,而一个平面上有树的渲染图像。
Mr-matt

2.我所有的树都标记为静态。据我所知,可以进行批处理吗?那是对的吗?当您说共享材料时,您是说树木具有相同的材料吗?
mr-matt

3.这实际上会带来什么样的性能改善?值得尝试吗?
mr-matt

1
2/3:根据我的经验,Unity在动态批处理方面做得并不好,而静态批处理会增加构建大小,因此我自己实施了批处理,并进行了网格合并加载时间的工作。使用这种技术,我成功进行了2500次抽奖,然后压缩为大约300次抽奖,这对于我们的手机游戏至关重要,因为手机游戏的抽奖非常重要。它几乎不需要计算多余的顶点(屏幕外),但这是值得的。
拉瑟

2
tfw,当您阅读有关树木性能不佳的问题,而没有一个关于广告牌的单词迷失时
Num Lock

13

好的,所以问题很简单,我没有使用预先计算的实时GI。我在不久前检查了一下,但没有立即生效,所以我把它忘了,而且照明处理时间也很长。但是,它刚完成处理,我的意思是,我的fps增长了3倍。因此,目前为止,我将保留它,并在将来确保始终使用计算机前实时GI!

如果还有什么我可以做的以进一步提高性能,请告诉我,我将不胜感激!


2
如果场景很大,也可以使用遮挡剔除-考虑将其分成多个块,例如,对许多地形进行加载和卸载。
坦率的月亮_Max_

考虑到您似乎已经解决了问题,您可能应该接受此答案。
Gnemlock
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.