Unity URP下接受阴影

前言

        虽然网络上已经有很多文章来说明如何实现了,但是网络上的文章有时候都不能满足我个人的需求。有时候我要去查找很多篇文章才能找到我想要的。所以我想自己写一篇文章记录一下,以后要是遇到啥直接来看自己的文章就是了。

环境

        Windows操作系统         Unity2022.3.8f1c1

常规的阴影实现

        如果我们直接新建一个URP的空白项目且不进行任何的修改。那么实现阴影的方法如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Shader "Test/OnlyShadow"
{
Properties {}
SubShader
{
Tags {
"LightMode"="UniversalForward"
}
LOD 100

Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag

#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE

#pragma multi_compile_fragment _ _SHADOWS_SOFT

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

struct appdata
{
float4 vertex : POSITION;
};

struct v2f
{
float4 vertex : SV_POSITION;
float4 worldPos : TEXCOORD0;
};


v2f vert (appdata v)
{
v2f o;
o.vertex = TransformObjectToHClip(v.vertex.xyz);
o.worldPos = float4(TransformObjectToWorld(v.vertex.xyz),1);
return o;
}

half4 frag (v2f i) : SV_Target
{
Light mainLight = GetMainLight(TransformWorldToShadowCoord(i.worldPos.xyz));
half shadowVal = mainLight.shadowAttenuation;
return half4(shadowVal,shadowVal,shadowVal,1);
}
ENDHLSL
}
}
}

下图中平面的阴影部分就是上面Shader的效果。

硬阴影

软阴影

上面的写法基本就是网上大部分的写法了。大多数情况下,上面的写法也确实可以接受阴影。但是凡事总是有例外的。

屏幕空间阴影

        URP中,我们可以将阴影设置为屏幕空间阴影。具体方法就是找到你项目中URP的设置(如何查找URP的设置可以看一下这篇文章),然后添加屏幕空间阴影的渲染特性就完成设置了。如果你设置成屏幕空间阴影,然后再使用上面的方法。你会发现一个“神奇”的现象:只有当你的物体处于透明物体的渲染队列时,物体的阴影才可以被正常渲染。这是因为上面的方法中少写了一个Pass —— DepthNormals。

        你可以在URP提供的Lit下找到这个Pass的实现。这里我直接贴出对应的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 Pass
{
Name "DepthOnly"
Tags
{
"LightMode" = "DepthOnly"
}
// -------------------------------------
// Render State Commands
ZWrite On
ColorMask R
Cull[_Cull]
HLSLPROGRAM
#pragma target 2.0
// -------------------------------------
// Shader Stages
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibraryDOTShlsl"
// -------------------------------------
// Includes
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}

在设置里面有一个屏幕空间阴影,它开启后就必须要加上DepthNormals才可以在不透明物体下加载阴影。

透明物体渲染阴影

        URP中,如果你想要在透明物体中显示阴影细节。那么你要在你项目开启透明物体渲染阴影的选项,否则你就算shader写对了也不会出现阴影。

结语

        如果上述说明存在,请帮忙指出来。