1 高级光线传播 Advanced Light Transport
虽然说是”高级“光线传播,但其实难度上并不比一定path tracing难,只是在计算机图形学入门这门课里不具体展开讲,不涉及到具体的计算,如果有兴趣可以自行研究
- 什么是有偏的,什么是无偏的 Biased vs. Unbiased
- 蒙特卡洛积分是一种无偏的算法,它没有系统误差 An unbiased Monte Carlo technique does not have any systematic error
- 如果无论样本多少,算出来的期望值永远是对的,那么我们就把它称为无偏的 The expected value of an unbiased estimator will always be the correct value, no matter how many samples are used
- 所有其他情况,算出的期望值有一定误差,我们称为有偏的 Otherwise, biased
- 特殊地,在有偏的情况下如果采样足够多的样本能够收敛到正确值,我们称为一致的 One special case, the expected value converges to the correct value as infinite #samples are used — consistent
1.1 无偏的光线传播方法 Unbiased
1.1.1 双向路径追踪 Bidirectional Path Tracing (BDPT)
- 之前做的路径追踪,是在用光路的可逆性,从相机开始产生路径,连接相机与光源 Recall: a path connects the camera and the light
- 双向路径追踪的方法是分别从光源和摄像机生成一系列半路径,然后再连接两个半路径的端点形成整条路径 BDPT: Traces sub-paths from both the camera and the light, Connects the end points from both sub-paths

比如下面这个场景,可以看到大灯是向上照射的,房间中的其他场景几乎都是由光源直接照亮的那一块墙壁漫反射出去的间接光照亮的。左图尽管每个像素跟踪了32条路径,但是这32条路径最终能成功弹射到光源表面的非常少,甚至是1条都没有,从而出现很多噪点,因为每次弹射都是随机选择1个方向进行下次弹射,光源的角度又比较苛刻,所以成功采样概率小。 右图采用双向路径追踪,对于这种场景就非常适用

这个算法也有缺点,速度很慢
闫老师说:BDPT看似简单,要实现正确是非常难的,如果能实现这个算法,手写一个渲染器都是没问题的
1.1.2 Metropolis光线传播 Metropolis light transport (MLT)
- Metropolis光线传播利用了马尔科夫链做蒙特卡洛积分 A Markov Chain Monte Carlo (MCMC) application
- 马尔科夫链是一种能在当前样本附近生成下一个样本的方法 Jumping from the current sample to the next with some PDF
- 使用马尔科夫链蒙特卡洛方法的好处是:在给定足够的时间下,可以以任意的函数为PDF生成样本,使得这些样本的分布就跟被积函数曲线一样。对比之前的以任意PDF进行采样,咱用的PDF是一条横线,所有样本的概率都是相等的。但是从结论来看,采用跟被积函数长得差不多的PDF使用蒙特卡洛积分效果最好(一条曲线函数,函数值大的点,其概率密度函数对应点采样到的几率也应该高一些)
- 使用马尔科夫链蒙特卡洛方法,给出一条路径可以稍加扰动地生成与这条路径相似的路径,这是一个局部(Local)的方法 Key idea: Locally perturb an existing path to get a new path

适用的场景:做复杂光路的传播
左图:光源从门外进来的,属于间接光照亮场景,但是光路更加复杂一些,此时用双向路径追踪效果不好,用MLT方法,只要找到一条,就能生成很多条类似的路径,从而提高渲染效果。
右图:这种Caustics现象,做路径追踪很难,摄像机出发,经过水面一次specular,打到水底会diffuse,再经过水面specular,最终连接光源。这种路径叫做SDS路径:specular-diffuse-specular非常难计算,中途采样次数特别多,也是很难采到一条正确的路径

Metropolis方法的缺点:
- 难以估计收敛速度,不知道要渲染多久 Difficult to estimate the convergence rate
- 所有操作都是局部的,不能保证每个像素的收敛速度相等,通常会产生图片比较“脏”的效果 Does not guarantee equal convergence rate per pixel, usually produces “dirty” results
- 所以我们通常不会用这个方法渲染动画,因为会出现上下两帧像素哪些收敛哪些没收敛不同,图像会”抖“的非常厉害

1.2 有偏光线传播方法 Biased
1.2.1 光子映射 Photon Mapping
- 非常适合渲染焦散(caustics)、Specular-Diffuse-Specular(SDS)路径

光子映射实现方法(很多方法中比较简单的一个):
Stage 1 — photon tracing:从光源发射光子,让它们在场景中多次反射与折射直到遇到漫反射表面,然后在漫反射表面上记录光子

Stage 2 — photon collection (final gathering):从相机射出一系列半路径,同样在场景中多次反射与折射直到到达漫反射表面
Calculation — 局部密度估计 local density estimation:我们认为光子分布的越多的地方越亮,遍历每个着色点,找到最近的 N 个光子(经典算法,利用树状结构加速),然后根据N个光子占据的面积计算光子密度
- 光子映射是一种有偏但是一致的方法 biased but consistent
- 局部估计出来的密度与实际的光子密度并不一样,所以是有偏的(Local Density estimation) \[ \frac{dN}{dA} \neq \frac{\Delta N}{\Delta A} \]
- 足够多的光子 → 相同的 \(N\) 个光子覆盖更小的 \(\Delta A\) → \(\Delta A\) 会逐渐接近 \(dA\),所以是一致的 More photons emitted → the same \(N\) photons covers a smaller \(\Delta A\) → \(\Delta A\) is closer to \(dA\)

这种渲染方法,其实就是模糊和噪声之间的平衡Photon Mapping存在的问题
光子数量N取小:充满噪声

光子数量N取大:模糊

为什么会有偏差?
渲染领域对于有偏无偏的理解 An easier understanding bias in rendering
- 有偏的结果相对于正确的结果会更模糊 Biased == blurry
- 一致的说明在样本足够多的情况下会收敛到正确结果 Consistent == not blurry with infinite #samples
- 如果取作色点周围固定的面积去数里面的光子数,那么它就永远不可能趋近与dA(无限小的面积微元),永远得不到一致的图像,那结果是即有偏也不一致的
1.2.2 顶点连接与合并 Vertex Connection and Merging (VCM)
主要还是采用双向路径追踪算法进行计算,但是其中某一个特殊的情况,我们对其进行光子映射的操作
当两个子路径的端点在同一个平面内,这两个路径其实在BDPT中就被放弃掉了,因为直接连接这两个点不满足光线传播规律啊(反射、折射)。
虽然不能连接,但可以合并这两个点,对这两条路径应用光子映射,认为光源那边的子路径发射的是光子,然后混合计算结果就是VCM方法了

1.3 实时辐射度 Instant Radiosity (IR / many light methods)
- 真实光源发出的光线打到场景表面后,这个被照亮的点就会被视作一个新的虚拟点光源,它会向四周继续发射光线,模拟间接光照(比如漫反射反弹)
- 相机看到的着色点,直接连真实光源算直接光,连所有 VPL 算间接光。实现了用直接光照的计算方法得到的间接光照的结果

- 优点: 计算速度快,通常在漫反射场景会有很好的表现
- 缺点: 不能处理光滑带镜面反射(Glossy)的材质;当光源离着色点特别近的时候会出现亮点。这是由于之前的渲染方程改良后,对光源采样代替了对半球上立体角采样,公式中,分母是光源上某个点到着色点的距离,当这个距离特别近,就会出现结果无限大的情况
目前工业界很多影视公司还在用path tracing,虽然听上去没那么高端,但是它是最可靠的
2 复杂外观建模 Advanced Appearance Modeling
2.1 非表面模型 Non-Surface Models
2.1.1 散射(参与)材质:云/雾 Participating media
参与介质:微观散射粒子的集合,也可以叫做散射介质
类似云、雾霾等,显然不是定义 在一个表面上的,而是定义在空间中的。
光线(直接or间接)会穿过介质,介质会吸收一定的能量,并且往外随机的朝各个方向散射能量。

比如下图这三种散射形式(向后散射、均匀向空间散射、向前散射)

参与介质的渲染方式:
其实可以理解成平面材质的渲染,只不过着色点不是击中平面某个点,而是参与介质中随机选择一个点。然后随机选择一个反射方向,随机选择前进多远,再选择某个点,重复进行直到光源,形成一个path。
- 随机选择一个方向反弹
- 随机选择一个行进距离,走多远由介质的吸收能力决定
- 在每个着色点,都连到光源,计算路径的贡献

散射介质的应用:影视、游戏中的云雾,很多的材质其实光线也会进入到内部,比如下面这个兔子也是应用散射介质渲染出来的,只是光进去物质内部比较少而已

2.1.2 头发/毛发/纤维 Hair / fur / fiber (BCSDF)
2.1.2.1 头发 Hair
对于头发也是非表面材质,因为它是一根一根的 ,所以我们要考虑光线如何和一根头发作用
(1)Kajiya-Kay Model(不常用)
- 一种比较简单的模型。光线击中细小圆柱,会被反射到一个圆锥形的区域中,同时还会进行镜面反射和漫反射。渲染结果并不真实

(2)Marschner Model(常用)
把光线与毛发的作用分为三个部分
R:在毛发表面反射到一个锥形区域。
TT:光线穿过毛发表面,发生折射进入内部,然后穿出再发生一个折射,形成一块锥形折射区域。
TRT:穿过第一层表面折射后,在第二层的内壁发生反射,然后再从第一层折射出去,也是一块锥形区域

一根毛发不仅要考虑直接光,还要考虑别的毛发反射过来的光线。利用Marschner Model,让光线和多根头发发生多次散射,一条路径可能就要经过几百上千根毛发。渲染困难,计算量大,但是效果很好

2.1.2.2 动物毛发 Fur
- 通过实践法线人的头发的模型并不能很好的模拟动物毛发的质感 Cannot represent diffusive and saturated appearance

从生物上的结构,头发/毛发分为角质,皮质以及髓质,对于动物来说,中间的髓质更大光线更容易发生散射

于是闫老师提出了双层圆柱模型 Double Cylinder Model,模拟了光线经过髓质的效果,使用了五个分量来模拟毛发,在《猩球崛起》《狮子王》中得到应用


2.1.3 颗粒材质 Granular Material

显式建模(Explicit Modeling):就是把每一颗颗粒都单独创建成独立的几何模型(比如每个沙粒都做一个小球模型)。这种方法精度高,但数量一多就会性能爆炸,完全不适合大规模场景。
程序化定义(Procedural Definition):不用逐个建模,而是在一个 “单元”(比如一个面片或体素)上用算法 / 规则去生成颗粒的外观和分布(比如用噪声函数、纹理采样来模拟颗粒感)。
目前仍没有很好的高效渲染这种材质的方法,仍然非常耗时,没有得到很广泛的应用
2.2 表面模型 Surface Models
2.2.1 半透明材质 Translucent Materia
次表面散射(Subsurface Scattering):光线从一个点进入材质,在表面的下方(内部)经过多次散射后,从其他一些点射出
区别于半透明:光线穿过物体时,方向基本不变,只是被吸收 / 衰减,像透过磨砂玻璃看东西:

双向次表面散射反射分布函数(BSSRDF)
次表面散射BSSRDF可以看作是BRDF的延申,因为BSSRDF光线从一个点进入,会因为入射irradaince的不同而从不同点射出
S(xᵢ, wᵢ, xₒ, wₒ)
次表面散射渲染方程
对具有次表面散射性质的表面材质,欲求解某个着色点在相机方向的Radiance,不仅要对该点的半球面上入射光的积分,还要考虑对该表面其他点的不同入射方向的光进行积分。
\[ L(x_0, w_0) = \int_A \int_{H^2} S(x_i, w_i, x_o, w_o)\, L_i(x_i, w_i) \cos\theta_i \, dw_i \, dA \]

以上计算比较复杂,因此又有一种近似的方法被提出
Dipole Approximation
- 引入两个点光源来近似达到次表面散射的效果

使用BSSRDF可以渲染出真实的次表面散射材质和真实的皮肤质感


2.2.2 布料材质 Cloth
- 布是由纤维缠绕而成的 A collection of twisted fibers
- 每一根 股(Ply) 是由 纤维(Fibers)缠绕而成
- 每一根 线(Yam)是由 股 (Ply) 缠绕而成
- 然后由线机织或针织成布 Woven or knitted

我们当成表面渲染,根据不同织法给出不同的BRDF Given the weaving pattern, calculate the overall behavior, Render using a BRDF

如果当成表面渲染意味着我们没法渲染类似天鹅绒的材质

我们也可以通过单根纤维的特性即分布推算出散射参数,向渲染云那样的散射介质一样来渲染布料,这样计算量很大

我们也可以把每一根纤维都渲染出来,当然计算量非常恐怖 Render every fiber explicitly!
2.2.3 细节模型 Detailed Appearance
现在的渲染看起来太过完美,并不真实,现实世界的的材质是复杂的 Real world is more complicated

微表面模型中最重要的是它的法线分布,但是我们描述这个分布用的都是很简单的模型,比如正态分布之类的,真实的分布要更复杂

- 真实的法线分布基本符合统计规律,但是又有一些细节

如果使用法线贴图来把这些起伏细节都定义出来,会非常耗时 Rendering? Too difficult!

使用路径追踪困难的点在于,微表面的镜面反射在法线分布复杂的情况下,很难建立有效的的光线通路从相机出发打到光源

- 一个像素会覆盖很多微表面,我们可以把一个像素内的法线分布算出来,替代原本光滑的分布用在微表面模型里
- 在不增加几何复杂度的前提下,还原真实材质的光照细节
- 简单说,就是用「统计分布」代替「逐个微表面」,解决性能和视觉真实感之间的矛盾。
- 小范围的P-NDF(Pixel-Normal Distribution Function)会呈现很独特的法线分布,不同的P-NDF也会呈现不同的分布特点

- 拉丝金属的高光、海面上波光粼粼、雪地上闪闪发光的效果都可以用这种方法
- 但是当尺度足够小时,就要考虑到光的波动性,比较复杂,本课不涉及
波动光学的BRDF结果与几何光学类似,但由于干涉出现不连续的特点

2.3 程序化生成外观 Procedural Appearance
其实意思更多的是不生成,需要用的时候再查询
利用三维空间中的噪声函数指导材质的生成,可以进行动态查询
我们可以定义一个三维的纹理,但是存一个三维的体积比一张图要大很多,因此我们不存,什么时候用,什么时候查,输入XYZ到一个噪声Noice函数。由于这是一个空间函数,所以你甚至可以做到当模型被破坏时,再生成截面、内部的纹理
应用:车绣效果、程序化地形、水面、木头纹理(木头内部也有纹理可随意切割)








