一、什么是Draw Call
Draw Call是CPU向GPU发送指令的过程
过程:设置颜色-->绘图方式-->顶点坐标-->绘制-->结束
二、优化Draw Call
渲染顺序
U3D的渲染是有顺序的,U3D的渲染顺序是由我们控制的,控制好U3D的渲染顺序,你才能控制好DrawCall
一个DrawCall,表示U3D使用这个材质/纹理,来进行一次渲染,那么这次渲染假设有3个对象,那么当3个对象都使用这一个材质/纹理的 时候,就会产生一次DrawCall,可以理解为一次将纹理输送到屏幕上的过程,(实际上引擎大多会使用如双缓冲,缓存这类的手段来优化这个过程,但在这 里我们只需要这样子认识就可以了),假设3个对象使用不同的材质/纹理,那么无疑会产生3个DrawCall
接下来我们的3个对象使用2个材质,A和B使用材质1,C使用材质2,这时候来看,应该是有2个DrawCall,或者3个DrawCall。 应该是2个DrawCall啊,为什么会有3个DrawCall???而且是有时候2个,有时候3个。我们按照上面的DrawCall分析流程来分析一 下:
1.渲染A,使用材质1
2.渲染B,使用材质1
3.渲染C,使用材质2
在这种情况下是2个DrawCall,在下面这种情况下,则是3个DrawCall
1.渲染A,使用材质1
2.渲染C,使用材质2
3.渲染B,使用材质1
因为我们没有控制好渲染顺序(或者说没有去特意控制),所以导致了额外的DrawCall,因为A和B不是一次性渲染完的,而是被C打断了,所以导致材质1被分为两次渲染
那么是什么在控制这个渲染顺序呢?首先在多个相机的情况下,U3D会根据相机的深度顺序进行渲染,在每个相机中,它会根据你距离相机的距离,由远到近进行渲染,在UI相机中,还会根据你UI对象的深度进行渲染
那么我们要做的就是,对要渲染的对象进行一次规划,正确地排列好它们,规则是,按照Z轴或者深度,对空间进行划分,然后确定好每个对象的Z轴和深度,让使用同一个材质的东西,尽量保持在这个空间内,不要让其他材质的对象进入这个空间,否则就会打断这个空间的渲染顺序
动态合批和静态合批
1.静态合批(static batch)
将static的静态物体(永远不会移动、旋转和缩放) ,如果相同材质球,面数在xx之内。unity会自动合并成一个batch送往GPU处理
(64k顶点和64k索引)
使用静态合批需要额外的内存开销来存储合并后的几何数据。
如果一些物体共用了同样的几何数据,那么引擎会在编译以及运行状态对每个物体创建一个几何数据备份
如果static物体过大,应该注意内存开销
原理:
1.自动提取这些静态模型的 VertexBuffer和IndexBuffer
2.根据其在场景中的位置等最终状态信息,将这些模型的顶点数据变换到世界空间下
3.重新构建大的VertexBuffer和IndexBuffer
4.记录每一个子模型的IndexBuffer数据在构建大的IndexBuffer的起始以及结束位置
2.动态合批(dynmaic batch)
如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行处理(动态批处理是自动完成的)
注意:
1.动态批处理物体需要在每个顶点上进行一定开销,动态批处理仅支持小于900顶点的网格物体(不知道现在啥样了)
2.如果着色器使用顶点位置,法线和UV值三种属性,只能批处理300顶点以下的物体;如果着色器需要使用顶点位置,法线,UV0,UV1和切向量,只能批处理180顶点以下的物体
3.不能使用缩放尺度(scale),缩放不同的物体不能进行批处理;统一缩放尺度的物体不会与非统一缩放尺度的物体进行批处理,eg:(1,1,1)和(1,2,1)不会批处理,(1,2,1)和(1,3,1)可以进行批处理
4.使用不同材质的实例化物体将会导致批处理失败
使用LOD
使用 LOD 技术可以根据物体与相机的距离或屏幕占比等因素动态调整物体的细节级别,以降低远离相机的物体的绘制质量和复杂度。这样可以减少不必要的绘制操作,从而减少 Draw Call 的数量。具体来说,通过使用较简化的模型、减少纹理贴图大小或使用更简单的着色器等方式,可以降低物体的多边形数、纹理内存和着色器计算量,进而减少 Draw Call 的数量。
通过合理地设置 LOD 级别并进行适当的渲染级别切换,可以根据观察者与物体的距离和视角来调整物体的质量和细节。对于离相机较远或屏幕上占比较小的物体,可以使用较低的 LOD 级别,减少对应的 Draw Call 数量。这种优化方法在场景中大量存在复杂物体的情况下尤为有效。
需要注意的是,LOD 技术并非适用于所有场景。在一些特定的应用中,如近距离观察或需要高质量渲染的场合,可能需要保持较高的 LOD 级别以提供更好的细节和视觉效果。
总而言之,通过使用 LOD 技术,可以优化 Draw Call 的数量,减轻 CPU 和 GPU 的开销,从而提升渲染性能和效率。