一.使用工具

1.1使用 HLOD

https://www.youtube.com/watch?v=WhcxGbKWdbI

由于HLOD是减少DrawCall的方案,所以其实他会对渲染性能的提高能够起到一定的帮助作用。因为它是将场景中互相独立的静态Mesh通过顶点和材质合并的方式聚合在一起,本来由于材质和顶点Buffer的不同而没有办法形成一个统一的Drawcall,现在可以迎刃而解。很显然那些被合并的顶点和索引buffer再也不能被复用了,而且pack到一起的纹理也是一样,它们都变成了场景中独一无二的资源,所以理论上讲HLOD是一种用空间来换取时间的方法。 所以HLOD是会增加内存使用的,如果是巨量的HLOD,不仅适得其反,会影响渲染性能的使用,cook的时候一个HLOD的文件大小是及其夸张的。压缩这些HLOD文件可能花费了数个小时的时间,它大大降低了研发迭代的效率。

  1. 将世界场景设置 中的 Enable Hierarchical LODSystem打开。

  2. 我们首先在windows 界面打开HLOD管理器

  3. 我们点击 Generate Cluster, 他会把所有level里面的空间位置临近的Mesh分组为一个Cluster。如果觉得分的不好的话是可以自己手动修改的。

然后我们点击加号增加HLOD的个数,例如我们增加两个一共三个LOD

  1. 确定好之后,点击Generate Proxy Meshs 将会分组的HLOD 数据。等待一段时间。

1.1.1HLOD调试

我们选择HLOD 的视图模式

我们由近到远就可以看到HLOD的变化。

1.1.2参数设置

距离每个cluster越近,使用的LOD的越数值越小,Mesh的数据越精确。每个LOD上面都有特定的参数。

参考: https://docs.unrealengine.com/zh-CN/BuildingWorlds/HLOD/Reference/index.html

1.2使用LOD和Merge Actor

1.2.1使用LOD

所以其实我们并不需要所有的物理都变为HLOD的,当然这个部分没有踩过坑是没有办法预知的,因此我们对于某些Mesh(待定)使用LOD应该就ok。我们的每个Mesh ,都需要设置LODs。

这里我们有了标准是可以使用脚本刷的。

相关调试

r.StaticMeshLODDistanceScale
r.forceLOD

由于我们的LOD是可以使用简化材质的。

1.2.2使用Merge Actor

由于HLOD的内存问题,所以另一种方案是合并actor,因为他是生成一个新的Mesh和material,所以他并不会产生额外开销。

1.3使用 Virtual Texture

首先开启 virtual texture

然后,我们将所使用的贴图进行转换

也可以在纹理编辑器里进行转换

若未使用上述转换菜单选项,将立即导致引用转换纹理的所有现有材质失效。应打开引用违规纹理的所有材质,并将纹理取样节点设为使用正确 虚拟(Virtual) 采样器类型。例如,虚拟纹理应使用 虚拟颜色(Virtual Color) 而非 颜色(Color) 采样器类别

1.3.1调试

 r.VT.Borders 1

1.4使用Level Streaming

https://www.youtube.com/watch?v=GkDg9GPpzXE&ab_channel=UnrealEngine

1.5使用纹理流送

此处用来保证MipMap的正确性。我们构建纹理流数据:

1.5.1构建检查

纹理流送构建期间计算的数据准确性可以通过查看纹理流送准确性视图模式来检查:

  1. Primitive距离准确度:这会显示流送器计算的视图网格体距离与实际GPU距离相比较的准确性。流送器计算从视点到纹理实例轴对齐边界框(AABB)的 距离。通过将使用该纹理的组件LOD部分AABB加总起来,在构建流程中计算该边界框。这里显示的值可以通过更改网格体组件的 流送距离乘数(Streaming Distance Multiplier) 调整。
  2. 网格体UV密度准确性:这种视图模式显示流送器使用的网格体场景纹理坐标(texcoord)大小与实际GPU值比较的准确性。这种大小通过场景空间单位与纹理坐标变体之间建立关联。 流送器用它来评估纹理坐标对纹理采样的影响。这种视图模式属于相当的视点不可知类型,当网格体的值不理想时,它们通常与场景无关,而是与网格体有关。这意味着,如果任何网格体包含错误数据,则使用该网格体的任何组件 很可能变得不正确。在静态网格体或骨架网格体编辑器中,通过调整StreamingDistanceMultiplier直到网格体位于 良好(Good) 范围内,可以更改该值。
  3. 材质纹理缩放准确性:材质中使用的大多数纹理都使用其中一个网格体UV密度的缩放值来采样。纹理流送构建尝试计算使用哪个纹理坐标以及对每个采样纹理应用哪个缩放。 这可能会因为许多原因而失败,如果失败,流送器会假设纹理是使用纹理坐标0和缩放1进行采样的。
  4. 所需纹理分辨率:在该视图模式下,可以显示当前流送纹理分辨率和所需纹理分辨率之间的关系。该视图模式与材质纹理缩放有一些相似之处,但它不显示纹理流送数据的准确性,而是显示当前以绝对方式 加载的纹理分辨率的有用性。任何时候针对纹理加载的分辨率都来自于逻辑和指标的组合。例如,纹理可能会缺少分辨率,因为没有足够的可用空间加载纹理,或者 它没有过多的分辨率,因为其更高的mip缓存在纹理池中等待将来使用。此外,流送器通常由需要最高分辨率的组件驱动, 因此调查纹理对一个组件的行为仅在这个组件是驱动其分辨率的组件时才有意义。

1.6 使用Static Mesh Instancing

对于材质一样,mesh一致,仅有旋转,位置,大小不一致的的大量物体,例如书柜里的书,我们是可以使用Static Mesh Instancing 来进行

r.MeshDrawCommands.DynamicInstancing

虚幻4.22引入了自动实例化的功能,因此无需再自行管理。手动做比自动做性能好?不是很清楚。合并太多的对象会把视锥剔除和遮挡剔除的所有优势抵消。如果静态网格体使用LOD,每个LOD都将在GPU上单独执行一次绘制调用。

二. 把控风险

2.1 内存相关

  1. 材质中使用默认的纹理,(一个纯白的一像素纹理等等)因为一个材质加载进来会将所有的硬引用的贴图数据(材质中指定的那个贴图)进行加载,但是我们其实只使用的是他的instance里面的数据,或者是我们后面给他重新赋值的贴图。

  2. 贴图大小不是二的整数,这个很好理解512*512的贴图的内存是512 * 512,但是513 *513的数据的内存是1024 * 1024。并且将不会有mipmap。

  3. 贴图的压缩格式,我们看到一个贴图很模糊不一定是他的分辨率的问题,可能跟他的压缩模式有关系,所以尝试调整。

  1. 材质接口的使用,如果有端口是你不使用的,那么请使用一些方案让他变成暗的,因为每个凉的节点都会增加不必要的变体消耗。

  2. 硬边缘和UV解封管理规则:UE4会沿着UV接缝和硬边缘分割网格体的边缘产生大量顶点数量,大部分边缘应尽可能保持平滑,UV接缝数量尽可能少

6. 正确设置纹理组, 打包的时候才能严格控制。

2.2性能时间

  1. 关闭远距离LOD的阴影投射,可以节省几毫米。远距离的阴影就算了把!!!!!!!!

  2. 移动物体的使用, 固定光源的使用,