猴哥出了新的客户端项目优化课程,一直等着,终于出来了。网上有关项目优化的知识很多,但是很零散,不系统!猴哥做了总结,真是及时雨。这里做一下学习的总结,猴哥的课程见这里。这里给自己立个flag,课程学完,总结写完。顺带推广哈我自己的个人博客哈。
Stats统计面板可以统计摄像机视野内所有元素顶点和面片的数量和、批处理次数、CPU耗时等。
Tris是Triangles(三角形)的缩写。
Vert是Vertex(顶点)的缩写。
新建新场景,场景中只有默认的一个灯光和一个摄像机。
然后看Stats面板,竟然发现Trix(三角面)高达1.7k,Vertex(顶点数)高达5.0k,这是为何?(k是千的意思)
原因是摄像机的背景是天空盒,天空盒其实也是个模型(只是Unity中看不到罢了)。
修改摄像机的Clear Flags为Solid Color(纯色)。
再看Stats面板,发现Trix变为2,Vertex变为4了。这两个面片其实是屏幕。
Stats统计面板只统计摄像机视野内所有元素顶点和面片的数量,视野外(摄像机视锥体外)的元素不统计。
新建一个球体,球在摄像机视野内。
移动球到视野外。
(ps:这一波疫情,让我感觉自己的抗风险能力有点低啊,得加把劲哦。)
(接着昨天开始)
什么意思呢?看图就明白了。
结论就是:Unity3D和3DMax统计模型的面片数是相同的,而顶点数不同。
Unity3D统计顶点数的方式是:如果一个顶点同时在N个面上,则统计为N。(Unity3D中的Cube物体有24个顶点,原因就是1个顶点在3个面上)
而3DMax统计顶点数的方式一个顶点就是一个顶点,无论它同时在几个面上。(所以3DMax中创建一个最简单的Cube物体其顶点数是8)
ps:3DMax打开上图中左上角的统计面板的方式如下图。
Stats统计面板中顶点数和三角面数的单位有k和M。
k表示千(不是1024哈),如Tris: 1.5k表1500个三角面。
M表示兆,百万,如:2M表示两百万个三角面。
①摄像机看到的模型的数量
这个就不多说了哈,一看就明白。
②光照和阴影
灯光如果开启了阴影(灯光的Shadow Type选项),然后照射到模型上,若模型开启了投射阴影(Mesh Renderer的Cast Shaows选项)则顶点数和面数将会增加。其实就是阴影会增加面数和顶点数。
首先做点准备工作,新建一个场景,修改摄像机的Clear Flags为Solid Color(纯色),然后新建一个Cube物体。
这时我们再依次调节灯光的Shadow Type和Cube的Cast Shadow来对比Stats面板统计的顶点数和面片数。见图。
i.灯光不产生阴影,Cube物体不投射阴影
ii.灯光产生阴影,Cube物体仍不投射阴影
灯光的Shadow Type选择Hard Shadow或者Soft Shadow均可。
ps:Hard Shadows 硬阴影,阴影的边缘没有过渡
Soft Shadows 软阴影,阴影的边缘过渡柔和,
效果更好,但消耗更大,尤其是CPU(计算阴影由CPU处理)
iii.灯光产生阴影,Cube物体也投射阴影
你可能会问那4种情况呢,灯光不产生阴影,Cube投射阴影?结果和第一种情况是一样的,这里就不截图了。
得出的结论如下:
开启产生阴影的灯光会影响场景中的三角面数和顶点数!
开启投射阴影的模型更会影响场景中的三角面数和顶点数,而且影响很大,说明阴影很耗!
这个想必大家都懂,就不多说了。(不说你打个标题干啥,看我不打死你,逃)
FPS就是Frames Per Second每秒传输帧数,又叫帧率,就是游戏一秒钟渲染多少帧(这个帧其实就是张的意思,电影是一张张图片连续播放形成的,我们的游戏也是这样,持续不断的渲染画面,然后持续不断地层现到屏幕,我们才能看到联系不卡顿地动画)。
那么多少FPS是合适的呢?人眼能适应的舒适FPS是24,就是每秒钟24帧,大家平时下载的小视频多是这个值。
早期的游戏一般是30FPS就行了,现在大量的3D游戏需要保持在60FPS才可以玩,而VR的项目,则需要90帧的高刷新率才行(否则在VR眼镜内观看画面很容易出现眩晕的感觉)。
首先看看什么是SetPass,就是设置Pass,Pass是Shader中的一个代码块,一个Pass就代表一次完整的渲染。简单但不准确的说,一个SetPass就是更换一次材质球。
call是调用的意思。
总结起来,简单但不准确的说,SetPass calls代表的就是设置材质球的次数。(其实我也不知道该怎么表述才算准确,哈哈,逃~~~)
所以这个值与场景中材质球的种类有关。
那么影响这个值的因素有哪些呢?
这里先给出结论:①材质球的种类 ②灯光是否开启阴影 ③物体是否投射阴影
所以阴影既会影响三角面数、顶点数,也会影响SetPass calls(接下来我们还会看到阴影还影响批处理次数等)。
下面来做实验看看效果。
首先新建一个场景,修改摄像机的Clear Flags为Solid Color(纯色),然后隐藏掉灯光。
然后添加一个Cube。
然后再不断复制这个Cube,会发现SetPass calls仍然为2,或者再手动创建其他的默认物体(如球体、胶囊体等),SetPass calls一直都是2。原因就是默认物体的材质球都是Default-Mateial,所以虽然物体增多了,但材质球数量没变,所以SetPass calls值不变。
现在我们新建一个材质球,然后拖拽到其中一个物体上,会发现SetPass calls变为了3。
然后删除多余的物体,只留下最初的Cube,再打开灯光,并开启灯光的阴影,关闭Cube的投射阴影,会发现SetPass calls都会增加。
然后又打开Cube的投射阴影,会发现SetPass calls立马变为了6!
可以看出,阴影真的耗。
具体阴影是怎么影响SetPass calls的值的,我也不晓得,如果有小伙伴晓得记得告诉我哈。(嘿嘿嘿)
Shadow caster 阴影投射器。说明该值与阴影相关。
Shadow Casters 属性用于统计在有光照的前提下且在摄像机的视锥体范围内, 有多少游戏物体具备投射阴影的能力。
稍微改变下场景中物体的属性都会影响这个数值,大概知道就行。
新建一个场景,什么都不改,发现Shadow casters为0,说明默认的天空盒不投射阴影,不影响该值。
然后添加一个Cube物体,并试图更改某些属性,比如说相机距离Cube物体的远近,Cube物体的Scale等。
Batch 批处理。
那么什么是批处理?
我们最常看到的优化技术大概就是批处理了。批处理的实现原理就是为了减少每一帧需要的draw call数目。为了把一个对象渲染到屏幕上,CPU需要检查哪些光源影响了该物体,绑定Shader 被设置它的参数,再把渲染纹理发送给GPU。当场景中包含了大量对象时,这些操作就会非常耗时。一个极端的例子是,如果我们需要渲染一千个三角形,把它们按一千个单独的网格进行渲染所花费的时间要远远大于渲染一个包含了一千个三角形的网格。在这两种情况下,GPU的性能消耗其实并没有多大的区别,但CPU的draw call数目就会成为性能瓶颈。因此,批处理的思想很简单,就是在每次面对draw call 时尽可能多地处理多个物体。
使用同一个材质的物体可以一起处理。对于使用同一个材质的物体,它们之间的不同仅仅在于顶点数据的差别。我们可以把这些顶点数据合并在一起,再一起发送给GPU,就可以完成一次批处理。
批出理的核心就是CPU把使用相同材质球的物体的网格合并再一起,然后把这个合并后的网格扔给GPU渲染,而不是一个一个网格扔给GPU渲染。
Stats面板上的Batches的值(批处理次数)说白了就是Draw Call的次数,就是要渲染完整个场景,CPU要总共通知GPU多少次。
那么什么会影响Batches呢?
①模型是否能够进行静态、动态批处理 ②灯光是否开启阴影 ③物体是否投射阴影
Saved by batching就是批处理节省Draw call的次数。
Unity3D中支持动态批处理和静态批处理。
先看动态批处理。
新建一个场景,并添加一个Cube物体。
然后复制多个Cube。
但是动态批处理的限制很多,比如模型的顶点数不能超过300个,模型使用的材质球的Shader不能有多个Pass等等。
对于场景中位置固定的物体,我们一般采用静态批处理,具体设置如下。
就勾选以上选项就ok了,然后需要运行起来才能看到效果,这里我就不截图了哈,自己可以去找个面数比较高的模型试试。这一部分可以去看看冯乐乐的《Unity Shader入门精要》讲得特别好、特别清楚。也可看看她的这篇博客,但是还是建议买书来看。
(ps:不知不觉4个小时过去了,今天先就这样吧)