Unity 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影子也全部合并成一个渲染层渲染,完美解决问题。 鼓掌~~~!

相关推荐
charon877821 分钟前
UE ARPG | 虚幻引擎战斗系统
游戏引擎
小春熙子1 小时前
Unity图形学之Shader结构
unity·游戏引擎·技术美术
Sitarrrr4 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
极梦网络无忧4 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
逐·風12 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
_oP_i13 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
代码盗圣17 小时前
GODOT 4 不用scons编译cpp扩展的方法
游戏引擎·godot
Leoysq1 天前
【UGUI】实现点击注册按钮跳转游戏场景
游戏·unity·游戏引擎·ugui
PandaQue1 天前
《潜行者2切尔诺贝利之心》游戏引擎介绍
游戏引擎
_oP_i1 天前
unity中 骨骼、纹理和材质关系
unity·游戏引擎·材质