高级渲染主题
高级光线传播
高级光线传播方法有如下几种:
无偏光线传播方法
Bidirectional path tracing(BDPT):双向路径追踪;
Metropolis light transport(MLT)。
有偏光线传播方法
Photon mapping:光子映射;
Vertex connection and merging(VCM)。
Instant radiosity(VPL / many light methods)
有偏与无偏蒙特卡洛估计
无偏(Unbiased)蒙塔卡洛估计指的是不论我们选取多少样本进行估计,得到的期望值和正确值一样。
有偏(Biased)蒙特卡洛估计指的是如果我们取样后得到的估计值与要预测的真实值是有偏差的,那么我们认为这是一个有偏估计。当我们采样足够大的的时候,有偏估计也可以收敛到正确值,这说明了有偏估计具有一致性(consistent)。
Bidirectional Path Tracing
BDPT 指的是我们分别从光源和眼睛(摄像机)引出半路径,并将半路径的终点连接起来形成路径。这种方法非常适用于光源出光线比较复杂的情况。但是实现困难并且渲非常慢,是一种无偏的估计。

Metropolis Light Transport
MLT 使用使用马尔可夫链的方法进行采样:从当前采样点依据某种 PDF 跳到下一个采样点。
这种采样方式可以很容易的采样到某一个采样的临近点。其主要思想是,当一条路径可以到达光源时,那么临近的采样也应该容易到达光源。非常适用于困难场景的渲染,尤其是 SDS(Specular-Diffuse-Specular)路径。
但是很难估计收敛速度,每一个像素的收敛速度也不一样。操作独立,各个像素独立导致画面会比较「脏」,因此很难应用到动画上。MLT 也是无偏估计。

Photon Mapping
光子映射是一个分为两步的方法。是一种有偏估计。适合于 SDS 路径以及焦散(caustics)材质。
- 从光源出发射出光子,当光子反射到漫反射平面时停止,记录光子位置;
- 从摄像机射出半路径,直到路径反射到漫反射平面上。
我们需要通过局部密度估计在计算单位面积内,光子数的多少。那么光子密度越高的地方应当越亮。对于任意一个点,我们选取临近 \(N\) 个距离最近的光子,那么使用 \(N\) 处以光子所占的面积 \(\Delta A\) 就可以得到该就可以得到该 点的局部密度。

为什么这是一个有偏的方法?我们 \(N\) 太少的话易产生噪声,但是 \(N\) 太多又会模糊。当我们使用的光子足够多的时候,\(\Delta A\) 就趋近于 \(\mathrm{d} A\) 因此,只要我们的采样是有限的,得到的密度多少都会有偏差,所以这是一个有偏的估计。但是这是一致的估计。
Vertex Connection and Merging
VCM 是一种结合了双向路径追踪和光子映射的方法。其主要思想是在双向光线追踪中如果半路径的结束点并不在一起但是距离比较近的话可以组合在一起。使用光子映射的方法来组合这些临近的「光子」。是一种有偏估计。

Instant Radiosity (IR)
IR 最主要的思想是认为被照亮的表面可以当作一个小光源。从光源打出来的地方到一些表面后,到达点就是新的虚拟光源。之后就可以将这些虚拟光源看作光源进行渲染。优点是渲染速度快并且在漫反射场景中表现的很好;缺点是不能很好的处理反射材质。

高级外观建模(Advanced Appearance Modeling)
此节会介绍:
- Non-surface models(非表面模型)
- Participating media(散射介质)
- Hair / fur / fiber (BCSDF)(毛发)
- Granular material(颗粒材质)
- Surface models(表面模型)
- Translucent material (BSSRDF)
- Cloth(织物)
- Detailed material (non-statistical BRDF)
- Procedural appearance
Non-surface models
Participating media
对于一些散射介质,例如云、雾,我们认为他们是非表面模型。因此他们不存在一个表面,而是由许多散射小颗粒组成的。任何一束光通过散射介质,会发生(部分)吸收或者散射。

我们采用相位函数(Phase Function)去描述在某一点光的散射和散射角度的关系。

再渲染散射介质时:
- Randomly choose a direction to bounce;
- Randomly choose a distance to go straight;
- At each 'shading point', connect to the light.

Hair / fur / fiber
光线与头发的作用不是简单的光线和表面的作用,首先视头发为一个圆柱体。
在 Kajiya-Kay 模型中,我们认为一束光射到头发上后,头发会将光线散射为一个圆锥。Kajiya-Kay 模型做出来的效果并不好。

在 Marschner 模型中,我们认为头发是一个能够透光的「玻璃」,光线应该分为三部分,分别是:
- R:光线直接反射光;
- TT:光线经过两次折射后射出的折射光;
- TRT:光线折射后经过一次介质内反射后的折射光。

以上的模型对于人类的毛发已经有了很好的表现,但是对于动物毛发来说,表现并不好。这是因为动物的毛发并不是单层的结构。动物毛发中包含一层毛髓质(Medulla),因此引入双层模型(Double CylinderModel)来对毛发进行建模。

在这个模型中我们额外增加了两种光:
- \(\text{TT}^{\text{s}}\):经过了中间介质的 TT 光线;
- \(\text{TRT}^{S}\):经过了中间介质的 TRT 光线。
这样 5 种光线结合在一起得到的毛发会更加的真实。
Granular Material
粒状材质是由细小的颗粒组成的材质,例如谷物,沙子,调味料等。这样的材质也有程序化的方法进行渲染。

Surface models
Translucent Material
Translucent 材质指的是能够透光的一些材质,光线可以从一个地方进去并从另一个地方出去。例如玉石,水母都是典型的 Translucent 材质。
一条光在半透明材质上入射后,出射光的起点并不一定在入射点上(Subsurface Scattering),因此我们需要对 BRDF 进行拓展。

此时 BDRF 就变成了 BSSDRF,此时我们需要引入新的位置参数,我们不仅要对角度进行积分。BSSDRF 的定义为: \[ S\left(x_i,\omega_i,x_o,\omega_o\right) \]
渲染方程要修正为: \[ L\left(x_o,\omega_o\right) = \int_A\int_{H^2}S\left(x_i,\omega_i,x_o,\omega_o\right) L_i\left(x_i,\omega_i\right) \cos \theta_i \, \mathrm{d} \omega_i \, \mathrm{d} A \]

我们会等效的认为,一个半透明材质上有一束光摄入相当于在介质的外部和内部各有一个光源。

Cloth
织物的制作工艺比较的复杂。首先,多层(Ply)缠绕会变成一根纱(Yarn),多根纱相互缠绕就会变成一根线(Fiber)。

我们可以使用两种编织工艺,一种是机织(Woven),通过线之间的经纬交叉得到布料,另一种方式是手打(Knitted)的方式,类似于织毛衣的过程。

不同的布料有不同的 BDRF,常见的渲染方法有:
- Render as Surface
- Given the weaving pattern, calculate the overall behavior
- Render using a BRDF
- Render as Surface
- Render as Participating Media
- Properties of individual fibers & their distribution -> scattering parameters
- Render as a participating medium
- Render as Actual Fibers
- Render every fiber explicitly
对于天鹅绒材质等布料,使用 BDRF 并不合适。
真实世界模型
现在的渲染器渲染出的画面并不真实,主要原因是这些渲染器过于完美。在实际生活中的物体一般表面都会带有划痕,会让物体表面看起来更真实。

我们可以用微表面模型的发现分布来解决这种情况。我们只需要在微表面模型的分布上加一些噪声,就可以产生带有划痕的效果。但是,在这样的法线分布下,光线很难反射到光源处。

因此,我们的解决方案是,我们对于每一个像素,对应一部分法线分布 \(\mathcal{P}-\mathrm{NDF}\),使用这一部分的法线总体分布进行路径追踪。

此外,目前研究比较前沿的问题还有波动光学(Wave Optics)的渲染。
程序化生成
程序化生成(Procedural Appearance)指的是我们可以不定义一个纹理,而是直接定义一个噪声,通过噪声计算纹理。木纹,陶瓷都可以定制对应的纹理进行程序化的生成。
不仅可以定义 2 维的噪声,也可以定义 3 维的噪声,在将物体切割时,3 维噪声会将切面的纹理动态地计算出来。
例如下面这个噪声函数:
1 | if noise(x, y, z) > threshold: |