9.3 阴影的淡出
9.3.1 有效利用计算平面阴影过程中的数据
9.3.2潜在的问题
这个方法还有一个显而易见的问题,那就是物体本身是立体的,不是一个平面,因此这个计算前后的点的距离是包括物体本身厚度的,这个厚度就会表现在阴影上。要解决这个问题,我们可以先把物体变换到灯光空间,使用_World2Light矩阵沿着灯光方向把物体压扁,然后投射物体,这样计算出来的阴影衰减就不会包括物体的厚度了。
9.3.1 有效利用计算平面阴影过程中的数据
一般情况下,比如用Shadow Mapping和Shadow Volumes计算阴影的衰减是比较困难的,但是在此例中,我们己经知道投射阴影物体的顶点在计算前和计算后的位置,根据这两个位置的距离,我们还是可以考虑计算一下阴影的衰减问题的。
<pre name="code" class="csharp">Shader "Tut/Shadow/PlanarShadow_3" {
Properties{
_Intensity("atten",range(1,16))=1
}
SubShader {
pass {
Tags { "LightMode" = "ForwardBase" }
Material{Diffuse(1,1,1,1)}
Lighting On
}//
pass {
Tags { "LightMode" = "ForwardBase" }
Cull Front
Blend DstColor SrcColor
Offset -1,-1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4x4 _World2Ground;
float4x4 _Ground2World;
float _Intensity;
struct v2f{
float4 pos:SV_POSITION;
float atten:TEXCOORD0;
};
v2f vert(float4 vertex: POSITION)
{
v2f o;
float3 litDir;
litDir=normalize(WorldSpaceLightDir(vertex));
litDir=mul(_World2Ground,float4(litDir,0)).xyz;
float4 vt;
vt= mul(_Object2World, vertex);
vt=mul(_World2Ground,vt);
vt.xz=vt.xz-(vt.y/litDir.y)*litDir.xz;
vt.y=0;
vt=mul(_Ground2World,vt);//back to world
vt=mul(_World2Object,vt);
o.pos=mul(UNITY_MATRIX_MVP, vt);
o.atten=distance(vertex,vt)/_Intensity;
return o;
}
float4 frag(v2f i) : COLOR
{
return smoothstep(0,1,i.atten/2);
}
ENDCG
}//
pass {
Tags { "LightMode" = "ForwardAdd" }
Cull Front
Blend DstColor SrcColor
Offset -2,-1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4x4 _World2Ground;
float4x4 _Ground2World;
float _Intensity;
struct v2f{
float4 pos:SV_POSITION;
float atten:TEXCOORD0;
};
v2f vert(float4 vertex:POSITION)
{
v2f o;
float3 litDir;
litDir=normalize(WorldSpaceLightDir(vertex));
litDir=mul(_World2Ground,float4(litDir,0)).xyz;
float4 vt;
vt= mul(_Object2World, vertex);
vt=mul(_World2Ground,vt);
vt.xz=vt.xz-(vt.y/litDir.y)*litDir.xz;
vt.y=0;
vt=mul(_Ground2World,vt);//back to world
vt=mul(_World2Object,vt);
o.pos= mul(UNITY_MATRIX_MVP, vt);
o.atten=distance(vertex,vt)/_Intensity;
return o;
}
float4 frag(v2f i) : COLOR
{
return smoothstep(0,1,i.atten*i.atten);
}
ENDCG
}
}
}
9.3.2潜在的问题
这个方法还有一个显而易见的问题,那就是物体本身是立体的,不是一个平面,因此这个计算前后的点的距离是包括物体本身厚度的,这个厚度就会表现在阴影上。要解决这个问题,我们可以先把物体变换到灯光空间,使用_World2Light矩阵沿着灯光方向把物体压扁,然后投射物体,这样计算出来的阴影衰减就不会包括物体的厚度了。