Unity上平面阴影的计算与实现
//如何求顶点投影到平面上的点(阴影点)
//当平面上取不相等的任意两个点组成一个向量,与平面的法线总是垂直的,向量垂直点乘为0,因此可以通过一个点和一个法线来定义,
//plane方程如下:(P - P0)·N = 0 N=normal,P0表示平面上的一个点,P表示平面上的任意点,当P = P0时 0·N = 0
//射线方程 P = o + t * D,(o为射线起点,t为标量,表示射线原点到和平面交点的距离)联立两个方程式可求交点。方程如下:
// ( O + D·t - P0 )·N = 0
// => ( O - P0 )·N + D·N·t = 0
// => t = ( P0 - O)·N / D·N ( 其中D·N ≠0 ,向量点积满足分配律)
// p0表示平面上一点中心点(0,0,0) o:顶点世界坐标 N:平面的法向量(0,1,0)D:直射光方向
//注意两点:
//当 D·N = 0 时,表示射线与平面垂直,则射线与平面平行。
//解出 t < 0 时,表示 射线沿着平面相反的半平面发射,也是不相交的(当然如果是直线就没关系啦)
Shader "Pluto/PlanarShadow"
{
Properties
{
_ShadowColor ("Shadow Color",Color) = (0.25,0.25,0.25,0.25)
_Center("Center", Vector) = (0,0.001,0,0)
_Normal("Normal", Vector) = (0,1,0,0)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" }
LOD 100
//渲染模型
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION; //模型空间中的顶点坐标
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION; //裁剪空间中的顶点坐标
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); //将顶点从模型空间转换到裁剪空间中,更高效
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
//渲染平面阴影Pass
Pass
{
ZWrite On
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
Stencil{
Ref 0
Comp Equal
Pass IncrWrap
ZFail Keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float4 _ShadowColor; //阴影颜色
float4 _Center; //平面上一点中心点
float4 _Normal; //平面法线
v2f vert (appdata v)
{
v2f o;
float4 wPos = mul(unity_ObjectToWorld ,v.vertex); //顶点世界坐标
float4 lightDir = normalize(_WorldSpaceLightPos0); //直射光的方向
float dist = dot(_Center.xyz - wPos.xyz, _Normal.xyz) / dot(lightDir, _Normal.xyz);
wPos = wPos + lightDir * dist;
o.vertex = mul( UNITY_MATRIX_VP,wPos); //转换到裁剪空间坐标
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _ShadowColor; //直接返回影子颜色
}
ENDCG
}
}
}

参考:https://www.jianshu.com/p/c8438bf6af0f
----码字不易,欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/beeasy/