Lv.2 Unity主线: 添加阴影
阴影的必要代码
PassTag
需要声明前向渲染ForwardBase,这是声明给程序端C++看的
1
2
3
Tags{
"LightMode" = "ForwardBase"
}
pragma指令
编译变体fwdbase,也就多次编译不同的Shdaer版本,这里是声明构成前向渲染专用变体,这和Tags的声明不同,它是给Shdaer编译器看的
1
#pragma multi_compile_fwdbase
Include文件
只需要阴影的话Lighting可以不引入也行,不过都写上就完了
1
2
3
4
#include "UnityCG.cginc"
#include "Lighting.cginc"
// 阴影宏定义在这里
#include "AutoLight.cginc"
appdata结构体声明要求
之前写的物体空间的顶点posOS必须换成vertex。原因在下面将 
v2f结构体声明要求
这里在结构体中声明阴影数据,注意括号中的顺序号 
1
2
3
4
float4 pos : SV_POSITION;
----
// 阴影坐标声明(自动处理多个变体)
UNITY_SHADOW_COORDS(4)
这里需要额外说明一点,裁剪空间下的顶点位置,必须命名为pos.同时这也是这是物体空间的顶点posOS必须换成vertex的原因。AutoLight.cginc文件下Unity阴影函数里面固定的,其他名称会报错 
顶点着色器
阴影数据处理,直接系统函数 
1
2
//传输阴影数据(关键!)
TRANSFER_SHADOW(o);
片元着色器
计算阴影衰减,输出结果和diffuse乘法计算就行,注意不要和环境光相乘 这里需要说明一点,阴影在Shader中分为两个内容,一个是接收其它的阴影,一个是投射自己的阴影 
1
2
// 计算阴影衰减(自动处理所有阴影类型)
fixed shadow = SHADOW_ATTENUATION(i);
投射阴影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
36
37
38
39
40
41
Pass
{
Name"ShadowCaster"
Tags{
"LightMode" = "ShadowCaster"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 阴影投射需要的变体
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
V2F_SHADOW_CASTER; // Unity预定义的结构
};
v2f vert(appdata v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) // 转换到阴影空间
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//裁剪处理位置clip()
SHADOW_CASTER_FRAGMENT(i) // 写入阴影深度
}
ENDCG
}
如果不想写这个Pass,可以直接在末尾加上 FallBack “Diffuse”,但是没有自己写性能好 
代码参考
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
Shader "Unlit/AddShadow"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Name "Forward"
Tags{
"LightMode" = "ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc" // 1.阴影宏定义在这里
struct appdata
{
float4 posOS : POSITION;
float2 uv : TEXCOORD0;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 posWS : TEXCOORD1;
float3 normalWS :TEXCOORD2;
float3 tangentWS: TEXCOORD3;
// 阴影坐标声明(自动处理多个变体)
UNITY_SHADOW_COORDS(4)
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.posOS);
o.texcoord = TRANSFORM_TEX(v.uv, _MainTex);
o.posWS = mul(unity_ObjectToWorld, v.posOS);
o.normalWS = UnityObjectToWorldNormal(v.normalOS);
o.tangentWS = UnityObjectToWorldDir(v.tangentOS);
// 传输阴影数据(关键!)
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.texcoord);
// 计算阴影衰减(自动处理所有阴影类型)
fixed shadow = SHADOW_ATTENUATION(i);
return col *shadow;
}
ENDCG
}
Pass
{
Name"ShadowCaster"
Tags{
"LightMode" = "ShadowCaster"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 阴影投射需要的变体
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
V2F_SHADOW_CASTER; // Unity预定义的结构
};
v2f vert(appdata v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) // 转换到阴影空间
return o;
}
fixed4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i) // 写入阴影深度
}
ENDCG
}
}
FallBack "Diffuse"
}
Enjoy Reading This Article?
Here are some more articles you might like to read next: