章程

场景优化进阶(一) 大量物体复用以及纹理合并在数据上产生的优化


这个教程里,我们假设在大场景的一个区域,把相同相似类型的物体复用到极致,纹理合并到极致。然后量化的来看效率提升了多少。
0

这是视觉效果上和上次同样一个场景. 但是在物件构成上有很大的不同.

1.物件的复用. 这里简单局部的把这个小场景里的复用物件罗列一下:
1

前面是该物品的种类,后面是该物品在场景里通过旋转缩放移动,拷贝的次数.在这样的机制下,美术在制作任何一个新关卡时,可能很有必要进行一个理性的规划,做一个类似的列表. 比如相似的树,作几种,形状差不多的灌木,作几种. 结合关卡本身,种类不用太多也不能太少.

2.纹理的合并.

2

可以看到,纹理数量从原来的22张, 缩减到了现在的8张. 关于合并纹理的原则,由于引擎读取纹理的机制,一般遵循以下原则:

原则一:

统一区域里一起出现的物体,强烈建议合并到一张纹理上.
比如说同屏上经常出现的木头架子,木头柱子这些,如果这些不同物件分布的区域比较集中,那应该秉着贴图越少越好的原则,把它们都分配到同一张纹理上.
反之,如果有一个火把,在整张大地图,甚至不同地图间,都是高度复用的,那么这个火把的纹理就不能和具有这个区域特色的物件分配在一起了. 因为玩家在地图的其他部分看到这个火把时,引擎把带这个火把的大贴图读下来的时候,这张纹理还连带很多当时没有出现的物件的内容,那就不划算了.
总之,合并纹理的时候, 把在同一区域内常常一起出现或者交错出现的物件,尽量分到一张贴图上, 对节约drawcall是很大的帮助。

原则二:

把相同材质,或者相同设定的纹理尽量分配在同一张贴图上。 比如这个区域里所有的石头材质集中在一张图上。
还有就是如果有用到透明材质的,可以尝试把透明材质的物体都分到一个贴图上。 打个比方:
3

在旧场景里,因为锁链是连在建筑上的,所以自然而然美术就把它分在了建筑的贴图上。 但其实由于锁链本身是带透明通道的,而且锁链周围又是有很多透明贴图的灌木,所以我就把锁链的纹理单独拿出来然后合并到灌木的贴图上了。这样,灌木的半透明贴图加载的时候,只需要一个有透明的材质,就把这个区域里所有透明物体涵盖了。 并且同时,那幢建筑的贴图和材质全部不用带透明了。

关于纹理合并时美术上的技巧,也希望能注意到以下两点:
第一: 如果增加的面数不是太夸张,尽量把需要透明的物体的边缘用polygon切出来,而不采用透明贴图的做法。 如下图:
poly_vs_opacity

从图上可以看出,在瓦片和栏杆上增加了面,把本来要透明掉的部分以polygon的形式切了出来。换来的是整幢楼都不需要使用透明四通道贴图和透明材质,与此相比,增加了几十个多边形的代价是完全划算的。

第二: 由于是合并的纹理, 所以纹理上很多元素是被其他元素包围的,过去那种把 UV 延展到纹理以外,用来获得纹理的重复的情况就不太行得通了。 但是这种把UV摊到纹理范围外的做法在渲染底层上也是要有折算,增加运算量的。 所以除了大面积平面的地面,同时纹理元素又很小,把地面切开需要增加上千个面的特殊情况, 一般情况下,还是建议把要纹理重复部分的多边形加面切开,把所有纹理移到贴图的范围内摊开。具体的效果可以看下图:
uv

模型A因为面没有被切开,所以UV延展到纹理范围外,以此获得纹理的重复。 在模型B里,因为面被切开了,所以就可以把超出贴图范围的那块移到纹理范围内来了。 每张纹理的四个顶点都是0到1范围内的一个坐标系,如果超出这个坐标系,就要耗费资源进行折算。所以,如果增加的面不是太多,就尽量把UV摊在纹理范围内, 可以省点消耗,而且合并纹理的时候也方便很多。

最后,讲了这么多优化,最终还是要从数据上来比较,才能真正衡量合并以及优化的意义.
先看一下场景A,没有作优化的。
4

在来看一下做过复用和合并的场景B:
5

复用和合并大大减少了纹理,材质,以及物件的数量,但是场景B,即没有多边形减面,又没有缩减纹理大小,所以在视觉效果上,和未优化的场景A是一模一样的。

来看一下两个引擎在负载上的数据比较:
6

逐一对比可以发现:

  • RAM(内存占用) 从 264M 降到 221M
  • DrawCall 从 84个 降到 72个 (引擎渲染底层对复用物体的批处理优化还在作,完成后drawcall会有更大幅度的下降)
  • Vertex 流量 从 12.6兆80个 降到 7.1兆51个
  • Texture流量 从22兆49个 降到 16.9兆21个

最后还有一个很有意义的参数是客户端包的大小, 由于引擎增加了对打组得模型储存上的优化,整个场景的模型文件大小从 1262k 降到了 959k,这个优化上的进步对网页游戏是相当有意义的。(以上具体每个参数对效率瓶颈的影响会在另外一个教程里作说明。)

还有就是整个美术的制作流程中有一个比较容易出错的环节要提醒一下,就是复用物体之间,只有第二个UV 和 顶点色 这两个和灯光贴图有关的属性是允许不同的,第二个UV的分的方法和切的块数应该一样,只是整体位置可以不同。 其他在工作流程中,如果不小心对复用物件中的一个或者几个做出任何顶点位置上的,光滑组(软硬边),或者第一个UV上的细微调整,或者第二个UV的打散或焊接。那么,该物体在引擎里就不再会被识别为可以打组的物体里。 如下图:

7

理论上, 物件 LM04_PotA_04_geom 是应该打在下面的shared1的包里面的,但是肯定在制作过程中,该物体的顶点,光滑组或者第一,第二个uv发生了一点变动,所以无法被识别成为复用物体了,所以美术在三维软件里修改模型的时候要特别注意。