您的位置:首页 > 其它

模拟实时光照下的阴影

2016-02-24 17:56 288 查看
在3d游戏中,实时光照是一个特别大的消耗,不仅是因为对于颜色的计算,还有消耗在绘制实时阴影,对于手机游戏无疑是一个很大的开销,但是吧,没有实时光照的影子,就显得很呆板,这里就说明一下3d游戏中绘制阴影的原理。



太阳光可以看做是一个平行光,平行光经过物体,投影到某个平面中,于是在该平面形成了阴影。

现在,我们假设需要投影到一个平面上,该平面的方程为ax+by+cz+d=0,其中(a,b,c)是该平面的法向量,假设该平面上存在一个点p(x2,y2,z2),那么d=-(a*x2+b*y2+c*z2),现在假设太阳光的方向向量为_LightVec,由上图可以看出

{

ax+by+cz-(a*x2+b*y2+c*z2)=0           1

}

{

    x1=x + k*LightVec.x             2

    y1=y+ k*LightVec.y             3

    z1=z+ k*LightVec.z              4

}

(x1,y1,z1)和(x2,y2,z2)同样是平面上的点,故可以将234代入1式中,得到:

k=a(x2-x)+b(y2-y)+c(z2-z)/(a*LightVec.x + b*LightVec.y +c*LightVec.z )

我是假设了平面法线向量(1, 0, 0)平面上存在点(0.3, 0, 0),所以可以算出k=(0.3-x)/LightVec.x;

代入上面得到

{

    x1=0.3

    y1=k*y + _LightVec.y;

    z1=k*z + _LightVec.z;

}

下面是完整shader代码:

Shader "Expand/RealTimeShadow" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_LightVec ("Light Position", Vector) = (1, 0, 0, 0)	//平行光向量
_Hight("Hight", Range (0.0, 2)) = 0.32
}
SubShader {
Tags {"Queue"="Geometry"}
LOD 200
//影子
Pass {
CGINCLUDE
#include "UnityCG.cginc"

struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : POSITION;
};
ENDCG

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 _LightVec;
float _Hight;
v2f vert(appdata v) {
v2f o;
//假设投影的平面上有一个点(0.32, 0, 0)为1x+0y+0z-(1*0.32+b*0+c*0)=0; 平行光向量;
float3 vec3 = _LightVec;
float k = (_Hight-v.vertex.x)/vec3.x;
v.vertex.y = k*vec3.y + v.vertex.y;
v.vertex.z = k*vec3.z + v.vertex.z;
v.vertex.x = _Hight;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
half4 frag(v2f i) : COLOR {
return 0;
}
ENDCG
}
}
}


可以自定义光照方向,离地高度,最后的效果是

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: