unity性能优化之批处理的优势

在某些情况下,批处理的对象指的是网格、顶点、边、UV坐标和其他用于描述3D对象的不同数据类型的大集合,当然该术语也可以简单的代表批处理音频文件、精灵、纹理文件和其他大数据的集合

批处理的两种形式

  1. 静态批处理
  2. 动态批处理
    这两种方法的最本质区别就是集合体合并的两种不同的形式,用于将多个对象的网格数据合并到一起,并且在单一的指令中去渲染他们,而不是单独准备和回值每个几何体。
为什么可以将多个网格进行批处理成单一的网格?

Unity中并没有规定网格对象必须是3D空间中的连续集合体,并且,Rendering pipeline(渲染管线)可以接受一系列没有公共边的顶点,由此,可以将原本需要多个渲染指令的多个独立网格合并成单个网格,然后使用单一指令来渲染它;

DrawCall

什么是DrawCall?说的通俗一点就是,从CPU发送到GPU的请求,指令

为什么进行了批处理就可以提高性能呢?

在CPU向GPU发送一个DrawCall命令,进行渲染之前,需要做一些工作

  1. 网格和纹理等数据必须从CPUneicun (RAM)推送到 GPU内存(VRAM)中,这种情况一般发生在场景初始化的时候,前提是当前场景文件知道的纹理于网格,如果使用非场景中的纹理和网格,那么必须在他们实例化时完成加载。
  2. 然后CPU必须要配置对象(这些对象就是DrawCall的目标)所需要的渲染特性,为GPU做准备
  3. 在渲染对象之前,必须要为渲染管线而配置的大量设置统称为渲染状态,除非这些状态发生了改变,否则GPU将会为所有传入的对象保持相同的状态,并且以类似的方式去渲染他们
  4. 更改渲染状态是一个非常耗时的事情,这也就是为什么减少DrawCall会提高性能的原因,比如,如果将渲染状态设置为使用一个蓝色纹理温江,然后要求它去渲染一个大的网格,那么他的速度是很快的,但是如果使用十种不同的纹理去渲染十个网格,将花费更长的时间,这是因为在为每隔网格发送DrawCall之前,都需要使用新的纹理来准备渲染状态,用于渲染当前对象的纹理在GraphicsAPI中实际上是一个全局变量,在并行系统内修改全局变量起始是比较难的,在GPU这样的大规模系统中,实际上必须在修改渲染状态之前一直等待,直到所有的作业都达到一个同步点为止,到达同步点之后,在重新启动所有作业,这样就会浪费很多时间,这也就是为什么DrawCall次数越少,性能越好的原因,那么如果进行了批处理,将很多单个的网格合并成一个网格的话,只需要一次DrawCall,渲染状态也不需要发生变化,直接去渲染剩下的网格就行了,这样就节省了很多时间,也减少了CPU、GPU上的工作负载;

材质和着色器

在Unity中,渲染状态的本质上是通过材质呈现给开发者的,材质是着色器的容器,着色器是一种定义GPU该如何进行渲染的简短程序
每隔着色器都需要一个材质,而每个材质都必须要有一个着色器;
因此,如果想要最小化渲染状态修改的频率,可以减少场景中使用的材质数量,这将在两个方面同时提高性能,CPU将花费更少的时间生成指令,传输给GPU,GPu不需要经常停止,重新同步状态的变更;

FrameDebugger

打开方式 window->FrameDebugger

测试
首先把ProjectSetting->Quality的shadows设置为DisableShadow
在这里插入图片描述
然后Editor->project Setting->Player 禁用StaticBatching和DynamicBatching ,这些会产生额外的DrawCall不方便观察

在场景中创建三个Cube,打开FrameDugger
在这里插入图片描述

左边面板的每一项后面的数字代表一个GraphicsAPI的调用,其中c一个DrawCall是用来清楚屏幕的(Clear),接着三个不同的DrwaCall(RenderForward.RenderLoopJob),右侧是详细信息

动态批处理

优势:

  1. 批处理在运行时生成
  2. 批处理中包含的对象在不同帧中可能有所不同,这取决于那些网格在摄像机中可见
  3. 甚至在场景中可以运动的对象也可以进行批处理
首先打开批处理

PlayerSetting开启DynamicBatching
有的时候,即使打开了动态批处理,也不会自动把多个DrawCall合并
在这里插入图片描述
但是有的时候又可以
在这里插入图片描述

这是因为动态批处理还是有很多限制条件的,如下

  1. 所有网格必须使用相同的材质引用
  2. 只有ParticleSystem和MeshRender组件进行动态批处理,SkinnedMeshRenderer组件和其他可渲染的组件不能进行批处理
  3. 每个网格的顶点至多有300个
  4. 所有网格实例要么使用等比缩放,要么使用非等比缩放,不能二者兼得
  5. 网格实例应该引用相同的光照纹理文件
  6. 材质的着色器不能依赖多个过程
  7. 网格实例不能接受实时阴影
  8. 整个批处理中网格索引总数有上限,这与平台有关系
  9. 着色器使用的顶点属性总数小于900的网格才会进行动态批处理

首先来说一下什么是顶点属性:
所谓的顶点属性包括但是不限于顶点位置,法线向量,一套或者多套纹理的UV坐标,甚至可能包括每个顶点的颜色信息;也就是说,如果每个顶点使用的属性数据越多,那么900个顶点属性的预算就越少,也就是变相的减少了网格所哟能拥有的顶点数量,打个比方,如果每个顶点所用到的属性有三个,那么能够动态批处理的的网格就要求顶点个数最多300个,如果是5个属性,那么就要求不能超过180个;
那么在unity中球的默认顶点个数包含515个顶点,每个顶点默认有24个属性,总共1545个顶点属性,超过900,因此上面的那几个球体不能进行批处理

网格缩放的要求:
举例说明, 假设有四个对象,A(1,1,1)缩放,B(2,1,1)缩放 ,C(2,2,1)、D(2,2,2),那么A和D是等比缩放,BC都不是等比缩放,因此,AD会自动放在一个批处理中,BC自动放在一个批处理中;另外一个情况,只有当缩放比例出现负数的时候才会出现,当缩放比例中出现符数,那么能否放在一个批处理还和渲染顺序有关;

静态批处理

要求:

  1. 网格必须被标记为Static
  2. 每个静态批处理的网格都需要额外的内存
  3. 合并到静态批处理中的顶点数量有上限,并且会随着平台的不同而改变,一般为32-64K
  4. 网格的实例可以来自任何网格数据,但是必须使用相同的材质引用
Static标记

在这里插入图片描述

静态批处理静态批处理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值