Unity渲染优化小结

<入门精要>第16章读书笔记.

=List=

    • 影响性能的因素
    • 针对于CPU的优化
        • 批处理
    • 针对于GPU的优化
        • 减少顶点数目
        • 减少片元数目
        • 降低计算复杂度
        • 节省带宽

影响性能的因素

  1. CPU
    -Drawcall数量多.
    -物理计算,骨骼蒙皮,粒子系统以及复杂的脚本等.

  2. GPU
    -顶点数量多
    -分辨率大
    -overdraw次数多
    -显存不足
    -顶点,片源着色器计算复杂

  3. 带宽
    -使用了大尺寸未压缩的纹理
    -分辨率过高的帧缓存

针对于CPU的优化

CPU主要负责保证帧率,最常见的优化技术是采用批处理(Batching),目的是减少每帧的drawcall数量.
批处理的核心思路,就是每次调用drawcall的时候尽量多的处理多个物体.
批处理的过程:使用同一个材质球(注意不是同一个shader)的物体.把这些物体的顶点数据合并,一起发送给GPU,就完成了一次批处理.
Unity支持两种方式:动态批处理和静态批处理.

批处理

  1. 动态批处理
    动态批处理基本由Unity自动完成,不需要自己操作,并且对象可移动,缺点是受限比较多
    动态批处理的限制条件:
    1.网格顶点数量不能过多.(目前版本粗略限定在900以内)
    2.使用Lightmap的物体需要使用额外的渲染参数,这些参数需要指向Lightmap中的同一个位置.
    3.多Pass的Shader会中断批处理.

  2. 静态批处理
    实现原理:只在运行开始阶段,将需要批处理的模型合并到一个新的网格结构中,并且这些模型不可以在运行时移动.
    缺点:需要占用更多内存来存储合并后的网格结构.VBO(顶点缓冲对象,Vertex Buffer Object)数目变大.
    操作方法:勾选Inspector面板的Static,运行后,可以看到静态批处理后的效果.
    细节:
    1.对于使用同一个材质的物体,调用一个drawcall就可以完成绘制.
    2.使用不同材质的物体,虽然drawcall数量没有变化,但是可以减少drawcall之间的状态切换,以提升渲染性能.
    3.多Pass的Shader,平行光计算的basePass依然会被静态批处理,额外的Pass不会被批处理.

  3. 共享材质球
    不同模型通常渲染属性不会完全相同,需要尽可能合并材质,达到这些模型可以共享同一个材质球.
    合并方法:
    1.当材质使用不同纹理贴图时,可以把这些纹理合并成图集,使用不同的uv坐标采样,达到共用一个材质球的目的.
    2.当材质参数有区别时,可以采用网格的顶点数据来存储这些参数,常用于更改顶点颜色.

  4. 批处理注意事项
    1.批处理需要将多个模型先变换到世界空间再合并,如果shader中有在模型空间中进行的运算,那么批处理的结果就是错误的.
    2.在SubShader中使用标签"DisableBatching"=“True”,设置材质不会被批处理.
    3.对于半透明材质,Unity会优先保证绘制顺序,再尝试进行批处理.

针对于GPU的优化

GPU主要负责分辨率相关的处理.对于顶点级别和片元级别,分别有对应的优化方法.

减少顶点数目

  1. 优化网格顶点数
    Unity中显示的顶点数要比建模软件显示的多,因为Unity是站在GPU的角度去计算顶点数量的.
    对于GPU来说,顶点的每一个属性和顶点必须是一对一的关系,建模软件中顶点被共用对于GPU是不能理解的.
    GPU会把一个顶点拆分成多个,为了分离纹理坐标和产生平滑边界,本质就是是达到一对一的关系.

  2. 使用模型的LOD技术
    原理:当对象逐渐原理摄像机时,减少模型的面数,从而提高性能.
    方法:使用LODGroup组件来为一个物体构建LOD.一个对象会有多个不同面数的模型,分别对应LODGroup组件的不同等级,Unity会自动 判断当前位置上对应的等级.

  3. 遮挡剔除
    遮挡技术用来剔除其他物体后面看不到的物件.不仅可以减少顶点数,还可以减少overdraw.
    原理:使用一个虚拟摄像机遍历场景,构建一个潜在可见的对象集合的层级结构.运行时,每个摄像机会使用这个数据来识别可见或不可见的物体.需要注意,摄像机的视锥体剔除只能剔除不在视锥范围内的物体,但是不会判断遮挡关系.

模型LOD技术和遮挡剔除可以同时减少CPU和GPU的负荷.CPU提交更少的drawcall,所以GPU处理的顶点片元数目也减少了.

减少片元数目

处理过多的片元会造成GPU瓶颈,这里的优化重点在于减少overdraw(同一个像素被绘制多次).

  1. 控制绘制顺序
    Unity的渲染队列中,小于2500的对象会默认为不透明,就可以保证从前往后绘制,由于后面的物体不会通过深度测试,所以不会被渲染.
    而透明对象是从后往前绘制,造成overdraw增多.所以尽可能减少透明和半透明使用.
    此外.尽量充分利用渲染队列控制绘制顺序,思考场景中所有部分的遮挡关系再定义渲染队列,总结排队的意识与经验.
  2. 注意透明物体
    没有被遮挡剔除的半透明物体几乎一定会造成overdraw.
    透明度测试也会影响性能.虽然有深度写入,但是它的实现使用了discard或者clip,会导致一些硬件优化策略失效.
    有的时候,透明度混合的性能比透明度测试要好.
  3. 减少实时光和阴影
    实时光,多光源,这些光照方式对移动平台来说过于昂贵.
    使用多个Pass处理光照的shader会造成性能下降.
    如果不能避免多个光源,尽量选择逐顶点光照计算.
    采用光照贴图更适合移动平台.
    另一个模拟光源的方法是使用GodRay,可以用来模拟场景中很多小型光源.
    实时阴影会使CPU提交更多drawcall,增加GPC处理的数据,静态物体可以采用烘焙,把阴影信息存储到光照纹理中.

降低计算复杂度

  1. 优化代码
    尽可能的把计算放在Vertex函数内.顶点级别的采样数量比片元要小得多.
    尽量采用低精度浮点数进行运算,避免在不同精度之间转换,避免频繁进行重排操作.
    避免使用循环语句,分支语句;尽量避免使用复杂的数学运算.
    全屏后处理要慎用,一些效果可以采用LUT来替代.
  2. 使用Shader的LOD技术
    当Shader的LOD值小于设定值时,当前Shader才会被使用.

节省带宽

  1. 减小纹理
    纹理的长宽比最好是1:1,并且最好是2的整数次幂.很多优化在这种条件下能发挥更大的作用.
    尽可能多采用纹理压缩.不同的GPU有各自的压缩格式,只要将Unity设置为自动压缩,它就会根据设备选择对应的压缩格式.
    采用多级渐远纹理技术Mipmapping.
  2. 利用分辨率缩放
    GPU的性能屏幕分辨率之间是需要做取舍的,面对某些低性能GPU的机型时,缩放分辨率是一个可选择的办法.

你可能感兴趣的:(图形学笔记)