参考:Unity MaterialPropertyBlock 正确用法(解决无法合批等问题)_costa100的专栏-CSDN博客
Instancing and Material Property Blocks | Ronja's tutorials?
Unity SRP Batcher的工作原理_zakerhero的博客-CSDN博客?
?SRPBatcher&GPUInstancing_汤姆猫X的博客-CSDN博客
?一、MaterialPropertyBlock(MPB) :属性块,用法:
MaterialPropertyBlock?mpb = new?MaterialPropertyBlock();//最好全局唯一静态对象
Render(MeshRenderer、SpriteRenderer).GetPropertyBlock(mpb);
mpb.SetFloat(...)//类似material.SetFloat使用
Render(MeshRenderer、SpriteRenderer).SetPropertyBlock(mpb);
这种使用方法与直接material区别是不会产生新的材质实例对象,而是会产生一个新的存储区域在CPU,它配合GPU Instancing使用,因为GPU Instancing要求同网格同材质,而且不支持SRPBatch(凡是使用MPB的则不可能生效SRPBatch,理由是SRPBatch必须所改动属性都在GPU的CBuffer中,不然会打破Batch)
二、GPU Instancing:GPU实例,条件:同网格(mesh)同材质实例(即一个网格一个材质实例),它可以批处理所有相同网格相同材质实例的物体,其中shader伪代码如下:(加粗部分是重点) Pass{ CGPROGRAM ... #pragma multi_compile_instancing
顶点输入结构体 { ... UNITY_VERTEX_INPUT_INSTANCE_ID } 顶点输出结构体(片段着色器输入结构体) { ... UNITY_VERTEX_INPUT_INSTANCE_ID } UNITY_INSTANCING_BUFFER_START(Props) //Props是BUFFER块名称访问时使用到 ????????//属性块里的属性全部类似写到这里 ????????UNITY_DEFINE_INSTANCED_PROP(类型, 变量名) ????????UNITY_DEFINE_INSTANCED_PROP(类型, 变量名) UNITY_INSTANCING_BUFFER_END(Props) 顶点着色器函数(v) { ? ? ? ? 输出结构体?o; ? ? ? ??UNITY_SETUP_INSTANCE_ID(v); ????????UNITY_TRANSFER_INSTANCE_ID(v, o); } 片段着色器函数(i) { ????????UNITY_SETUP_INSTANCE_ID(i); ? ? ? ? 类型 value =?UNITY_ACCESS_INSTANCED_PROP(Props, 变量名); //访问Props块的变量(即MPB传递过来的变量) }
三、SRPBatch:可编程渲染管线批处理,条件:URP、HDRP、自定义RP环境下,能加速CPU处理同shader且相同变体的物体(即使不同材质或不同材质实例都可以加速),加速的是CPU准备设置属性的时间,因属性都会被直接存储在GPU的CBuffer中,如果材质的属性没有变化,就不会进行去花费时间设置属性,从而节省DrawCall时间,但DrawCall数量是不变的。 注意:不能使用MaterialPropertyBlock去设置属性,因为MPB会设置的属性产生新的存储空间存储而不是存储到GPU的CBuffer中,从而打断SRPBatch。
需引入:#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" ?? ??? ??? ?#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl" 同理所有CGPROGRAM ENDCG改成HLSLPROGRAM ENDHLSL并且sampler2D改TEXTURE2D(_MainTex),额外增加一个采样器SAMPLER(sampler_MainTex),采样使用half4 color = _MainTex.Sample(sampler_MainTex, uv); 重点是将所有Properties块内的属性全部放到 CBUFFER_START(UnityPerMaterial) ? ? ? ? float4 xxx; CBUFFER_END 在Shader界面能看见SRP Batch compiled就代表会支持SRP Batch了。
|