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/