UPL9-2——降低几何复杂度

为什么要降低几何复杂度

降低几何复杂度的主要目的是

  1. 减轻 GPU 与 CPU 在几何处理阶段的负担
  2. 减轻 内存带宽 压力和 显存 压力

等等

  • 从GPU角度

    GPU 渲染管线的第一步就是处理顶点,
    如果场景里有几百万甚至上千万个顶点,GPU 必须逐个变换(模型矩阵、光照计算、蒙皮等),
    负担会极大,可能带来:

    1. 帧率下降
    2. 移动端功耗升高、发热严重
    3. 顶点带宽不足导致 GPU 卡顿

    等等

    因此,降低几何复杂度,相当于直接减少了顶点着色器的工作量

  • 从 CPU 角度

    每个网格渲染之前,CPU 要把网格数据提交给 GPU(DrawCall),
    如果模型过于复杂(高面数、网格碎片多),则会导致 CPU 消耗在渲染准备工作上,挤占逻辑、物理计算上的时间
    因此,降低几何复杂度,可以间接减少 CPU 开销

  • 从显存角度

    一般高面数模型文件更大,贴图需要更高分辨率支撑
    高分辨率贴图以及顶点数据都需要占显存,可能给显存带来压力
    因此,降低几何复杂度,可以减轻显存压力

  • 从内存带宽角度

    每帧都需要把顶点、顶点索引相关数据传送到GPU,几何复杂度高会增加数据传输量,消耗内存带宽
    因此,降低几何复杂度,可以减少内存带宽的占用

降低几何复杂度的具体方法

  1. 美术优化

    从源头减少模型的复杂度,主要由美术人员在建模阶段直接控制,主要做法:

    1. 少用高面数模型,能用贴图法线(Normal Map)代替细节就用贴图
    2. 使用合理的多边形分布,把细分面留给容易注意到的部位

    等等

    主要目的就是用最少的资源做出做好的美术表现
    从源头制定好的规范,可以让整体模型预算更加可控
    避免后期出现性能问题时再来改

  2. 移除网格

    完全剔除不必要的几何体,避免 GPU 浪费处理不可见或者无关的网格

    主要做法:

    1. 删除关卡中看不到或不重要的装饰性几何体
    2. 用法线贴图、贴花效果代替体积结构,比如雕刻、螺丝、砖块接缝等效果等
    3. 用平面贴图代替立体模型,比如窗户格子效果等

    主要目的就是优化关卡中装饰或远景模型,有时候牺牲一些细微表现,带给玩家的体验区别不大

  3. LOD

    利用 Unity 中的 LOD Group 组件,根据距离切换不同分辨率的模型网格
    LOD 模型通常由美术导出(也可以利用一些插件自己生成),配合摄像机视距控制显示哪一个模型

    主要做法:
    让游戏中的角色、建筑、大型创景元素使用 LOD Group 组件关联不同精度的模型
    这样能显著减少远处对象的顶点数

    详细可见:UPL9-3——LOD

  4. 遮挡剔除

    利用 Unity 中自带的遮挡剔除 (Occlusion Culling) 相关功能,
    避免渲染那些被其它物体完全挡住、相机不可见的物体,从而减少 GPU 和 CPU 的渲染开销

    主要做法:
    在一些容易产生遮挡的环境中,比如室内场景、复杂建筑场景、森林场景等
    使用 Unity 中的遮挡剔除功能,剔除在墙体、地形、树木等背后的对象,让他们不被渲染,减少渲染开销

    详细可见:UPL9-4——遮挡剔除

  5. 更多方式

    以下这些方法,可能会影响美术表现效果

    1. 简化骨骼动画

      骨骼数量过多时,GPU 和 CPU 负担都重
      可以减少关节数,或者用 VAT(骨骼烘焙动画纹理)代替

    2. Impostor (冒充者/替身) 技术
      把一个复杂的 3D 物体 预先烘焙成 2D 纹理
      用 2D 贴图来冒充 3D 模型,可以配合 LOD 使用

      • 近距离,使用正式的 3D 模型
      • 中远距离,使用低模 LOD
      • 超远距离,使用 Impostor (冒充者/替身) 技术
    3. Mesh Simplification(网格简化算法)

      美术在建模时,使用一些建模软件自带的网格简化功能,Unity 也有一些第三方插件,比如:

    等等