3.7 SRP Batcher

1.传统渲染模式(非 SRP Batcher)的处理方式

2.SRP Batcher 的处理方式

3.如何开启SRP Batcher

4.SRP Batcher的使用限制


1.传统渲染模式(非 SRP Batcher)的处理方式

csharp 复制代码
在传统模式下, "材质参数是否不同"是判断"是否需要切换渲染状态"的核心依据, 哪怕只是同一个Shader的不同材质实例(

参数不同), CPU都会做大量重复的状态切换工作; 非SRP Batcher的处理方式:

a.渲染状态的判定标准: 传统模式中, "材质实例"是渲染状态的核心标识 ------ 每个不同的材质实例(哪怕仅参数不同),都会被

视为"不同的渲染状态"

b.具体处理流程(以3个物体为例: Shader相同, 材质A/材质B/材质C, 参数分别为颜色红/绿/蓝)

- CPU处理物体1: 设置材质A的所有参数(纹理、颜色红、Shader变体等) -> 提交Draw Call -> 绘制物体1

- CPU处理物体2: 先清空/切换材质A的状态 -> 设置材质B的所有参数(纹理、颜色绿、Shader变体等) -> 提交Draw Call -> 

绘制物体2

- CPU处理物体3: 再清空/切换材质B的状态-> 设置材质C的所有参数(纹理、颜色蓝、Shader变体等) → 提交Draw Call → 

绘制物体3

c.最终结果

产生3次Draw Call(物体数 = Draw Call 数)

核心开销: "CPU反复切换材质状态(每次切换都要向GPU重新传递所有材质参数), 这是最大的性能损耗点"

2.SRP Batcher 的处理方式

csharp 复制代码
SRP Batcher的核心优势就体现在"区分参数类型" ------ 哪怕材质参数不同, 只要这些差异属于"Per-Object(每个物体)数据",

就能大幅减少状态切换

第一步: 先判断"参数差异的类型"

SRP Batcher会把材质参数分为两类, 这是处理的关键
csharp 复制代码
第二步: 具体处理流程(同上面3个物体的例子: Shader相同, 仅颜色参数不同)

a.预处理阶段

CPU提前将该Shader对应的Per-Material公共数据(比如纹理、高光强度)打包, 一次性上传到GPU的常量缓冲区并缓存 ------ 这

一步只做1次

b.绘制阶段

- CPU为这3个物体仅设置1次Shader/Per-Material 公共状态(无需反复切换)

- 仅为每个物体更新Per-Object数据(颜色红/绿/蓝、各自的世界矩阵), 这些数据会被批量组织成连续内存块上传

- 最终批量提交这3个物体的绘制指令(仅1次核心的状态设置, 后续仅更新可变参数)

c.最终结果

产生1次"有效状态切换" + 3次轻量级的Draw Call(仅更新 Per-Object 数据)

核心开销: 几乎消除了"Shader/材质公共状态"的切换成本, 仅保留少量Per-Object数据的更新开销(远低于传统模式)
csharp 复制代码
例外情况: 若参数差异是Per-Material类型

如果材质参数的差异是"Per-Material级"的纹理, 那么SRP Batcher会将它们分为不同的组

- 用纹理A的物体归为组1, 用纹理B的归为组2

- 组1: 1次状态设置 + 组内物体批量绘制

- 组2: 1次状态设置 + 组内物体批量绘制

- 相比传统模式, 仍能减少组内的状态切换开销(比如组1有10个物体, 传统模式10次切换, SRP Batcher仅1次)

3.如何开启SRP Batcher

csharp 复制代码
在Unity2021后, 在SRP管线(URP、HDRP)中该功能默认开启, 不允许关闭了; 之前的版本中可以在URP Asset中的Inspector窗

口勾选开启, 观察SRP Batcher是否工作,只需要用Frame Debugger查看渲染事件是否为SRP Batch即可
csharp 复制代码
优先级问题

a.内置渲染管线中: 静态批处理 > GPU Instancing > 动态批处理 > 单独绘制

b.SRP管线中: 静态批处理 > SRP Batcher > GPU Instancing > 单独绘

4.SRP Batcher的使用限制

csharp 复制代码
1).对象使用的Shader必须与SRP Batcher兼容

在HDRP和URP中, 所有Lit Shader和Unlit Shader都符合这一要求(除了它们的粒子版本); 若要让一个自定义Shader与SRP

Batcher兼容, 它必须满足以下要求

a.Shader必须将所有引擎内置属性声明在一个名为UnityPerDraw的常量缓冲区里

b.Shader必须将所有材质属性声明在一个名为UnityPerMaterial的常量缓冲区里
csharp 复制代码
- 引擎内置属性是Unity引擎自动为每个渲染物体生成、管理的属性, 不是你在Shader里自定义的, 也没法在材质面板手动调

整, 这些属性的核心特点是: 每个物体独有、随物体变化(比如"物体的位置/旋转/缩放对应的矩阵")

- 材质属性是你在Shader里自定义的、可以在材质面板手动调整的属性,核心特点是: 同一材质的所有物体共用、不随物体变

化(比如一个红色材质, 所有用它的物体都是红色)

csharp 复制代码
2).对象不能使用MaterialPropertyBlocks, MaterialPropertyBlock 是一个特殊的容器, 用来在不复制材质的情况下,给

某个物体单独设置材质参数

3).对象不能是粒子

对象需要是MeshRenderer或SkinnedMeshRenderer(注意: 蒙皮网格渲染器在新版本支持, 2019之前不支持)
相关推荐
快乐觉主吖2 小时前
Unity方便修改产品名和包名的小工具
unity·游戏引擎
JIes__14 小时前
Unity(二)——MonoBehavior中的重要内容
unity·游戏引擎
4Forsee1 天前
【增强现实】快速上手 Vuforia Unity Android AR 应用开发
android·unity·ar
两水先木示1 天前
【Unity】对指定物体进行描边——模板测试法
unity·游戏引擎·shader·外描边
Miss_SQ1 天前
实现Unity录音、百度云语音转文字
unity·语音识别
CreasyChan1 天前
unity 对象池实测可用
unity·c#
weixin_424294671 天前
Unity项目的Artifacts文件夹过大怎么解决?
unity·游戏引擎
没事写写笔记2 天前
Unity HDRP14.0.12 Volume 配置参数
unity
红黑色的圣西罗2 天前
手游手动异形屏适配方案,类“明日方舟”
unity