Unity的URP下使用SRPBatcher

大家好,我是阿赵。这里继续来讲一下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。

猜你喜欢

转载自blog.csdn.net/liweizhao/article/details/130716036