URP 渲染实战 / 第 29 章 性能优化 / 案例 29.1
案例 29.1合批友好的 Shader 与反例入门
目标:写一个同时兼容 SRP Batcher、GPU Instancing 和 LOD Cross-Fade 的最小 Shader,再写一个反例,学会在编辑器里验证。
Assets/Cookbook/Ch29/BatcherFriendly.shader(节选:cbuffer)
TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); // SRP Batcher:每个材质一份常量缓冲,布局在所有变体里必须一致 CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; CBUFFER_END // GPU Instancing:允许用 MaterialPropertyBlock 逐实例覆盖颜色 UNITY_INSTANCING_BUFFER_START(PerInstance) UNITY_DEFINE_INSTANCED_PROP(half4, _InstanceColor) UNITY_INSTANCING_BUFFER_END(PerInstance)
反例只差一行——属性声明在 CBUFFER 之外:
Assets/Cookbook/Ch29/BatcherBreaker.shader(节选:bad)
逐实例颜色通过 MaterialPropertyBlock 设置:
Assets/Cookbook/Ch29/PerInstanceTint.cs(节选:apply)
如何验证:
- 在 Project 窗口选中 Shader,Inspector 里会显示 SRP Batcher: compatible 或 not compatible,不兼容时附带原因。上面的反例会提示类似 Material property is found in another cbuffer than "UnityPerMaterial";如果不同 Pass 的 UnityPerMaterial 内容不一致,原因是 UnityPerMaterial CBuffer inconsistent size inside a SubShader。
- 打开 ,Enable 后展开 DrawOpaqueObjects。兼容的物体会被归入名为 SRP Batch 的事件,选中后右侧会说明这一批为什么没能和上一批合并,例如 SRP: Node have different shaders.、SRP: Node use different shader keywords、SRP: Node is not compatible with SRP batcher、SRP: Node use multi-pass shader。
- 对非 SRP Batcher 的绘制(Instancing、静态/动态合批),Frame Debugger 同样会给出不能合批的原因,常见的有 Objects have different materials.、Objects have different MaterialPropertyBlock set.、Objects are affected by different light probes.、Objects are lightmapped. 等。
提示“同一 Shader 变体”是 SRP Batcher 连续合批的关键。材质之间关键字不同(例如一个开了
_NORMALMAP、一个没开)会让它们落到不同变体,Frame Debugger 里就会看到 Node use different shader keywords。整理材质、统一关键字,往往比改 Shader 更能提升合批效果。另外,URP 的不透明物体排序是“由近到远”优先的(支持隐藏面消除的 GPU 上会放宽,见 CameraData.defaultOpaqueSortFlags 的注释),排序也会打断同 Shader 的连续性。