模拟实时光照下的阴影
2016-02-24 17:56
288 查看
在3d游戏中,实时光照是一个特别大的消耗,不仅是因为对于颜色的计算,还有消耗在绘制实时阴影,对于手机游戏无疑是一个很大的开销,但是吧,没有实时光照的影子,就显得很呆板,这里就说明一下3d游戏中绘制阴影的原理。
![](https://img-blog.csdn.net/20160224173520220?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
太阳光可以看做是一个平行光,平行光经过物体,投影到某个平面中,于是在该平面形成了阴影。
现在,我们假设需要投影到一个平面上,该平面的方程为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代码:
可以自定义光照方向,离地高度,最后的效果是
太阳光可以看做是一个平行光,平行光经过物体,投影到某个平面中,于是在该平面形成了阴影。
现在,我们假设需要投影到一个平面上,该平面的方程为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 } } }
可以自定义光照方向,离地高度,最后的效果是
相关文章推荐
- ${pageContext.request.contextPath}的作用
- 监听文本框输入开发仿新浪微博限制输入字数的textarea插件
- 固定表格布局,固定列的宽度,溢出字隐藏
- The Swift Programming Language学习笔记(十八)——可选链式调用
- mongodb errmsg: no write ops were included in the batch
- Spring中注解的实现原理-Autowired和Resource的区别
- 【转】oracle对BLOB类型数据的操作与性能问题
- 了解JavaScript 面向对象基础 & 原型与对象
- Http中Get与Post区别详解
- Git之版本管理
- iOS开发 高级绘图
- Android Studio常用快捷键(eclipse版)
- Android属性动画完全解析
- Android内存优化--内存泄露解决方案
- ORA-27125: unable to create shared memory segment
- Android 混淆代码总结
- Android 数据库框架ormlite 使用精要
- Microservices
- 修改nrf52832的nfc天线引脚p09,p10为gpio
- #学习笔记#(45)Chart.js曲线图