URP平面阴影合批处理 shadow

闲谈

相信大家在日常工作中发现了一个问题 , urp下虽然可以做到3个Pass 去写我们想要的效果,但是,不能合批(不能合批,那不是我们CPU要干冒烟~!)

好家伙,熊猫老师的偏方来了 ,教大家如何在URP渲染管线下做到多pass也能合批,干货满满。

一:合并公共预设

方便我们多Pass状态下 ,更快的实现,也能让代码更加专业。

如图所示:

我们在Subshader下用 HLSLINCLUDE 和 ENDHLSL 去实现。

其次 咱们在第二个Pass "影子渲染pass"里面添加Tags 并对LightMode 复制渲染层为 "XiongMaoWuDao"

如图所示:

复制代码
   Pass
        {

		Name "XiongMaoWuDao"
		Tags{
	   
	    	"LightMode" = "XiongMaoWuDao"
		}

二:URP Add Renderer Feature

如图步骤:

添加Renderer Feature 设置如下:

好了,现在我们来看看多物件下影子Pass是否合批。

上才艺:

复制代码
Shader "XiongMaoWuDao/Shadow"
{
    Properties
    {
	    
	    [MainColor] _BaseColor("BaseColor", Color) = (1,1,1,1)
        [MainTexture] _BaseMap("BaseMap", 2D) = "white" {}
	    //影子处理
		//影子淡出处理
        _ShadowColor("Color", Color) = (0, 0, 0, 1)
        _LightDir ("Light Direction", Vector) = (0, 1, 0, 0)
        _PlaneY ("Plane Height", Float) = 0	
		_ShadowFalloff ("ShadowFalloff ",Range (0,1)) = 0.5

    }
    SubShader
    {
		Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "Queue" = "Opaque"}
	  HLSLINCLUDE
		  #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

	         TEXTURE2D(_BaseMap);
             SAMPLER(sampler_BaseMap);

           CBUFFER_START(UnityPerMaterial)
		
            float4 _BaseMap_ST;
            half4 _BaseColor;
		    float4 _ShadowColor;
            half3 _LightDir;
			half _PlaneY;
			half _ShadowFalloff;

            CBUFFER_END
        ENDHLSL

		pass 
		{
			Name "Forward"
       
            Tags {
		  
			}
		  HLSLPROGRAM
		    #pragma vertex vert
            #pragma fragment frag
		    #pragma multi_compile_instancing
			  struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				 UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;   
                float4 vertex : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

			   v2f vert (appdata v)
            {
                v2f o;
				  UNITY_SETUP_INSTANCE_ID(v);
				  UNITY_TRANSFER_INSTANCE_ID(v, o);
                o.vertex = TransformObjectToHClip(v.vertex.xyz);;
                o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
           
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                 UNITY_SETUP_INSTANCE_ID(i);
             return SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv) * _BaseColor;
            }
	
			ENDHLSL
		}
        Pass
        {

		Name "XiongMaoWuDao"
		Tags{
	   
	    	"LightMode" = "XiongMaoWuDao"
		}
		//添加模板缓冲区是解决影子重叠问题(降低透明度就能发现)
		  Stencil
    {
        Ref 1  //和模板缓冲区的值进行比较。
        Comp NotEqual   //比较函数, 决定参考值和模板缓冲区的值如何比较 (是否相等) NotEqual
        Pass Replace   //模板测试通过时候的操作 。  Replace 模板缓冲区中的值设为参考值。Replace
        Fail Keep    //模板测试失败时候的操作 。    keep是保持缓冲区当前的值
		//ZFail Keep  
		
    }
		Blend SrcAlpha OneMinusSrcAlpha
		//	ZWrite off
       //     Offset -1 , 0
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
		
      
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;   
                float4 vertex : SV_POSITION;
		    	float4 color : COLOR;
            };
		

			  //阴影方向计算。
        float3 PlanarShadowPos(float3 posWS)
        {
          float3 L = normalize(_LightDir);
          float3 N = float3(0, 1, 0);

          float d1 = dot(L, N);
          float d2 = posWS.y - _PlaneY;

          // 阴影坐标沿法线方向偏移一点,防止与平面重叠时出现z-fighting的问题
          float3 offsetByNormal = N * 0.001;
          return posWS - L * (d2 / d1) + offsetByNormal;

          }


            v2f vert (appdata v)
            {
                v2f o;
				 // 顶点坐标,转世界坐标
                float3 posWS = TransformObjectToWorld(v.vertex.xyz);
               // 世界顶点坐标转为平面坐标
                posWS = PlanarShadowPos(posWS);
                o.vertex = TransformWorldToHClip(posWS);
                o.uv =v.uv;         
		
			   //得到中心点世界坐标
		    	float3 center = float3(unity_ObjectToWorld[0].w,  _PlaneY, unity_ObjectToWorld[2].w);
		    	//计算阴影衰减
				float falloff = 1 - saturate(distance(posWS, center) * _ShadowFalloff);
 
			   	o.color = _ShadowColor;
				o.color.a *=falloff;
                return o;
            }



            half4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDHLSL
        }

  }}

能看见我在场景中做了4个材质球且用了不同的贴图,但是 能看见第一个pass对颜色渲染已经合批成一个了(除了地面用了默认的材质球外,忽略)。 第二个Pass影子也全部合并成一个渲染层渲染,完美解决问题。 鼓掌~~~!

相关推荐
ellis19702 小时前
Unity插件SafeArea Helper适配异形屏详解
unity
nnsix3 小时前
Unity Physics.Raycast的 QueryTriggerInteraction枚举作用
unity·游戏引擎
地狱为王3 小时前
Cesium for Unity叠加行政区划线
unity·gis·cesium
小贺儿开发12 小时前
Unity3D 八大菜系连连看
游戏·unity·互动·传统文化
在路上看风景12 小时前
25. 屏幕像素和纹理像素不匹配
unity
ۓ明哲ڪ14 小时前
Unity功能——创建新脚本时自动添加自定义头注释
unity·游戏引擎
熬夜敲代码的小N14 小时前
Unity大场景卡顿“急救包”:从诊断到落地的全栈优化方案
java·unity·游戏引擎
派葛穆15 小时前
Unity-realvirtual-S7通讯快速配置(未完结)
unity·游戏引擎
w-白兰地1 天前
【Addressable远端加载资源】
unity·addressable·资源加载
小张不爱写代码1 天前
[Unity 技巧] 如何自定义 Inspector 变量显示名称 (CustomLabel)
unity·游戏引擎