折射向量计算(Refraction Vector Calculation)

1226925-20190115214627272-970207118.png

上个月学习Peter Shirley-Ray Tracing in One Weekend的系列三本书,收获真的很多。这个系列的书真的是手把手教你如何从零开始构建一个光线跟踪渲染器,对新手(像我)非常友好。但是书中有很多章节需要有一定的数学功底才能看懂,本文想分享一下关于in One Weekend-chapter 8:Metal中一笔带过的折射公式推导,内容主要来自于《Mathematics for 3D Game Programming and Computer Graphics, 3rd Edition》[1],加上我个人的理解,如有错误,欢迎指出。

(配图为raytracer构建后渲染)


问题简述

已知入射向量 \(L\) 和交点法线 \(N\),和入射光线所在介质折射率 \(\eta _ { \mathrm { L } }\) 及折射光线所在介质折射率 \(\eta _ { \mathbf { T } }\) ,求折射向量 \(T\)。如图:

  • 设入射角为 \(\theta _ { \mathrm { L } }\) ,折射角为 \(\theta _ { \mathbf { T } }\)
  • \(L\)\(N\) 已经标准化为单位向量,所求 \(T\) 也为单位向量
  • 注意此处 \(L\) 的方向指向外,保留与书上一致(实际入射方向应为\(-L\))
  • L、T可以理解为light和transmission的缩写
1226925-20190115225200863-1896909595.png

图 1


推导过程

(若推导过程感觉理解困难可以先考虑二维情况再考虑三维,其实入射光线和折射光线都在一个二维平面上)

关键公式:折射定律或斯涅尔定律(Snell's Law),用于计算折射角 \(\theta _ { \mathbf { T } }\) :
1226925-20190115221154227-146542157.png

推导思路:
\(T\) 分解为平行于 \(N\)(-\(N\)) 和垂直于 \(N\) 的向量 (\(-G\)),见图 1。(用这两个向量的线性组合\(a*-N+b*G\)表示 \(T\),问题就在于求两个系数a、b和向量 \(G\),将问题转换为求\(a\)\(b\)\(G\)

1. 求 \(a\)

\(a\)实际上就是求向量\(T\)在向量\(-N\)上的投影,利用点乘公式即可计算出\(a=\cos \theta _ { \mathrm { T } }\),由于所求 \(T\)\(-N\) 都为单位向量,所以其点乘展开式最终化简为\(\cos \theta _ { \mathrm { T } }\)

\(T \cdot (-N) = |T| |-N| \cos \theta _ { \mathrm { T } }=\cos \theta _ { \mathrm { T } }\)

\(T \cdot (-N) = |-N|\cdotp Proj = Proj\)

联立上式即可

2. 求 \(b\)

基本思路和求 \(a\) 一样,这里求出 \(b = \sin \theta _ { \mathrm { T } }\)

(实际此处先求出的是cos<T,-G>,根据由于垂直关系,两角互余,等值于 \(\sin \theta _ { \mathrm { T } }\) )

3. 求 \(G\)

\(G\)\(\operatorname { perp } _ { \mathrm { N } } \mathbf { L }\)平行(\(\operatorname { perp } _ { \mathrm { N } } \mathbf { L }\)\(L\)垂直于\(N\)的分量,见图 1),由于 \(L\) 为单位向量,\(\left\| \operatorname { perp } _ { \mathbf { N } } \mathbf { L } \right\| = \sin \theta _ { \mathbf { L } }\)\(G\) 可表示为:
1226925-20190115212829319-330888519.png
(求 \(\operatorname { perp } _ { \mathrm { N } } \mathbf { L }\) 的过程有点像施密特正交化的过程,都是一个向量去除某个方向的分量,除以 \(\sin \theta _ { \mathbf { L } }\) 即标准化为单位向量)

4. 所以 \(T\) 可以表示为:

1226925-20190116224059288-356864691.png

利用斯涅尔定律替换\(\frac { \sin \theta _ { \mathrm { T } } } { \sin \theta _ { \mathrm { L } } }\):

1226925-20190116223953818-1421109792.png

\(\cos \theta _ { \mathrm { T } }\)\(\sqrt { 1 - \sin ^ { 2 } \theta _ { \mathrm { T } } }\)代替,\(\sin \theta _ { \mathrm { T } }\)\(\left( \eta _ { \mathrm { L } } / \eta _ { \mathrm { T } } \right) \sin \theta _ { \mathrm { L } }\) 代替:

1226925-20190117110618599-988810617.png

最后,将 \(\sin ^ { 2 } \theta _ { \mathrm { L } }\)\(1 - \cos ^ { 2 } \theta _ { \mathrm { L } } = 1 - ( \mathbf { N } \cdot \mathbf { L } ) ^ { 2 }\) 带入可得最终 \(T\) 的表达式:
1226925-20190117111244735-831217185.png

(如果 \(\eta _ { \mathbf { L } } > \eta _ { \mathbf { T } }\),方程式中根号内的量可能为负,光线发生全反射,应用反射公式计算向量方向。即当 \(\sin \theta _ { \mathrm { L } } \leq \eta _ { \mathrm { T } } / \eta _ { \mathrm { L } }\),上式才可用于计算折射向量。)

其他

最后放一张in one weekend中计算折射向量的函数,参数 v 即为入射光线方向,只要将上诉公式加以对照即可写出。(记得上述 \(-L=v\))

1226925-20190117111644352-691250189.png

参考文献

  1. Eric Lengyel. Mathematics for 3D Game Programming and Computer Graphics, 3rd Edition. Course Technology PTR, 2011.
  2. Peter Shirley. Ray Tracing in One Weekend. Amazon Digital Services LLC, January 26, 2016.

转载于:https://www.cnblogs.com/theWhisper/p/10269574.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值