当前位置: 首页 > news >正文

Unity 性能优化 之 理论基础 (Culling剔除 | Simplization简化 | Batching合批)

Unity 之 性能优化 -- 理论基础

  • 优化相关概念
  • Unity工程中的剔除方案
    • 渲染管线中基于深度检测的片元遮挡
    • Unity Depth Priming (Pre-Z pass)使用限制
    • 可自行拓展的高级剔除方案
  • Simplization简化
    • Unity工程中的简化方案
    • 可自行拓展的高级简化方案
  • Batching合批
    • Unity工程中的合批方案
    • 资源Batching
    • Draw Call Batching
    • Set Pass Call Batching
    • GPU Instancing
    • Batching异常原因

优化相关概念

Culling剔除、Simplization简化、Batching合批,三者的最终目的均为优化渲染提前期,使得渲染下游能够持续得获取数据并处理。

细分起来,Culling为去除不需要渲染的信息,Simplization为对待渲染的内容根据类型分类,Batching为对数据路径类似的信息进行打包转发。

Unity工程中的剔除方案

在这里插入图片描述

渲染管线中基于深度检测的片元遮挡

  • 传统渲染管线中,会在片元着色器绘制后,进行深度测试,以进行遮挡剔除,但片元绘制已经发生了,依然会带来Overdraw性能开销。
  • 在现代硬件的支持下,往往会在片元着色器绘制前,先进行深度测试与写入、从而节省不必要的片元绘制,该步骤称为Early-Z。
  • 但在一些情况下,如开启AlphaTest、关闭DepthTest、手动修改深度、手动丢弃片元等,Early-Z将失效,从而带来Overdraw。
  • 因此,可以在渲染管线中,手动实现RenderPass,从而在Early-Z之前,预先进行一步深度测试与写入,从而确认ZBuffer有效,这个流程成为Pre-Z。
  • 在Unity的URP管线中,预置了Depth Priming功能,实现Pre-Z流程。

Unity Depth Priming (Pre-Z pass)使用限制

  • 只能在Forward前向渲染中使用,同时自定义Shader需要手动添加DepthOnlyPass。
  • 如果场景不复杂,即Overdraw不是造成GPU瓶颈的主要负担时,反而不建议使用Depth Priming,此时有可能反而成为负优化。
  • 移动端如果Depth Priming与MSAA同时开启,将带来了大量额外开销,甚至高于Overdraw开销。
  • 需要注意Depth Priming将带来额外的DrawCall或其他图形API调用开销,所以在开启Depth Priming前后需要对比额外调用开销和节省的Overdraw开销情况。

可自行拓展的高级剔除方案

  • 场景数据结构:Octree、BSP Tree、Portal、Voxelization;
  • GPU Culling:Hi-Z Pass、Temporal Reprojection Culling、Cluster、Tile-based Visible Buffer。


Simplization简化

Unity工程中的简化方案

  • Quality Settings中有若干配置项,可以根据目标平台进行选用;
  • 使用烘焙光照简化实时光照;
  • 使用BoudingBox或组合碰撞体来代替Mesh碰撞体;
  • 使用Local Volume代替Global Volume;
  • 使用Raycast代替SphereCast、CapsuleCast等;
  • 使用纹理文字代替系统文字;
  • 使用Mesh LOD、Shader LOD、HLOD等LOD方案;
  • 在Camera中Override一些URP管线中的通用设置;
  • OnDemandRendering配置;

可自行拓展的高级简化方案

  • 场景数据结构简化
  • 第三方LOD方案与插件
  • Mesh Impostor
  • AnimationLOD
  • 骨骼LOD
  • 2D寻路代替Navigation Mesh
  • 拓展类似OnDemand接口


Batching合批

Unity工程中的合批方案

资源Batching:

  • 分为Mesh、Texture、Shader参数、材质属性;
  • 资源Batching是做其他渲染合批优化的前提。

Draw Call Batching:

  • 分为Static Batching、Dynamic Batching;
  • 通过将多个Draw Call合批成一个较大的Draw Call,从而减少CPU到GPU之间的通信开销和渲染管线中的状态切换次数。

Set Pass Call Batching:

  • 仅有SRP Batching;
  • 将具有相同渲染状态和材质属性的多个Draw Call合批成一个大的Draw Call,并在GPU上以一次性的方式执行,而不是逐个绘制调用。

GPU Instancing:

  • 分为直接渲染、间接渲染、程序化间接渲染;
  • 在GPU中一次性传递多个相同网格的实例数据,然后在GPU内部进行并行处理和渲染,同样起到减少Draw Call的目的从而优化性能。

上述各类Batching方案,在实践效果意义上的优先级一般为:
资源Batching > SRP Batching = Static Batching > GPU Instancing > Dynamic Batching

资源Batching

  1. Mesh:

    • 使用Mesh.ConbineMesh合并相邻的网格对象。
    • 优点在于,能够使用对整体网格的单次Draw Call,来代替零散网格的多次Draw Call。
    • 缺点在于,可能会带来额外的内存开销,同时Occulusion Culling会受到影响,在某些情况下可能会导致剔除不够精确从而带来的Overdraw。
      对于SkinnedMeshRenderer,其在动态合并或拆分Mesh时,可能需要根据需求考虑Bone、UV和Texture的合并。
  2. Texture:

    • Texture的组合合并思路,有AtlasTexture和TextureArray两种类型。
    • Atlas Texture是将多个小纹理合并成一个大纹理的技术,在使用时通过UV坐标来指定每个小纹理的位置。这样做可以减少渲染时的纹理切换次数,从而提高性能。
    • Texture Array是将多个纹理作为一个纹理数组存储在GPU内存中的技术。这样做可以在单个渲染调用中同时使用多个纹理,从而减少CPU到GPU的通信开销和渲染状态切换次数。通常用于同时渲染具有相似外观但不同纹理的物体,例如一组树木或草地。
  3. Shader与材质:

    • 尽量不要为了微小的属性差异而生成与配置大量几乎重复的材质球,而是可以考虑通过代码做参数覆盖。
    • Build In管线下,使用Material Property Block (Renderer.SetPropertyBlock)。
    • SRP管线下,使用Const Buffer (Material.SetFloat、Material.SetConstantBuffer等)。

Draw Call Batching

  1. Static Batching :

    • 将静态物体合并为一个大网格,从而以更快的速度渲染它们。
    • Static Batching不一定减少DrawCall,但是会让CPU在“设置渲染状态-提交Draw Call”上更高效。
    • 限制条件为:
      一个静态批处理中,顶点数量上限为64000。同时类似ConbineMesh,可能存在额外的内存开销与Occulusion Culling影响。
    • 具体配置方式为:
      在ProjectSettings-Player中勾选“Static Batching”项,同时在编辑器中对于需要实现Static Batching的GameObject,在其Static中勾选“Batching Static”项。对于Runtime动态生成的对象,可以参考StaticBatchingUtility.Combine方法。
  2. Dynamic Batching:

    • 在运行时Unity自动把使用相同材质引用的网格实例合并为一个,再传递给GPU。
    • Dynamic Batching是为过去的低端设备设计的,只有当Dynamic Batching产生的CPU开销小于DrawCall的开销,Dynamic Batching才具有优化性能的效果。而在如今的电子设备上,动态批处理产生的CPU开销反而有可能大于DrawCall的开销,影响性能。
    • 限制条件为:
      • 一个动态批处理中,顶点属性数量不能大于900;
      • 除了渲染阴影对象外,相同材质,不同材质示例也不能合并;
      • 具有光照贴图的游戏对象如果有附加渲染器参数时,如果需要动态合批这些对象,他们必须指向相同的光照贴图位置;
      • 有多Shader Pass的游戏对象无法实现Dynamic Batching;
      • 受多个光照影响的对象,满足动态合批条件合批后,只会受一个光源的影响;
      • 延迟渲染下不支持动态合批;
      • CPU开销可能会增大。
    • 具体配置方式为:
      在Universal Render Pipeline Asset中勾选“Dynamic Bathcing”项,同时务必通过Profile等分析工具确保Dynamic Batching不会带来负优化。

Set Pass Call Batching

当场景中有很多物体与材质球,但是这些材质球使用的是同一个shader时,SRP Batcher的CBUFFER维护逻辑将带来更优的性能开销。SRP Batcher本身不会减少DrawCall,而是在DrawCall与DrawCall之间减少CPU的工作量。

限制条件为:

  • 图形Api版本要求(移动端版本要求为OpenGL ES 3.0以上);
  • SRP Batcher仅能在SRP管线下运行;
  • 粒子对象不能实现SRP Batching;
  • 使用MaterialPropertyBlocks的游戏对象不能合批;

场景Shader需要支持SRP Batcher,可以在Shader信息界面中观察“SRP Batcher”项是否为“Compatible”。URP/HDRP中的Lit/Unlit Shader默认支持。为使自定义Shader支持SRP Batcher,所有的Shader属性都要在一个名为UnityPerMaterial的CBUFFER中声明,详见:URP 系列教程 | 能讲讲如何在 URP 中使用 SRP Batcher 吗?

具体配置方式为:在Universal Render Pipeline Asset中勾选“SRP Batcher”项。

GPU Instancing

GPU Instancing适用于处理大量相同物体,即相同Mesh和Material,比如建筑物/树/草等重复出现的物体。
限制条件为:

  • 图形Api版本要求(移动端版本要求为OpenGL ES 3.0以上);
  • 渲染顶点数较少的网格时,效率可能会较差,需要实际测试对比;
  • 【GPU Instancing】不能与【Static Batching、Dynamic Batching、SRP Batching】同时使用。若同时开启,程序只会执行优先级更高的一个:SRP Batcher|Static Batching > GPU Instancing > Dynamic Batching。

具体配置方式为:
在材质球面板中开启Enable GPU Instancing项,如果自定义Shader则同时还需要自定义Instancing Buffer的结构。同时可以在Runtime中通过DrawMeshInstanced、DrawMeshInstancedIndirct、DrawMeshInstancedProcedural方法,这些API不创建GameObject,直接根据参数在屏幕上进行DrawMesh。

Batching异常原因

在FrameDebugger中,会提示造成Batching异常的原因,官方文档总结清单如下:

  • “An object is affected by multiple forward lights.” 此物体受到多个前向灯光的影响;
  • “Objects have different materials.” 此物体有不同的材质;
  • “An object is using a multi-pass shader.” 此物体使用了多pass着色器;
  • “An object has odd negative scaling.” 此物体Trasform的Scale使用了负数;
  • “Either objects have different \”Receive Shadows\“ settings, or some objects are within the shadow distance, while some other objects are not.” 此物体接收阴影的设置不同,或者物体有不同的的阴影距离设置;
  • “Objects are affected by different forward lights.” 此物体受到不同的前向灯光影响;
  • “Objects are on different lighting layers.” 物体在不同的Lighting Layer上;
  • “Objects have different \”Cast Shadows\“ settings.” 此物体有不同的投影体设置;
  • “Objects either have different shadow caster shaders, or have different shader properties / keywords that affect the output of the shadow caster pass.” 此物体有不同的投影着色器设置或者有不同的着色器属性或者关键字影响Shadow Caster Pass的输出;
  • “The shader explicitly disables batching with the \”DisableBatching\“ tag.” 着色器中显式设置了DisableBatching的标记;
  • “Objects have different MaterialPropertyBlock set.” 此物体有不同的MaterialPropertyBlock集合;
  • “Non-instanced properties set for instanced shader.” Instanced的着色器有非instanced属性集;
  • “Objects are lightmapped.” 物体使用了不同的LightMap或者虽然使用相同的LightMap但使用的UV不同;
  • “Objects are affected by different light probes.” 此物体受到不同的光照探针影响;
  • “Objects are shadowed by baked occlusions and have different occlusion factors.” 此物体烘焙了遮挡,并且设置了不同的遮挡因子;
  • “Objects are affected by different reflection probes.” 此物体受到不同的反射探针影响;
  • “Rendering different meshes or submeshes with GPU instancing.” 使用GPU实例化渲染不同的网格或子网格;
  • “Objects have different batching-static settings.” 此物体有不同的静态合批设置;
  • “Objects belong to different static batches.” 此物体归属不同的Static Batches;
  • “Dynamic Batching is turned off in the Player Settings or is disabled temporarily in the current context to avoid z-fighting.” 在Player Settings中关闭了动态合批,或者在当前的环境中为了避免深度冲突而临时关闭了合批;
  • “There are too many indices (more than 32k) in a dynamic batch.” 动态合批中有太多的索引(大于32k);
  • “A mesh renderer has additional vertex streams. Dynamic batching doesn‘t support such mesh renderers.” Mesh Renderer具有其他顶点流。动态批处理不支持此类网格渲染器;
  • “A submesh we are trying to dynamic-batch has more than 300 vertices.” 动态合批超过300个顶点;
  • “A submesh we are trying to dynamic-batch has more than 900 vertex attributes.” 动态合批超过900个顶点属性;
  • “This is the first draw call of a new shadow cascade.” 新阴影级联的第一次绘制调用;
  • “The material doesn‘t have GPU instancing enabled.” 材质未启用GPU Instancing功能;
  • “Objects are rendered using different rendering functions. This can happen if the type of renderer is different (eg Mesh/Skinned Mesh) or when using different settings within the same renderer, such as Sprite Masking.” 使用不同的渲染。如果渲染器的类型不同(例如网格/蒙皮网格),或者在同一渲染器中使用不同的设置(例如精灵遮罩),则可能会发生这种情况;
  • “Objects have different batching keys. This is usually caused by using different vertex streams on Particle Systems, or by mixing Lines and Trails, or by mixing lit and unlit geometry.” 此对象具有不同的Batching Keys,这通常是由于在粒子系统上使用不同的顶点流,或混合线和轨迹,或混合Lit和Unlit的几何体造成的;
  • “Mesh uses 32 bit index buffer.” Mesh使用了32位的索引缓冲;
  • “Submesh has non-zero base vertex.” 子网格对象有非0的基础顶点,即submesh.BaseVertexLocation != 0;
  • “The previous instanced draw call has reached its maximum instance count.” 先前的InstanceDrawCall已经达到了Instance的最大数量;
  • “Motion Vector rendering doesn‘t support batching.” Motion Vector的渲染不支持Batching;
  • “When using late latching, children of an XR late latched GameObject do not use batching.” 使用late latching时,XR late latched GameObject的子级不能合批;
  • “Objects have different bounds and bounds instancing is disabled.” 对象具有不同的包裹体,那么包裹体实例化被禁用;
  • “SRP: Node have different shaders.” 节点具有不同的着色器;
  • “SRP: Node use multi-pass shader” 节点使用了多Pass着色器;
  • “SRP: Node use different shader keywords” 节点使用了不同的着色器关键字;
  • “SRP: End of the batch flush” Batch Flush结束;
  • “SRP: Node is not compatible with SRP batcher” 节点与SRP Batcher不兼容;
  • “SRP: Node material requires device state change” 节点材质需要改变渲染设备状态 ;
  • “SRP: First call from ScriptableRenderLoopJob” ScriptableRenderLoopJob第一次调用;
  • “SRP: This material has custom buffer override” 材质有自定义重写的Buffer。

本文整理自:Metaverse大衍神君《Unity性能优化》

http://www.dtcms.com/a/390664.html

相关文章:

  • react+andDesign+vite+ts从零搭建后台管理系统
  • No007:构建生态通道——如何让DeepSeek更贴近生产与生活的真实需求
  • 力扣Hot100--206.反转链表
  • Java 生态监控体系实战:Prometheus+Grafana+SkyWalking 整合全指南(三)
  • 生活琐记(3)
  • 在 Elasticsearch 和 GCP 上的混合搜索和语义重排序
  • 借助Aspose.HTML控件,使用 Python 将 HTML 转换为 DOCX
  • 设计测试用例的万能公式
  • 黑马头条_SpringCloud项目阶段三:HTML文件生成以及素材文章CRUD
  • 精准模拟,实战赋能-比亚迪秦EV整车检测与诊断仿真实训系统
  • 学习路之PHP--生成测试数据:fakerphp的使用
  • 《UE5_C++多人TPS完整教程》学习笔记54 ——《P55 旋转根骨骼(Rotate Root Bone)》
  • go资深之路笔记(五)用系统信号实现优雅关机
  • C++实战㉔】解锁C++ STL魔法:list与deque实战秘籍
  • Linux 系统指令——助力信奥初赛
  • LVS详解:构建高性能Linux负载均衡集群
  • 【Linux网络编程】网络层协议-----IP协议
  • 电池AH的定义与WH关系
  • 谙流 ASK 技术解析(四):负载均衡引擎
  • 乾元通渠道商中标国家华中区域应急救援中心应急救援装备采购项目
  • 网络原理补充——NAT/NAPT、代理服务、内网穿透、交换机
  • 深入 HTTP 协议:剖析 1688 商品详情 API 的请求构造与签名机制
  • 共用体union和大小端模式
  • 2022年下半年 系统架构设计师 案例分析
  • LeetCode 面试经典 150_哈希表_有效的字母异位词(42_242_C++_简单)
  • go webrtc - 3 工程演示
  • JVM(五)-- 执行引擎
  • 微算法科技(NASDAQ:MLGO)量子架构搜索技术:突破变分量子算法性能瓶颈,实现量子计算的鲁棒优化
  • 海亮科技亮相第十一届亚教展,“教育 + AI”赋能县域教育振兴
  • JMeter的配置元件