Unity URP 手游中常用的平面投影阴影

第一个pass随便你怎么写,直接用URP自带的也可以,我自己写了一个高光+兰伯特+阴影,可以无视第一个pass

USEPASS "Universal Render Pipeline/Lit/ForwardLit"

直接上shader吧,复制就能用了,好耶!

Shader "HLSL/PlanarPlayerShadow" {
	Properties{
	_BaseMap("Example Texture", 2D) = "white" {}
	_BaseColor("Example Colour", Color) = (0, 0.66, 0.73, 1)
	_Specular("Specular",Float) = 1
	_Smoothness("Smoothness",Float)=0.5
	_ShadowColor("ShadowColor",COLOR)=(0,0,0,0)
	_ShadowFalloff("ShadowFalloff",Range(0,1))=0.5
	_Plane("Plane",float)=0

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

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

				CBUFFER_START(UnityPerMaterial)
				float4 _BaseMap_ST;
				float4 _BaseColor;
				float _Specular;
				float _Smoothness;


				float4 _ShadowColor;
				float _ShadowFalloff;
				float _Plane;
				CBUFFER_END
			ENDHLSL

			Pass {
				Name "Diff+Sp"
				Tags { "LightMode" = "UniversalForward" }

				HLSLPROGRAM
				#pragma vertex vert
				#pragma fragment frag

				#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
				#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
				#pragma multi_compile _ _SHADOWS_SOFT

				

				struct Attributes {
					float4 positionOS	: POSITION;
					float2 uv 		: TEXCOORD0;
					float4 color		: COLOR;

					float4 normalOS		: NORMAL;
				};

				struct Varyings {
					float4 positionCS	: SV_POSITION;
					float2 uv		: TEXCOORD0;
					float4 color		: COLOR;

					float3 normalWS		: NORMAL;
					float3 positionWS	: TEXCOORD2;
					float3 worldView	: TEXCOORD3;
				};

				TEXTURE2D(_BaseMap);
				SAMPLER(sampler_BaseMap);

				Varyings vert(Attributes IN) {
					Varyings OUT;

					VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
					OUT.positionCS = positionInputs.positionCS;
					// Or this :
					//OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);

					OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
					OUT.color = IN.color;

					OUT.positionWS = positionInputs.positionWS;

					VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS.xyz);
					OUT.normalWS = normalInputs.normalWS;

					OUT.worldView= _WorldSpaceCameraPos.xyz - OUT.positionWS;

					return OUT;
				}

				half4 frag(Varyings IN) : SV_Target {
					half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
					half4 color = baseMap * _BaseColor * IN.color;

					

					float4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS.xyz);
					Light light = GetMainLight(shadowCoord);

					light.color *= light.shadowAttenuation;
					half3 shading = LightingLambert(light.color, light.direction, IN.normalWS);

					float Smoothness = exp2(10 * _Smoothness + 1);
					float3 WorldNormal = normalize(IN.normalWS);
					float3 WorldView = SafeNormalize(IN.worldView);
					half3 specular = LightingSpecular(light.color, light.direction, WorldNormal, WorldView, half4(_Specular, _Specular, _Specular, 0), Smoothness);

					return half4(color.rgb * shading+ specular, color.a);
				}
				ENDHLSL
				}
				Pass{
				Name "Planr Shadow"
				Tags{ "LightMode" = "SRPDefaultUnlit" }//URP不支持多pass,这样可以多pass,或者干脆不加tags也可以
				Stencil
				{
					Ref 0
					Comp equal
					Pass incrWrap
					Fail keep
					ZFail keep
				}

				Blend SrcAlpha OneMinusSrcAlpha

				ZWrite off

				Offset -1 , 0

				HLSLPROGRAM
				#pragma vertex vert
				#pragma fragment frag

				struct Attributes {
					float4 positionOS	: POSITION;
				};

				struct Varyings {
					float4 positionCS	: SV_POSITION;
					float4 color : COLOR;
				};

				float3 ShadowProjectPos(float4 vertPos,float3 lightDir)
				{
					float3 shadowPos;

					//得到顶点的世界空间坐标
					float3 worldPos = TransformObjectToWorld(vertPos);

					//阴影的世界空间坐标(低于地面的部分不做改变)
					shadowPos.y = min(worldPos.y, _Plane);
					shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _Plane) / lightDir.y;

					return shadowPos;
				}
				Varyings vert(Attributes IN) {
					Varyings OUT;

					Light light = GetMainLight();

					//得到阴影的世界空间坐标
					float3 shadowPos = ShadowProjectPos(IN.positionOS, light.direction);

					OUT.positionCS = TransformWorldToHClip(shadowPos);

					//得到中心点世界坐标
					float3 center = float3(unity_ObjectToWorld[0].w, _Plane, unity_ObjectToWorld[2].w);
					//计算阴影衰减
					float falloff = 1 - saturate(distance(shadowPos, center) * _ShadowFalloff);

					//阴影颜色
					OUT.color = _ShadowColor;
					OUT.color.a *= falloff;


					return OUT;
				}
				half4 frag(Varyings IN) : SV_Target{
					return IN.color;
				}
				ENDHLSL
				}
	}
}

 参考文章https://zhuanlan.zhihu.com/p/31504088

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Unity URP(Universal Render Pipeline)是Unity引擎的一种渲染管线,它提供了一种用于创建高质量的实时渲染效果的方式。 要实现手电筒效果,首先我们需要创建一个聚光灯(Spotlight)对象,该对象作为手电筒的光源。在Unity的场景,我们可以通过创建一个聚光灯来模拟手电筒效果。设置聚光灯的位置和旋转方向,以正确照亮游戏场景。 在URP,我们可以使用Volume组件来控制渲染效果。创建一个Volume,选择“添加Override”来添加一个覆盖,选择"Lighting > Additional Light Data"来控制聚光灯的相关属性。在这里,我们可以设置聚光灯的颜色、强度、角度和范围等参数。 为了使手电筒效果更真实,我们还可以添加一个雾效(Volumetric Fog)。Volumetric Fog可以模拟光线在空气的散射效果,给手电筒效果增加一些逼真度。在Volume组件选择“添加Override”,然后选择"Rendering > Volumetric Fog"来添加并控制雾效的参数。 在场景调整聚光灯的位置和角度,可以看到聚光灯产生的光束随着手电筒的移动而变化。当玩家在游戏控制角色移动时,手电筒效果能够在场景产生动态的照明效果,增强了游戏的沉浸感和真实感。 总之,Unity URP提供了一种简单而强大的方式来实现手电筒效果。通过创建聚光灯和调整其属性,加上可能的雾效,我们可以在游戏实现有趣而逼真的手电筒效果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值