大家好,我是阿赵。这里继续来讲一下URP相关的东西。
这次主要说的是SRP Batcher的使用
一、在URP下实现SRP Batcher
1、设置
在我们创建的URPAsset文件的高级选项里面,有一个SRP Batcher的开关,默认就是勾上的。
2、修改shader
在把项目转换为URP后,会看到shader属性里面出现了SRP Batcher的项
如果是自己写的shader,在没有做处理之前,SRP Batcher项会是not compatible,也就是没有适配,下面有提示:Material property is found in another cbuffer than “UnityPerMaterial”(_MainTex_ST)
根据提示,可以知道是cbuffer的问题,所以要对shader做一点小修改
主要的修改地方:
把shader内部使用的变量用CBUFFER_START(UnityPerMaterial)和CBUFFER_END包住。注意这里内部使用的变量,是指在Properties里面声明了,并且在顶点或者片段程序里面再用到的变量,不包括global的全局变量。
增加完之后,再看shader的属性,会发现SPR Batcher项已经变成了compatible,也就是说该shader已经适配了SRP Batcher了
例子:
CG:
Shader "azhao/CGBatch"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
CBUFFER_START(UnityPerMaterial)
sampler2D _MainTex;
float4 _MainTex_ST;
CBUFFER_END
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
HLSL:Unity的URP是推荐使用HLSL的,因为这个例子先是用CG写的,后来改成HLSL,所以有些地方不太符合HLSL。之后有机会再说一下为什么要用HLSL。
Shader "azhao/HLSLBatch"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
CBUFFER_START(UnityPerMaterial)
sampler2D _MainTex;
float4 _MainTex_ST;
CBUFFER_END
v2f vert (appdata v)
{
v2f o;
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
o.pos = mul(unity_MatrixVP, worldPos);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
half4 frag (v2f i) : SV_Target
{
// sample the texture
half4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDHLSL
}
}
}
3、渲染效果
我这里渲染2000颗草的模型,可以看到,Saved by batching居然变成了负数。这是因为Statistics分析的数据是普通渲染管线的,它对URP的实际数据识别得有问题。不过出现负数,就证明SRP Batch已经生效了
二、多种渲染方式的对比
还是渲染2000棵草,下面对比一下Unity的多种渲染合并方式下的情况,我顺便用Frame Debug工具给大家看看实际合并渲染的情况。至于哪一种方式的性能更好,各位可以自己去看看参数了。
1、不合并
可以看到,动态Batches高达2001
从Frame Debug里面看,可以看出渲染的次数非常多
2、静态合并
把所有物体勾选上Batching Static,然后渲染
出现了颜色变亮了的问题,不过Batches变成了12了,有1989个合并被保存起来了。
从Frame Debug看,渲染的次数明显的减少了,总共渲染11次,而每一次的渲染,名称就叫做Static Batch
3、GPU Instancing
在GPU Instancing和静态合并同时勾选时,会优先静态合并,所以不要两者同时使用
GPU Instancing之后,Batches变成了9,有1992个合并被保存起来了。
从Frame Debug看,总共渲染了8次,每次的名字变成了Draw Mesh(Instanced)
4、SRP Batcher
这里显示问题就不去深究了
从FrameDebug看,同样的渲染了8次,每次的名字就叫SRP Batch。