public class CastShadow : MonoBehaviour {
public Transform rec;//接受阴影的物体
// Use this for initialization
void Start () {
GetComponent<Renderer>().sharedMaterial.SetMatrix("_World2Ground", rec.GetComponent<Renderer>().worldToLocalMatrix);
GetComponent<Renderer>().sharedMaterial.SetMatrix("_Ground2World", rec.GetComponent<Renderer>().localToWorldMatrix);
}
void Update()
{
}
}
这个脚本主要是为了设置需要接受阴影的地面的坐标系,如果没有这个脚本,物体产生的阴影的坐标系是原始坐标系(0,0,0)
// shader,放在需要显示阴影的对象上
Shader "Study/8_PlanarShadow" {
Properties{
_Instensity("Shininess", Range(2, 4)) = 2.1
}
SubShader{
pass {
Tags{ "LightMode" = "ForwardBase" }
Material{ Diffuse(1,1,1,1) }
Lighting On
}
Pass{
Tags{ "LightMode" = "ForwardBase" }
Blend DstColor SrcColor
Offset -1,-1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4x4 _World2Ground;
float4x4 _Ground2World;
float _Instensity;
struct v2f {
float4 pos:SV_POSITION;
float atten : TEXCOORD0;
};
v2f vert(float4 vertex:POSITION)
{
float3 litDir;
litDir = WorldSpaceLightDir(vertex);//世界空间主光照相对于当前物体的方向
float4 litDir_4 = float4(litDir,0);
litDir_4 = mul(_World2Ground, litDir_4);//光源方向转换到接受阴影的平面空间
litDir_4 = normalize(litDir_4);// 归一
float4 vt;
vt = mul(_Object2World,vertex); //将当前物体转换到世界空间
vt = mul(_World2Ground,vt); // 将物体在世界空间的矩阵转换到地面空间
vt.xz = vt.xz - (vt.y / litDir_4.y)*litDir_4.xz;// 用三角形相似计算沿光源方向投射后的XZ
vt.y = 0;// 使阴影保持在接受平面上
vt = mul(_Ground2World, vt); // 阴影顶点矩阵返回到世界空间
vt = mul(_World2Object, vt); // 返回到物体的坐标
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, vt);//输出到裁剪空间
o.atten = distance(vertex, vt) / _Instensity;// 根据物体顶点到阴影的距离计算衰减
return o;
}
float4 frag(v2f i) :COLOR
{
return smoothstep(0,1,i.atten / 2);
}
ENDCG
}
}
}
这个shader只是讲解下平面阴影的产生原理,核心的原理就是通过三角形相似,根据光照方向将顶点投影到地面上。
其中第一个Pass是渲染物体本体,第二个Pass渲染阴影。渲染阴影的原理是将坐标系转换成接受阴影的地面坐标系后,根据三角形相似,计算出物体顶点在x方向和z方向的投影坐标。