Unity Shader总结(十六)——Unity渲染优化(批处理、LOD)

CPU

1.动态批处理

优点:一切处理unity自动完成,物体可以移动;
缺点:限制很多,可能无法动态批处理一些使用了相同材质的物体;
原理:每一帧把可以批处理的模型网格合并,再把合并后的模型数据给GPU,然后使用同一个材质进行渲染;
如果使用了多个pass的物体需要使用多个光照,就会破坏动态批处理的机制,unity不会对其进行动态批处理;

2.静态批处理

优点:自由度很高,限制很少;
缺点:会占用更过的内存(因为共享网格的每一个物体都会对应一个该网格的复制品,如:1000个相同树的模型,会占用1000倍的内存),相当于内存换性能,物体不可以移动;
原理:只在运行开始阶段,把需要静态批处理的模型合并到一个新的网格结构中;
内部实现:unity首先将这些静态物体变换到世界空间下,然后为它们构建一个更大的顶点和索引缓存,使用同一材质的物体只需要一个Draw Call,使用不同材质的物体虽然仍然需要多个Draw Call,但可以减少这些Draw Call之间的状态切换;

3.共享材质

如果两个材质之间只有纹理不同,可以将两张纹理合并成一个更大的纹理——图集,然后使用不同的采样坐标采样即可;

4.应用场景

游戏中的小道具:可以捡拾的金币等,可以使用动态批处理;
对于包含动画的物体,无法全部使用静态批处理,如果有不动的部分,可以把这部分标识成static;

GPU

一、减少需要处理的顶点数目

优化几何体

建模时尽量减少三角面片的数目,建模软件中有相应的优化选项;
移除不必要的硬边和纹理衔接,避免边界平滑和纹理分离;

LOD技术

当对象远离摄像机时,减少模型上的面片数量,在unity中,可以使用LOD Group组件来为一个物体构建一个LOD。需要为同一个对象准备多个包含不同细节程度的模型,把它们赋给LOD Group组件中的不同等级,unity就会自动判断当前位置上需要使用哪个等级的模型。

遮挡剔除技术

遮挡剔除会使用一个虚拟的摄像机来遍历场景,从而构建一个潜在可见的对象集合的层级结构。在运行时刻,每个摄像机将会使用这个数据来识别哪些物体是可见的,哪些被挡住不可见。遮挡剔除不仅可以减少处理的顶点数,还可以减少overdraw,提高游戏性能。

LOD和遮挡剔除可以使CPU提交更少的draw call,GPU处理更少的顶点和片元数目;

二、减少需要处理的片元数目

这部分重点是减少overdraw,即一个像素被绘制了多次;

控制绘制顺序

由于深度测试,如果保证物体是从前往后绘制,就可以很大程度上减少overdraw,因为后面绘制的物体无法通过深度测试;
通常渲染队列小于2500的不透明物体从前往后,其他的物体从后往前,尽量把物体的队列设置为不透明物体,避免使用半透明队列;
对于天空盒子,它覆盖了所有像素,并且在所有物体的后面,因此可以把它设置为Geometry+1;

当心半透明物体

半透明物体因为没有开启深度写入,必须从后往前渲染,因此一定会产生overdraw。
GUI大部分是半透明,尽量减少窗口中GUI所占的面积;
透明度测试会影响性能,尽量使用透明度混合;

减少实时光照和阴影

避免使用实时光照,使用烘焙技术,将光照提前烘焙到一张光照纹理(lightmap)中,根据纹理采样得到光照结果;
God Ray也可以模拟光源,很多情况是通过透明纹理模拟得到;

三、节省带宽

减少纹理大小

所有纹理的长宽比最好是正方形,且是2的整数幂;
尽可能使用mipmap和纹理压缩,将纹理类型设置为advanced可以自定义许多选项,如生成mipmaps;
纹理压缩设置Auto即可,GUI例外。因为对画质有要求;

利用分辨率缩放

直接调用Screen.SetResolution,实际使用可能会遇到问题,网上查阅解决方法;

四、减少计算复杂度

shader的LOD技术

只有shader的LOD值小于某个设定的值,这个shader才会被使用;
在subshader中LOD xxx(数值),然后通过Shader.maximumLOD或Shader.globalMaximumLOD来设置允许的最大LOD值;

优化代码

尽可能将计算放在每个对象或逐顶点上;
使用低精度的浮点值,最高精度的float/highp适用于存储顶点坐标等变量,但计算速度最慢,尽量避免 在片元着色器中使用;
half/mediump适用于一些标量、纹理坐标等,计算速度大约是float的两倍;
fixed/lowp适用于绝大多数颜色变量和归一化后的方向矢量,速度是float的4倍,尽量避免不同精度的转换;
对GPU来说,使用尽可能少的插值变量,如对两个纹理坐标插值,可以存在一个float4中的xy和zw分量中;
尽可能不要使用全屏的屏幕后处理效果,尽量把多个特效合并到一个shader中;
尽量不要使用分支和循环语句;
尽量避免sin、cos等复杂运算,使用查找表替代;
尽量不要使用discard操作;

猜你喜欢

转载自blog.csdn.net/memory_MM_forever/article/details/118522311