Draw Call就是CPU调用图形编程接口,是CPU向GPU发送的命令和GPU并行工作的原理CPU和GPU工作有一个命令缓冲区(Command Buffer)命令缓冲区包含了一个命令队列,由CPU向其中添加命令,而由GPU从中读取命令。当CPU需要渲染一些对象时,它可以向命令缓冲区添加命令,而GPU完成了上一次的渲染任务后,它就可以从命令队列里取出一个命令并执行它。命令缓冲区中的命令有很多种类,而Draw Call是其中的一种,其它命令还有改变渲染状态等命令(改变使用的Shader,使用不同的纹理等)。
(资料图片仅供参考)
2.为什么 Draw Call多了会影响帧率?在每次调用Draw Call之前,CPU需要向GPU发送很多内容,包括数据,状态,命令等。CPU完成了这些准备工作,GPU就可以开始本次的渲染。如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call命令上,造成CPU的过载。3.如何减少DrawCall?DrawCall是CPU调用底层图形接口。比如有上千个物体,每一个的渲染都需要去调用一次底层接口,而每一次的调用CPU都需要做很多工作,那么CPU必然不堪重负。但是对于GPU来说,图形处理的工作量是一样的。所以对DrawCall的优化,主要就是为了尽量解放CPU在调用图形接口上的开销。所以针对drawcall我们主要的思路就是每个物体尽量减少渲染次数,多个物体最好一起渲染。所以,按照这个思路就有了以下几个方案:
使用Draw Call Batching,也就是描绘调用批处理。Unity在运行时可以将一些物体进行合并,从而用一个描绘调用来渲染他们。具体下面会介绍。
通过把纹理打包成图集来尽量减少材质的使用。
尽量少的使用反光啦,阴影啦之类的,因为那会使物体多次渲染。
mesh合并,减少Cpu需要提交的模型信息次数。
使用Gpu Instance一次绘制多个相同的物体。
优化shader 减少pass通道
注意OverDraw
Call Batching
首先我们要先理解为何2个没有使用相同材质的物体即使使用批处理,也无法实现Draw Call数量的下降和性能上的提升。
因为被“批处理”的2个物体的网格模型需要使用相同材质的目的,在于其纹理是相同的,这样才可以实现同时渲染的目的。因而保证材质相同,是为了保证被渲染的纹理相同。
因此,为了将2个纹理不同的材质合二为一,我们就需要进行上面列出的第二步,将纹理打包成图集。具体到合二为一这种情况,就是将2个纹理合成一个纹理。这样我们就可以只用一个材质来代替之前的2个材质了。
而Draw Call Batching本身,也还会细分为2种。
Static Batching 静态批处理
只要物体不移动,并且拥有相同的材质,静态批处理就允许引擎对任意大小的几何物体进行批处理操作来降低描绘调用。
那要如何使用静态批来减少Draw Call呢?你只需要明确指出哪些物体是静止的,并且在游戏中永远不会移动、旋转和缩放。想完成这一步,你只需要在检测器(Inspector)中将Static复选框打勾即可,如下图所示:
编辑
Dynamic Bathing 动态批处理
编辑
动态批处理需要在Project Setting → Player → Other Setting 中将Dynamic Bathing 勾选上,Unity会自动将使用相同材质的物体合并处理。但动态批处理需要满足以下条件:
顶点属性最大限制900的可移动物体,
使用lightmap的物体不行进行批处理
使用多通道的shader也不会进行批处理
缩放比不同的物体不会批处理
Enable GPU Instancing
在使用大量重复的物体时,需要将该物体的材质的 Enable GPU Instancing 勾选上,这样Unity会将Mesh相同的物体合并处理,常用于树木,植被,粒子等。使用GPU Instancing 对shader有要求,需要在shader中添加支持GPU Instancing 批处理的命令 #pragma multi_compile_instancing
编辑切换为居中
实际测试,如果shader中有多pass也会影响Enable GPU Instancing的合批操作。
减少实时光照和阴影效果
光照产生阴影同样会产生大量的DrawCall,类似模型的渲染,在不需要阴影的情况下关闭灯光的阴影效果,降低阴影质量。对需要阴影和不需要阴影的物体拆分shader,分别使用会产生阴影和不会产生的材质shader。
编辑
编辑
同样可以在物体的meshrender 组件中选择是否产生和接受阴影
编辑
减少Shader的pass通道
一个pass通道会多产生一个绘制信息,并且对动态合批和gpu instance产生影响,尽可能的在一个pass通道中处理好模型的表现效果。
注意渲染顺序和透明材质使用
unity的绘制顺序是先绘制不透明物体,再绘制透明物体,如果有透明物体则会导致一些像素点被重新绘制增加调用次数并可能打断一部分合批操作,如果多个透明物体重叠则更加复杂。OverDraw就是上面所表达的意思。常常是游戏的性能问题所在。注意透明材质的使用,合理的设置渲染顺序,尤其是特效这部分常常是开发者所忽略的,特效包含大量的半透明效果。
特效方面的优化可以看我这篇文章:/read/cv25215347
UGUI方面的优化可以看我这篇文章:/read/cv23858056