drawcall原理
drawCall实际上就是一个命令,是Cpu想Gpu发起的渲染命令。
所以优化drawcall的数目,实际上就要减少cpu对gpu发起的渲染命令,举个例子,如果我们要渲染一千个三角形,把他们按一个单独的网格进行渲染所花费的时间要远大于渲染一个包含了一千个三角面的网格,而主要的问题就是在CPU块,调用了太多次的drawcall,Gpu可能并没有太大的差别。
批处理
动态批处理
如果一个场景一些模型共享了同一个材质并且满足动态批处理的条件,Unity会自动对它们进行动态批处理,从而只要花费一个drawcall就可以渲染这些模型。动态批处理的原理是,每一帧都把这部分可以进行动态批处理的模型进行模型网格合并,所以我们依然可以在代码里面移动这些物理。
限制的条件- 能进行动态批处理的网格的顶点属性规模要小于900,例如,如果在shader中要使用 3个顶点属性(顶点位置,发现,纹理坐标),那它的顶点数目不能超过900/3 = 300个。
- 多Pass的Shader会中断批处理。
- 一般来说,所有对象都需要使用同一个缩放尺寸。(听说在Unity5 已经没有了这种限制)
静态批处理
静态批处理相对于动态批处理,没有了模型大小的限制,实现原理只在运行开始的阶段,把需要静态批处理的模型合并到一个新的网格结构中,这就意味着在静态批处理的模型无法在运行时刻移动,旋转等。
注意:批处理是有缺点的,它会占用个多的内存来存储合并后的几何结构,例如,如果在一个使用了1000个相同树模型的森林中使用静态批处理,会多使用1000倍的内存!!原本相同的模型会因为坐标位置不同,同时合并到一个新的网格结构中,这会造成严重的内存影响。
使用方法:只需要对物体勾选Static 为静态- 共享材质
如果两个材质之间只有使用的纹理不同,我们可以把这些纹理合并到一张更大的纹理中(图集),一旦使用了同一张纹理,我们就可以使用同一个材质再使用不同的采样坐标对纹理采样就可以。
减少需要处理的顶点数目
- 从美术上减少顶点的数目
- Unity模型的LOD技术(Level of Detail),类似于 mipmap的技术,当物体离摄像机很远时,模型上的很多细节无法被察觉到,因此,LOD允许当对象逐渐远离摄像机时,减少模型上的面片数量。在Unity中使用LOD很简单,准备细节的美术模型,然后为物体添加一个LOD Group进行调整就可以
- 遮挡剔除技术(Occlusion Culling),相关(http://docs.unity3d.com/Manual/OcclusionCulling.html)
减少需要处理的片元数目
- 控制渲染顺序最大的避免overdraw,尽量避免使用半透明队列
- 减少实时关照和阴影
节省带宽
- 合并纹理图集
- 纹理的长宽比最好是正方形,而且是2的整数幂
- 使用MipMaps,Unity会自动生成mipmap,可以节省GPU访问的像素数目
- 利用分辨率缩放
代码块的计算复杂度
Shader中的Lod
SubShader{
Tags{"RenderType" = "Opaque"}
LOD 200
}
默认的Diffuse LOD值为200,Bumper Specular LOD值为400,我们可以使用Shader.maximunLOD / Shader.globalMaxinumLOD来设置徐云的最大LOD值,大于该LOD值的shader会禁用掉