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之前不支持)
相关推荐
山檐雾8 小时前
OctreeNode
unity·c#·八叉树
WarPigs10 小时前
Unity协程返回值的解决方案
unity·游戏引擎
WarPigs14 小时前
Unity单例笔记
unity·游戏引擎
Allen74742 天前
ComfyUI 自动化生产 3D资产 工作流笔记
图像处理·opencv·unity·自然语言处理·3d模型生成·confyui
nnsix2 天前
Unity Windows11 打字中文显示不出来输入法的候选框
unity
adogai2 天前
unity mcp接入 实现一句话生成游戏!
游戏·unity·游戏引擎
mxwin2 天前
Unity Shader 逐像素光照 vs 逐顶点光照性能与画质的权衡策略
unity·游戏引擎·shader·着色器
CDN3602 天前
游戏盾导致 Unity/UE 引擎崩溃的主要原因排查?
游戏·unity·游戏引擎
mxwin2 天前
Unity URP 全局光照 (GI) 完全指南 Lightmap 采样与实时 GI(光照探针、反射探针)的 Shader 集成
unity·游戏引擎·shader·着色器
mxwin2 天前
Unity URP 溶解效果基于噪声纹理与 clip 函数实现物体渐隐渐显
unity·游戏引擎·shader