TA-Shader-文件 Unity实时反射——AngryBots示例项目地面实时反射效果剖析
发布于
2016-3-25
12449
111
TA资源类型
TA资源类型: 算法思路 
shader资源类型: 其它 
适用引擎: unity 
资源介绍: -

您需要 登录 才可以下载或查看,没有账号?注册

x
Angry Bots是Unity安装程序自带的开源示例项目。该示例项目虽然已经发布很久了,但是其很多设计和实现仍然具有参考价值。
运行该项目仔细观察,可以发现其雨天地面效果是实时反射的。这里我们先阐明实时反射的原理,然后分析其绘制流程。


构造反射相机
视图矩阵
  反射相机的视图矩阵由反射矩阵变换得到,反射矩阵由反射平面确定,下面列出反射矩阵推导过程。
反射位置 f40c96f205ed4a95a1121408b91faa3e.001.1458563794.png

f40c96f205ed4a95a1121408b91faa3e.002.1458563795.png


反射方向




M1*M2即得到示例代码所示的反射矩阵。


  1. static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
  2. {
  3.     reflectionMat.m00 = (1.0F - 2.0F * plane[0] * plane[0]);
  4.     reflectionMat.m01 = (-2.0F * plane[0] * plane[1]);
  5.     reflectionMat.m02 = (-2.0F * plane[0] * plane[2]);
  6.     reflectionMat.m03 = (-2.0F * plane[3] * plane[0]);
  7.     reflectionMat.m10 = (-2.0F * plane[1] * plane[0]);
  8.     reflectionMat.m11 = (1.0F - 2.0F * plane[1] * plane[1]);
  9.     reflectionMat.m12 = (-2.0F * plane[1] * plane[2]);
  10.     reflectionMat.m13 = (-2.0F * plane[3] * plane[1]);
  11.     reflectionMat.m20 = (-2.0F * plane[2] * plane[0]);
  12.     reflectionMat.m21 = (-2.0F * plane[2] * plane[1]);
  13.     reflectionMat.m22 = (1.0F - 2.0F * plane[2] * plane[2]);
  14.     reflectionMat.m23 = (-2.0F * plane[3] * plane[2]);
  15.     reflectionMat.m30 = 0.0F;
  16.     reflectionMat.m31 = 0.0F;
  17.     reflectionMat.m32 = 0.0F;
  18.     reflectionMat.m33 = 1.0F;
  19.    return reflectionMat;
  20. [align=left]}
点击此处复制文本
其中代码中4维数组plane存的是点法线式平面方程的参数。

投影矩阵

  反射相机的投影矩阵并非常规的投影矩阵,反射面上的斜投影面才是反射相机真正的投影面,

所以需要用斜投影面代替掉常规的投影面。示例代码中给出了斜投影矩阵,

原理和推导过程参看本文末尾给出的参考文献链接。这里给出示意图:



绘制流程 

1.创建反射摄像机reflectionCamera,reflectionCamera默认disable,用一张RenderTexutre来保存reflectionCamera绘制的结果,用来在之后的shader里采样。

  1. reflectCamera.enabled = false;                                         
  2. reflectCamera.targetTexture = CreateTextureFor(cam);
点击此处复制文本

  1. private RenderTexture CreateTextureFor(Camera cam)
  2. {

  3.               RenderTexture rt = new RenderTexture(Mathf.FloorToInt(cam.pixelWidth * rtSizeMul), Mathf.FloorToInt(cam.pixelHeight * rtSizeMul), 24, rtFormat);                                         
  4.               rt.hideFlags = HideFlags.DontSave;
  5.               return rt;
  6. }
点击此处复制文本

2.在LateUpdate中根据当前摄像机去构造反射摄像机变换矩阵,涉及到反射面reflectiveSurface的选取,示例中是选取合适的路面做反射面,然后手动调用绘制,绘制前设置前面剔除,绘制完置回。

  1. private void RenderReflectionFor (Camera cam, Camera reflectCamera)
  2. {

  3.     //构造反射平面
  4.      Vector3 pos = reflectiveSurface.transform.position;
  5.               pos.y = reflectiveSurface.position.y;
  6.               Vector3 normal = reflectiveSurface.transform.up;
  7.               float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
  8.               Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
  9.             
  10.     //构造反射视图矩阵                                         
  11.               Matrix4x4 reflection = Matrix4x4.zero;
  12.               reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
  13.     //得到反射摄像机位置                           
  14.               oldpos = cam.transform.position;
  15.               Vector3 newpos = reflection.MultiplyPoint (oldpos);
  16.                   
  17. //得到反射摄像机视图矩阵                                         
  18.               reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
  19.             
  20. //得到反射摄像机投影矩阵                                         
  21.               Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
  22.                                                       
  23.               Matrix4x4 projection =  cam.projectionMatrix;
  24.                             projection = CalculateObliqueMatrix(projection, clipPlane);
  25.                             reflectCamera.projectionMatrix = projection;
  26.                            
  27.               …
  28. GL.SetRevertBackfacing(true);            
  29. reflectCamera.RenderWithShader (replacementShader, "Reflection");                                         
  30. GL.SetRevertBackfacing(false);
  31. }
点击此处复制文本
Shader
  反射面的材质接受反射相机绘制好的RenderTexture做为贴图对其采样。

示例中的反射面——地面shader增加了uv扰动参数和噪声贴图用来达到扭曲效果,

还叠加了一个水花效果,这样的话使得雨天地面反射更加真实,而不是干净得像一面镜子。

  1. v2f_full vert (appdata_full v)
  2. {
  3.               …                                         
  4. // uv坐标扰动,随时间变化
  5.               o.normalScrollUv.xyzw = v.texcoord.xyxy * _TexAtlasTiling + _Time.xxxx * _DirectionUv;
  6.             
  7. //经验算法?!生成UV取水花贴图                                                                    
  8. half3 worldSpace = mul(_Object2World, v.vertex).xyz;
  9. worldSpace = (-_WorldSpaceCameraPos * 0.6 + worldSpace) * 0.07;
  10. o.fakeRefl =  worldSpace.xz;                           
  11.                            
  12.               return o;
  13. }
  14. fixed4 frag (v2f_full i) : COLOR0
  15. {
  16.               fixed4 nrml = tex2D(_Normal, i.normalScrollUv.xy);
  17.               nrml = (nrml - 0.5) * 0.1;
  18.             
  19. //UV扰动,在RenderTexture采样                                                                                                                           
  20.               fixed4 rtRefl = tex2D (_ReflectionTex, (i.screen.xy / i.screen.w) +nrml.xy);
  21.                                           
  22.               //叠加上在水花贴图
  23.               rtRefl += tex2D (_FakeReflect, i.fakeRefl + nrml.xy);
  24.             
  25.               //原贴图颜色                                                      
  26.               fixed4 tex = tex2D (_MainTex, i.uv);
  27.             
  28. //SrcAlpha One混合模式叠加                           
  29.               tex  = tex + tex.a * rtRefl;
  30.                                           
  31.               return tex;
  32. }
点击此处复制文本

效果附School项目按示例方式添加雨水地面实时反射效果前后对比图:









参考链接:
http://fp.optics.arizona.edu/optomech/Fall13/Notes/6%20Mirror%20matrices.pdf
http://www.terathon.com/lengyel/Lengyel-Oblique.pdf




参与人数 2 元素币 +10 活跃度 +10

本帖被以下画板推荐:

还没有设置签名!您可以在此展示你的链接,或者个人主页!

使用道具 举报 登录

回复 <
试试起个中文名  发表于 2016-3-25 17:32:14  
2#
高端大气上档次
回复 收起回复
使用道具
xs21212121  发表于 2016-3-26 02:15:58  
4#
瞧瞧看看
回复 收起回复
使用道具
狼之独步  发表于 2016-3-28 11:18:15  
5#
实时反射
回复 收起回复
使用道具
249318266  发表于 2016-3-28 18:16:57  
6#
瞧瞧看看
回复 收起回复
使用道具
至尊24  发表于 2016-4-9 21:14:05  
7#
哈哈哈哈哈哈哈
回复 收起回复
使用道具
Zh_Jason  发表于 2016-4-9 23:31:18  
8#
好资源~!点赞
回复 收起回复
使用道具
夜浅  发表于 2016-4-12 00:01:25  
9#
感谢分享{:1_144:}
回复 收起回复
使用道具
至尊24  发表于 2016-5-9 10:36:22  
10#
灌灌灌灌灌灌灌灌灌
回复 收起回复
使用道具
FAFA123  发表于 2016-5-10 13:26:03  
11#
6666666666666666
回复 收起回复
使用道具
枕头儿  发表于 2016-5-13 09:50:51  
12#

高端大气上档次
回复 收起回复
使用道具
mackyhung  发表于 2016-5-22 18:24:48  
13#
即时经典侠MMORPG手机游戏
回复 收起回复
使用道具
mackyhung  发表于 2016-5-22 18:24:59  
14#
即时经典侠MMORPG手机游戏
回复 收起回复
使用道具
mackyhung  发表于 2016-5-22 18:25:07  
15#
即时经典侠MMORPG手机游戏
回复 收起回复
使用道具
笑笑520  发表于 2016-5-23 09:00:55  
16#
{:1_145:}
回复 收起回复
使用道具
至尊  发表于 2016-5-24 21:18:46  
17#
啊啊啊啊啊啊

评分

参与人数 1活跃度 -20
成林 -20 这么水可不好哦.~论坛提供了便捷回复呢

查看全部评分

回复 收起回复
使用道具
蓦然的柔情  发表于 2016-6-16 10:11:24  
18#
学习了。我知道的是添加反射探测头,但是不能反射周围物体。。还有别的方法解决嘛?
回复 收起回复
使用道具
madmonkey  发表于 2016-8-5 09:19:13  
19#
根本看不懂啊,还是支持下,谢谢分享
回复 收起回复
使用道具
chen86723  发表于 2016-8-26 17:28:40  
20#
效果很高大上,虽然很想细入研究,但这向量题看得我头昏眼花
回复 收起回复
使用道具

快来发表你宝贵的意见吧!

成林 实名

通过了实名认证的内容创造者

unity3D

主题
181
精华
28
超神
5
扩散
750
微金
3000
智慧
220
余额
0
在线时间
5805 小时

【绝】结界玄晶 微库VIP 扩散者 紫色药水 学徒法袍 元素铜币 元素银币 元素金币 元素秘币 长剑 绿色药水 长枪 火元素

快速回复 返回顶部 返回列表