一、说明
秦春林的《全局光照技术:从离线到实时渲染》2018年6月第1版的6.5.1光线微分这一节中,对光线微分的概念阐述不够清晰和准确,这里做一个纠错笔记,同时也是自己的学习记录。
可通过文中的【表述不清晰】【纠错】高亮标签快速查找纠错信息。
二、理论提出(推导)
《全局光照技术》一书的6.5.1节的理论推导部分主要参考的是[Igehy, 1999]这篇,但在阅读中发现很多地方前后逻辑不顺畅,甚至有些地方无法正确推导,所以把原论文翻出来看了一下。读了之后发现原书省略、修改、杂糅了部分公式(杂糅的主要是PBRT里的公式),并且部分公式原书解读得并不正确,现在在这里做一个简单的梳理。
1、什么是光线微分?
先来看论文里的一张图,相较原书的图6.18,这张更易于理解。
图中的R是光线的表达式,包含P(位置)和D(方向)两个量(懒得打公式了,下面截了一张论文里的定义段落)。最基础的光线追踪,屏幕空间上的一个位置只对应一条光线,也就是R(x),光线微分就是给原本的一条光线(下称中心光线)加了两个小跟班,分别在屏幕空间上水平方向和垂直方向偏移一个单位,上图中只绘制了水平方向偏移的跟随光线。
为什么要多算这两条线呢?是为了更好地在局部(物体表面 / 纹理空间)进行采样,为了反走样。这也是为什么原书把光线微分放在6.5纹理过滤这一节里。
2、什么是光线足迹(ray's footprint)?
原书在介绍光线微分是什么和怎么计算过程中,多处提到光线足迹一词,但不同处的表达又有些微妙的不同:
P311 第四行:在路径的每个顶点处,该光线微分与表面的交点同中心光线的交点的距离用来近似该顶点的足迹。
P312 第二段第二行:如图6.18所示,所以光线的位置分量的微分和就能够表示每个顶点的足迹。
【表述不清晰】P311的表达中,“距离”和“足迹(footprint)”这两个词能够划等号,一度让我非常困惑。 按照我的理解(可能不一定准确),光线足迹表示的是中心光线和跟随光线与物体表面的交点(一共是3个)所构成的能够进行采样的整个区域。传统光线追踪中,光线与表面的相交信息只局限于一点,用了光线微分技术之后,相交扩大为一个区域,就好像光线走过留下一个个脚印,所以叫这个区域为光线足迹?(猜的哈,我觉得挺有道理hhh
3、怎么计算光线微分?
光线微分通过一阶泰勒近似来进行计算,论文的公式如下图所示。同时论文还举例计算了光线从相机位置(眼睛为之Eye)发出时最初的微分值,公式(5)在上一张截图中有写。
【纠错】原书中的公式6.29只列了位置P的一阶泰勒近似,但第一个P用了P',这个是错的,泰勒展开针对的同个函数。
4、光线微分的传播
这部分的公式非常混搭,杂糅了PBRT和[Igehy, 1999],导致了解释的错位。先来看一下论文里的公式:
【纠错】与原书的最大区别是公式(11),在书中是公式6.33,书里的公式6.33是这样的(这一页已经被我涂得乱七八糟了,就不拍照了:D): ,这个t值的表达与前面公式6.32的平面方程一起,使用的是PBRT中第10章节的表达。PBRT中的表述在上下文语境下非常直观清晰,但插在这里,替换了论文的公式(11)的表达,严重影响公式(12)也即书中公式6.34的推导。事实上我就是看书推不出公式6.34,才翻原论文来看的。
那么这两种表达明明不相等,为什么都对呢?因为PBRT中法向量N是一个三分量的向量,但是论文里的N是齐次坐标下的四分量向量,应该说是论文里的推导全部是在齐次坐标系下进行的。所以同样的平面方程,PBRT和原书中的表达是ax + by + cz + d = 0, N = (a, b ,c), P'在平面上,NP' + d = 0,其中P' = P + tD,即N(P + tD) + d = 0,从而推导出了公式6.33的表达。但论文里可以直接表述为N(P + tD) = 0,从而推导出公式(11)。
【纠错】同时作者对公式6.34(即论文公式12)的推导说明有错误:
正确的推导过程如下,简单地说就是对求偏导,然后再用替换一部分变量,简化表达:
另外,因为作者错误地理解了这一段的公式推导,导致作者对“两条跟随光线与物体表面的交点”的计算流程理解有错误,在下一节重点介绍。
三、光线微分实现
这部分内容参考的是PBRT第10章的第一小节,只截取介绍一下光线微分的传递,反射和折射大家可以自己去看。其实截出来的这部分已经讲得很清楚了(第一次看PBRT这本书,被行文风格友好哭了,代码配合公式,当前没办法详细展开介绍的代码段落用文字概括,并标注详细介绍的段落页面,真的太友好了QAQ)。需要纠正原书的是下面这段表述:
P314 倒数第二段:
为了计算两条光线微分的t值,我们首先需要计算出平面隐式函数中的d值。这是通过中心光线来计算的,因为中心光线的相交计算会得到中心光线与表面相交的t值,将中心光线的值代入上式就可以求出平面隐式函数中的值,然后在给定两条光线微分的起点位置和方向的情况下,就可以求出两条光线微分与同一平面相交对应的值。
【纠错】首先,光线与物体表面的求交计算,得到的应该是法线和交点位置,不会直接得到当前交点与上一交点的距离(也就是),关于值怎么求,截图中说得很清楚, 。所以正确的计算流程应该是,①求交计算得到、→ ②计算得到 → ③计算得到(代码段中的tx、ty)→ ④计算得到两条跟随光线与表面的两个交点位置(代码段落中的px、py)→ ⑤计算得到、 (代码段落中的dpdx、dpdy)。其中第④步的计算有个重要的近似,即,计算中两条跟随光线的值等价于中心光线的值,这也是《全局光照技术》原书中表述错误的地方(原书的逻辑是先得到中心光线的,计算的到,再计算得到跟随光线的)。需要注意,截图中PBRT中的对应的是论文里的,即,当前计算的中心光线与物体表面的交点。
【纠错】同样的,P315-316所写的计算思路,也是同样的问题,不再赘述。
看PBRT这一段的时候,个人比较疑惑的是,PBRT中的计算流程与论文中的不太一样,论文中计算流程是:
-
已知、、、 → 计算得到 → 计算得到 → 计算得到。
对比之下PBRT的计算流程是:
-
已知、 、、→ 计算得到 → 计算得到 → 计算得到,也即。
注意,这里用【'】区分当前相交的信息与上一次相交的信息。也就是说,上面段落中PBRT的实际上等价的是这一段落中的,即表示当前中心光线与表面的交点,表示的上一次相交时的中心光线与表面的交点。对应PBRT中的代码段落, 即 , 即 。原书P312、313也放了PBRT中光线微分的数据结构定义,这里不再截图。
为什么采用不一样的计算流程?个人猜测分析,论文的计算流程中,中心光线与物体表面的交点位置信息(即)不是用在当前的光线微分计算,而是用在下一次相交的光线微分计算中,这一特性在数据记录存储上不够直观。
四、参考资料
《全局光照技术:从离线到实时渲染》秦春林 2018年6月第1版
《Tracing ray differentials.》Igehy, H. (1999). SIGGRAPH '99 Proceedings
《Physically Based Rendering Third Edition》