Unity 性能优化 之 非常酷的SRP Batcher!

概述

做Unity性能优化,减少Draw Calls是最头疼的事。

既然用到了URP管线,那么在做渲染优化的时候,就需要针对URP管线做相应的优化。

今天发现了除了动态batching和静态batching以外的一个非常酷炫的batching,那就是SRP Batching。

因为动态batching限制较多,包括模型顶点不能超过300个,shader的顶点属性不能超过900个(假如你的vertex shader用到了vertex position,normal,一个uv,那300个顶点*3 = 900,这样计算的),并且材质和贴图得必须一致,还不能用材质的copy等等。

其中模型顶点数量限制这个就很无解了,我们项目的模型顶点动辄就超过500到一千,那么做动态batching就是天方夜谭。

但是draw calls数量太多了,还是得想办法呀。皇天不负有心人,终于让我发现了SRP Batching。

这是我没有做SRP Batching之前,在Frame Debugger的状况:

我的天,单单是渲染阴影就用了100个draw calls。

甚至还提示无法batching的原因是:

 "Dynamic Batching is turned off in Player Settings or is disabled temporarily in the current context to avoid z-fighting".

一头雾水的报错,因为pipelineAsset里确实勾选了Dynamic Batching。不过放心,下面的SRP Batching会解决这个问题。

渲染Opaque(不透明物体)13个。

渲染Transparents(半透明物体)93个!总共100+13+93 = 206个draw calls!

SetPass calls到达196。

具体实现

首先在Pipeline Asset里勾选SRP Batcher。

接着,得让我们的shader是SRP compatible(符合SRP的)的。

前提是我们修改的shader是支持URP管线的,具体怎么让shader支持URP管线可以参阅我之前的博客。

非常重要的步骤就是加入CBUFFER,例如:

CBUFFER_START(UnityPerMaterial)
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
CBUFFER_END

UnityPerMaterial的意思是在 Properties大括号里声明的所有变量,如下方的_Color和_MainTex变量:

Properties
{
	_Color("与主贴图正片叠底的颜色", Color) = (1,1,1,1)
	_MainTex("主贴图", 2D) = "white" {}
}

所以注意,不要加入Properties以外的属性变量。否则会报

"unitypermaterial var is not declared in shader property section"的错。

一般加入CBUFFER,并生效的话,SRP就compatible了。

然后我们来打开Frame Debugger来看看Batching的情况:

我的天,Transparents(半透明物体)的draw calls从93个跌到了11个!简直是魔法!

渲染Opaque(不透明物体)的从13跌倒了2个!

ShaderCaster阴影的SRP Batching

如果你的shader有用到ShaderCaster来实现阴影的话。以下的代码可以直接用来使阴影的SRP Batching生效。

pass {
			Name "ShadowCast"

			Tags{ "LightMode" = "ShadowCaster" }
			HLSLPROGRAM

			#pragma vertex ShadowPassVertex
			#pragma fragment ShadowPassFragment

			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

			CBUFFER_START(UnityPerMaterial)
			CBUFFER_END

			struct Attributes
			{
				float4 positionOS   : POSITION;
				float3 normalOS     : NORMAL;
			};

			struct Varyings
			{
				float4 positionCS   : SV_POSITION;
			};

			Varyings ShadowPassVertex(Attributes input)
			{
				Varyings output;

				float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
				float3 normalWS = TransformObjectToWorldNormal(input.normalOS);

				float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _MainLightPosition.xyz));
				output.positionCS = positionCS;
				return output;
			}
			half4 ShadowPassFragment(Varyings input) : SV_TARGET
			{
				return 0;
			}
			ENDHLSL
}

 同样打开打开Frame Debugger来看看Batching的情况:

 Unity 性能优化 之 非常酷的SRP Batcher!_第1张图片

我的天,draw calls从100个跌到了10个!酷毙了!

最终,SetPass calls从196优化到109个。

参考文章:

https://zhuanlan.zhihu.com/p/137455866

https://zhuanlan.zhihu.com/p/156858564

https://blogs.unity3d.com/2019/02/28/srp-batcher-speed-up-your-rendering/

你可能感兴趣的:(shader,Unity,渲染,shader,unity,srp)