public class CastShadow : MonoBehaviour {public Transform rec;//接受阴影的物体// Use this for initializationvoid 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 SrcColorOffset -1,-1CGPROGRAM
#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;// 用三角形相似计算沿光源方向投射后的XZvt.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方向的投影坐标。