Built-in转URP Chapter9(2)-多光源阴影

话不多说,直接上代码,具体区别我后边会补充上,

暂时委屈各位,先锻炼下自己的“找不同”的能力,哈哈:

Built-CG写法:

Shader "Unity Shaders Book/Chapter 9/Shadow" {
	Properties {
		_Diffuse("Diffuse Color", Color) = (1,1,1,1)
		_Specular("Specular Color", Color) = (1,1,1,1)
		_Gloss("Gloss", Range(10, 256)) = 10
	}

	SubShader {
		Tags {"RenderType"="Opaque"}

		Pass {
			Tags {"LightMode"="ForwardBase"}

			CGPROGRAM
			#include "Lighting.cginc"
			#include "AutoLight.cginc"

			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase

			fixed4 _Diffuse;
			fixed4 _Specular;
			fixed _Gloss;

			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldPos : TEXCOORD0;
				float3 worldNormal : TEXCOORD1;

				// #define SHADOW_COORDS(idx1) unityShdowCoord4 _ShadowCoord : TEXCOORD##idx1;
				// 注意此处没有分号 ';' 
				SHADOW_COORDS(2)
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);

				// #define TRANSFER_SHADOW(a) a._ShadowCoord = mul(unity_WorldToShadow[0], mul(_Object2World, v.vertex));
				TRANSFER_SHADOW(o);

				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb;
				fixed3 halfDir = normalize(viewDir + lightDir);

				fixed atten = 1.0;
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);

				fixed shadow = SHADOW_ATTENUATION(i);

				return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);
			}

			ENDCG
		}

		Pass {
			Tags {"LightMode"="ForwardAdd"}

			CGPROGRAM

			#include "Lighting.cginc"
			#include "AutoLight.cginc"

			#pragma vertex vert
			#pragma fragment frag
			// #pragma multi_compile_fwdadd
			#pragma multi_compile_fwdadd_fullshadows

			fixed4 _Diffuse;
			fixed4 _Specular;
			fixed _Gloss;

			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				SHADOW_COORDS(2)
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				TRANSFER_SHADOW(o);

				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
				#ifdef USING_DIRECTIONAL_LIGHT
					fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
				#else
					fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos);
				#endif

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb;
				fixed3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(halfDir, worldNormal)), _Gloss);

				// fixed atten = 1.0;

				#ifdef USING_DIRECTIONAL_LIGHT
					fixed atten = 1.0;
				#else
					#if defined(POINT)
						// 此处不能是float4,暂时不明白
						float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
						fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
					#elif defined(SPOT)
						float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1.0));
						fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy/lightCoord.w + 0.5).w + tex2D(_LightTextureB0, dot(lightCoord, lightCoord),rr).UNITY_ATTEN_CHANNEL;
					#else
						fixed atten = 1.0;
					#endif
				#endif

				fixed shadow = SHADOW_ATTENUATION(i);

				return fixed4(ambient + (specular+diffuse) * atten * shadow, 1.0);

				// return fixed4(1,1,1,1);
			}
			ENDCG		
		}
	}

	FallBack "Specular"
}

 URP+HLSL写法:

Shader "Unity Shaders Book/Chapter 9/Shadow" {
	Properties {
		_Diffuse("Diffuse Color", Color) = (1,1,1,1)
		_Specular("Specular Color", Color) = (1,1,1,1)
		_Gloss("Gloss", Range(10, 256)) = 10
		[Toggle(_AdditionalLights)] _AddLights("AddLights", Float) = 1
	}

	SubShader {
		Tags {
			"RenderType"="Opaque"
			"RenderPipeline"="UniversalPipeline"
		}

		Pass {
			Tags {"LightMode"="UniversalForward"}

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

			#pragma vertex vert
			#pragma fragment frag
			#pragma shader_feature _AdditionalLights

			// GetMainLight(shadowCoord)中需要用到 _MAIN_LIGHT_CALCULATE_SHADOWS ,进而用到_MAIN_LIGHT_SHADOWS
           	#pragma multi_compile _ _MAIN_LIGHT_SHADOWS

			// TransformWorldToShadowCoord 中需要用到 _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

			// AdditionalLightRealtimeShadow 中需要用到 _ADDITIONAL_LIGHT_SHADOWS
			#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS

			// 可能和精度有关系
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS

			// GetMainLight(shadowCoord)中需要用到 _SHADOWS_SOFT
			#pragma multi_compile _ _SHADOWS_SOFT

CBUFFER_START(UnityPerMaterial)
			half4 _Diffuse;
			half4 _Specular;
			half _Gloss;
CBUFFER_END

			struct a2v {
				float4 vertex : POSITION;
				half3 normal : NORMAL;
			};

			struct v2f {
				float4 pos : SV_POSITION;
				half3 worldPos : TEXCOORD0;
				half3 worldNormal : TEXCOORD1;

				// // #define SHADOW_COORDS(idx1) unityShdowCoord4 _ShadowCoord : TEXCOORD##idx1;
				// // 注意此处没有分号 ';' 
				// SHADOW_COORDS(2)
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = TransformObjectToHClip(v.vertex.xyz);
				o.worldNormal = TransformObjectToWorldNormal(v.normal);
				o.worldPos = mul(UNITY_MATRIX_M, v.vertex).xyz;

				// // #define TRANSFER_SHADOW(a) a._ShadowCoord = mul(unity_WorldToShadow[0], mul(_Object2World, v.vertex));
				// TRANSFER_SHADOW(o);

				return o;
			}

			half3 LightingBased(half3 lightColor, half3 lightDir, half lightAtten, half3 worldNormal, half3 viewDir) {
				lightDir = normalize(lightDir);
				viewDir = normalize(viewDir);

				half3 diffuse = lightColor * _Diffuse.rgb * saturate(dot(lightDir, worldNormal));
				half3 halfDir = normalize(lightDir + viewDir);
				half3 specular = lightColor * _Specular.rgb * pow(saturate(dot(halfDir, worldNormal)), _Gloss);
				return (diffuse + specular) * lightAtten;
			}

			half3 LightingBased(Light light, half3 worldNormal, half3 viewDir) {
				return LightingBased(light.color, light.direction, light.shadowAttenuation * light.distanceAttenuation, worldNormal, viewDir);
			}
			
			half4 frag(v2f i) : SV_Target {
				half3 worldNormal = normalize(i.worldNormal);
				half3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);

				// half3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
				// half3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				// half3 diffuse = _LightColor0.rgb * _Diffuse.rgb;
				// half3 halfDir = normalize(viewDir + lightDir);
				// half atten = 1.0;
				// half3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				// half shadow = SHADOW_ATTENUATION(i);
				// return half4(ambient + (diffuse + specular) * atten * shadow, 1.0);

				// 逐像素平行光
				float4 shadowCoord = TransformWorldToShadowCoord(i.worldPos);
				Light mainLight = GetMainLight(shadowCoord);
				half3 color = LightingBased(mainLight, worldNormal, viewDir);

				// 逐像素的额外光(不支持阴影,自带的lit也不支持)
				#if _AdditionalLights
					uint addLightCount = GetAdditionalLightsCount();
					for(uint iu = 0; iu < addLightCount; iu ++) {
						Light addLight = GetAdditionalLight(iu, i.worldPos);
						// half realtimeShadow = AdditionalLightRealtimeShadow(iu, i.worldPos);
						color += LightingBased(addLight, worldNormal, viewDir);
					}
				#endif

				half3 ambient = SampleSH(worldNormal);
				return half4(color + ambient, 1.0);
			}


			ENDHLSL
		}

		// 产生阴影有问题,有时有,有时没有
		// FallBack "Universal Render Pipeline/Simple Lit"

		// // 方式1:下面计算阴影的Pass可以直接通过使用URP内置的Pass计算
        // UsePass "Universal Render Pipeline/Simple Lit/ShadowCaster"
        
        // 方式2:自己计算阴影的Pass
        Pass
        {
            Tags { "LightMode" = "ShadowCaster" }
			
            Cull Off
            ZWrite On
            ZTest LEqual
			ColorMask 0
            
            HLSLPROGRAM
            
            // 设置关键字
            #pragma shader_feature _ALPHATEST_ON
            
            #pragma vertex vert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
			

            float3 _LightDirection;
            
            struct a2v
            {
                float4 vertex: POSITION;
                float3 normal: NORMAL;
            };
            
            struct v2f
            {
				float4 pos: SV_POSITION;
            };            
            
            // 获取裁剪空间下的阴影坐标
            float4 GetShadowPositionHClips(a2v v)
            {
                float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
                float3 normalWS = TransformObjectToWorldNormal(v.normal);
                // 获取阴影专用裁剪空间下的坐标
                float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
                
                // 判断是否是在DirectX平台翻转过坐标
                #if UNITY_REVERSED_Z
                    positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #else
                    positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #endif
                
                return positionCS;
            }
            
            v2f vert(a2v v)
            {
                v2f o;
                o.pos = GetShadowPositionHClips(v);
                return o;
            }

       
            half4 frag(v2f i): SV_TARGET
            {
                return 0;
            }
            
            ENDHLSL
            
        }
	}

	
    // FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Unity URP中,点光源的自定义阴影需要通过脚本来实现。具体步骤如下: 1. 创建一个新的着色器,并设置其为使用“Universal Render Pipeline/Lit”着色器。 2. 在着色器中添加一个新的块,用于计算阴影: ```hlsl #pragma shader_feature __ _SHADOWS_SOFT #pragma shader_feature __ _SHADOWS_CASCADE float3 ComputeShadowCoord(float4 pos) { float3 shadowCoord = pos.xyz / pos.w; shadowCoord = shadowCoord * 0.5f + 0.5f; #if defined(_SHADOWS_SOFT) shadowCoord.z += 0.0005f; #endif #if defined(_SHADOWS_CASCADE) shadowCoord.z += 0.0001f * pos.w; #endif return shadowCoord; } ``` 3. 在Pass中添加以下代码,用于计算阴影: ```hlsl #ifdef LIGHTMAP_ON SHADOW_COORDS_LIGHTMAP #elif defined(SHADOWS_SCREEN) SHADOW_COORDS_SCREEN #else float3 shadowCoord = ComputeShadowCoord(UnityObjectToClipPos(v.vertex)); #endif ``` 4. 在Pass中添加以下代码,用于生成阴影: ```hlsl #if defined(_SHADOWS_SOFT) float shadow = ComputeSoftPointShadow(shadowCoord, _LightPosition, _LightRadius, _ShadowmapTexture, _ShadowStrength); #elif defined(_SHADOWS_CASCADE) float shadow = ComputeCascadePointShadow(shadowCoord, _CascadeShadowmapTexture, _CascadeShadowStrength, _CascadeShadowDistance); #else float shadow = ComputePointShadow(shadowCoord, _LightPosition, _ShadowmapTexture); #endif return shadow; ``` 其中,ComputePointShadow函数用于计算点光源阴影。您可以通过调整参数来自定义阴影的外观和行为。 希望这能帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值