上个月学习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的缩写

图 1


推导过程

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

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

推导思路:
将 \(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\) 可表示为:

(求 \(\operatorname { perp } _ { \mathrm { N } } \mathbf { L }\) 的过程有点像施密特正交化的过程,都是一个向量去除某个方向的分量,除以 \(\sin \theta _ { \mathbf { L } }\) 即标准化为单位向量)

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

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

将 \(\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 } }\) 代替:

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

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

其他

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

参考文献

  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.

折射向量计算(Refraction Vector Calculation)的更多相关文章

  1. 【3D数学基础】三维空间折射向量计算

    问题:在三维空间中,已知折射率 e .入射角 L 和法线 N. 要求:计算出折射向量 T. 其中: L. N 和 T 都为单位向量. 如图片所示,下面所有的公式都看着这张图片来求解的: 首先,我们必须 ...

  2. 由浅入深学习PBR的原理和实现

    目录 一. 前言 1.1 本文动机 1.2 PBR知识体系 1.3 本文内容及特点 二. 初阶:PBR基本认知和应用 2.1 PBR的基本介绍 2.1.1 PBR概念 2.1.2 与物理渲染的差别 2 ...

  3. shader函数

    Intrinsic Functions (DirectX HLSL) The following table lists the intrinsic functions available in HL ...

  4. unity shader 常用函数列表

    此篇博客转自csdn的一位大牛. 中间排版出了一些问题 Intrinsic Functions (DirectX HLSL) The following table lists the intrins ...

  5. DirectX HLSL 内置函数

    Intrinsic Functions (DirectX HLSL) The following table lists the intrinsic functions available in HL ...

  6. HLSL Shader编程基础总结

    转自:https://blog.csdn.net/Blues1021/article/details/47093487 基本前提概念 Shader是一种映射到GPU硬件汇编语言上的高级语言,Shade ...

  7. 【SIGGRAPH】用【有说服力的照片真实】技术实现最终幻想15的视觉特效

    原文:西川善司 http://www.4gamer.net/games/075/G007535/20160726064/   最终幻想15的演讲会场.相当大,听众非常多.      在本次计算机图形和 ...

  8. Nvidia Anisotropic Lighting

    http://http.download.nvidia.com/developer/SDK/Individual_Samples/DEMOS/Direct3D9/HLSL_Aniso.zip Anis ...

  9. Nvidia VertexTextureFetch Water

    http://http.download.nvidia.com/developer/SDK/Individual_Samples/samples.html http://http.download.n ...

随机推荐

  1. c语言-遍历pci设备(2)mmio访问

    前言 今天其实我在公司也没有做什么,但是昨天就把pcie遍历的mmio形式做了出来,赞扬公司的台湾服务器,至少我可以使用google来去搜索我想要的资料和答案,有一位大神在台湾的论坛上发布了一片博文, ...

  2. Java源码阅读(不断补充)

    java.util.LinkedList LinkedList是实现了List接口的双链表实现,拥有list的所有方法并且允许所有元素(包括null). 双向链表也叫双链表,是链表的一种,它的每个数据 ...

  3. 原型模式Prototype,constructor,__proto__详解

    最近由于在找工作,又拿起<JavaScript高级程序设计>看了起来,从中也发现了自己确实还是有很多地方不懂,刚刚看到原型模式这里,今天终于搞懂了,当然,我也不知道自己的理解是否有错. 1 ...

  4. 【PAT 甲级】1151 LCA in a Binary Tree (30 分)

    题目描述 The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has bo ...

  5. 并发编程之 Fork-Join 分而治之框架

    前言 "分而治之" 一直是一个有效的处理大量数据的方法.著名的 MapReduce 也是采取了分而治之的思想.简单来说,就是如果你要处理1000个数据,但是你并不具备处理1000个 ...

  6. Windows 忘记登录密码解决方法 【摘抄于百度】

    一.简单的方法: 开机启动windows,进入欢迎界面后,会出现输入用户名密码提示框,这时候,同时按住Ctrl+Alt+Delete,会跳出一个账号窗口,输入用户名:administer,按回车即可. ...

  7. 在.net中序列化读写xml方法的总结--转载过来学习学习

    原文章地址:http://www.cnblogs.com/fish-li/archive/2013/05/05/3061816.html 首先做个大概的总结,XML包括的元素有XmlElement,X ...

  8. Java - Iterator源码解析

    java提高篇(三十)-----Iterator 迭代其实我们可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类,它是一个很典型的设计模式.Iterator模式是用于遍历集合类的标准 ...

  9. 数据库导入导出expdp,impdp

    数据库操作 (1)数据库导入导出expdp,impdp 在导入导出数据库的时候,经常会用到exp和imp,在数据量小的情况下可以随意使用,但是当数据量大,表中数据有百万,千万条的时候,就要等好久好久好 ...

  10. innerHTML在ie9有部分无法添加

    在高版本的浏览器,innerHTML就如正常时候,里面可以套任何字符串,但是在ie9下,innerHTML不能是table ,tr td等标签字符串,解决方法如下: 在table添加一个tr var ...