上个月学习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. http server 简单实现

    本blog主要是模仿http server的实现,使得客户端使用浏览器访问server所指定的目录. 当访问的为一个目录时, 则列出改目录下的所有文件 当访问的是文件时,则下载文件到本地 本log仅仅 ...

  2. 原本在滴滴只负责批100万元以上开支的Leslie决定,ofo所有30万元以上的开支都要由她亲自过目。那段时间,他“天天晚上12点才下班,眼睛都熬红了”

    戴威即将28岁了,熟悉他的人更愿意用“孩子”来形容他. 这样的特质,在追随者眼中,是天真.纯粹.理想主义:在合作伙伴眼中,是倔强高傲.不可一世:在投资人眼中,则是任性狂妄,一味蒙眼狂奔.他像个无意间闯 ...

  3. 并发编程之 ConcurrentHashMap(JDK 1.8) putVal 源码分析

    前言 我们之前分析了Hash的源码,主要是 put 方法.同时,我们知道,HashMap 在并发的时候是不安全的,为什么呢?因为当多个线程对 Map 进行扩容会导致链表成环.不单单是这个问题,当多个线 ...

  4. [日常] PHP与Mysql测试kill慢查询并检验PDO的错误模式

    <?php try{ //1. pdo的错误模式,抛出异常,不记录到php的error日志,不影响代码继续运行, $opts=array( PDO::ATTR_ERRMODE => PDO ...

  5. CSS学习笔记04 CSS文字排版常用属性

    字体样式属性 font-size:字号大小 font-size属性用于设置字号,该属性的值可以使用相对长度单位,也可以使用绝对长度单位.其中,相对长度单位比较常用,推荐使用像素单位px,绝对长度单位使 ...

  6. Java - Iterator源码解析

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

  7. C#进行数据筛选(二)

    这里介绍LINQ+Lambda表达式进行数据筛选的方式 这里是第一种方式,还是使用了if条件语句去判断,根据选择的条件去筛选出我所需要的数据 public GxAnaly SelectDay(stri ...

  8. -C++11可变模版参数(转载)

    泛化之美--C++11可变模版参数的妙用 1概述 C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意 ...

  9. 查看centos操作系统、java_jdk、hadoop位数

    1.centos操作系统位数: file /bin/ls 此为64位 2.java jdk 位数: java -version 这个是64为的,若是没有,则默认为32位 3.hadoop位数: 进入h ...

  10. js之展开收缩菜单,用到window.onload ,onclick,

    目标效果:点击标签1,如果列表标签的style的display是block,改成none,否则改成block,来达到展开收缩菜单效果 一.准备阶段 html文件 <!DOCTYPE html&g ...