高级渲染和材质概述
这一节的内容涉及许多比较复杂的高级渲染方法和材质的知识,只做了解,增长见识,如果以后对哪方面需要深入学习可以方便查找。
1 无偏方法和有偏方法
所谓无偏(Unbiased)方法是指利用无偏蒙特卡洛估计的光线传播方法,无偏是指无论采样点多与少,最终得到的估计的期望是正确的;那自然有偏(Biased)就是指估计的期望和真实值有偏差,但如果随着采样点数量增多,估计的期望最终会收敛到正确的期望,那么称这样的估计是有偏但一致(consistent)的。
2 无偏光线传播方法
2.1 双向路径追踪(Bidirectional Path Tracing)
路径追踪是从相机投射光线,BDPT 是既从相机又从光源投射出光线,称为半路径,对两条半路径进行追踪,最后将两条半路径的端点连接起来形成一条通路:
当然实现起来非常困难且速度极慢,但是这种方法能够产生一些传统路径追踪难以采样到的光路,所以能够很有效地降低噪声,对于光线在光源附近传播比较复杂的场景来说,效果会非常好:
2.2 Metropolis 光线传播
路径追踪中一个核心问题就是怎样去尽可能多的采样一些贡献大的路径,而 MLT 方法可以自适应的生成贡献大的路径。简单来说它会避开贡献小的路径,而在贡献大的路径附近做更多局部的探索,通过特殊的变异方法,生成一些新的路径,这些局部的路径的贡献往往也很高。与双向路径追踪相比,MLT 更加鲁棒,能处理各种复杂的场景。比如说整个场景只通过门缝透进来的间接光照亮,此时传统的路径追踪方法因为难以采样到透过门缝的这样的特殊路径而产生非常大的噪声。
MLT 是马尔科夫链蒙特卡洛估计(Markov Chain Monte Carlo)的应用,我们知道蒙特卡洛估计以不同的概率密度函数采样得到的结果是不同的,理论上来说概率密度函数分布和被积函数分布一致的时候,得到的估计值最准确,马尔科夫链可以通过一个样本在其附近推导出另外一些样本,并且尽量使这些样本的分布和被积函数分布相似。
MLT 可以通过一条已知光路推导出其附近的其他光路进行渲染:
这种方法对一些光线传播极其复杂的场景效果很好:
缺点是无法确定什么时候会收敛,并且由于每个像素是独立计算的,每个像素的收敛时间也不同,因此有时渲染的结果会显得比较“脏”:
3 有偏光线传播方法
3.1 光子映射(Photon Mapping)
光子映射非常适合渲染 caustics 情景,就是光线聚焦产生的现象,比如:
再比如之前见过的水面在阳光下会有很明亮的纹路,这都是由于光线聚焦产生的。
光子映射首先 追踪从光源放射出的所有的光子,当光子打到漫反射表面的时候就停下,停留在当前位置,然后追踪从相机射出的光线,同样打到漫反射表面就停下:
这样对于每一个相机射出的光线所到达的位置,取其周围 N 个光源发出的光子,然后利用这些光子数量除以他们围成的面积,就可以得到当前位置的光子密度,光子密度越大的地方自然也就越亮。
但是由于我们是用光子数量除以面积,但实际上面积应该是一个非常小的面积的时候,这样的除法才能代表密度,因此这只是对密度的近似,所以是一个有偏估计,但是当我们射出的光子足够多的时候,所取得 N 个光子所围成的面积也会足够小,这时得到的密度就是无限接近正确密度,因此这个方法是有偏但一致的。
体现到渲染结果上,如果 N 取得非常小,那结果噪声就会很大,因为偏差很大,如果 N 很大,得到的结果就会很模糊,这是因为方法本身是有偏的,有偏体现的图像上就是模糊:
因此我们说:
3.2 Vertex Connection and Merging
VCM 是一种应用非常广泛的光线传播算法,结合了双向路径跟踪和光子映射。
3.3 实时辐射(Instant Radiosity)
IR 的核心思想非常简单,把每一个被光源间接照亮的点都当成新的光源。渲染其他点时考虑所有这些虚拟光源,这样相当于考虑了光线的多次弹射,因此只需要用计算直接光照的方法就可以得到间接光照的结果。
这种方法效率高,效果也不错,但无法渲染 glossy 反射,并且有时边缘会莫名发光,这和采样时积分转换过程有关,这里不展开讨论。
4 高级材质
4.1 散射介质
散射介质(Participating Media)也叫参与介质,是指云、雾一类的会对光具有散射作用的介质。
我们可以把他们当成空间中的颗粒,光线传播到每个颗粒上时,会有一部分被吸收,有一部分发生散射:
因此只要描述颗粒吸收光线和散射光线的性质就可以,吸收光线由散射介质的性质决定,比如乌云就会吸收大量光导致光线传播不出去,而散射性质由相位函数(Phase Function)来描述,相位函数描述一个颗粒散射的时候向各个方向会散射多少,有的是均匀散射,有的向前方散射多后方散射少:
渲染的时候我们可以假设光线向前传播一段距离就会发生一次散射,具体传播多远由介质性质决定,具体怎么散射由相位函数决定,然后最终到达光源,将光源和所有散射点链接,计算每个散射点的着色就可以形成云雾透过光线的效果:
4.2 毛发材质
毛发材质的渲染最早采用的是很简单的方式,将头发当作一根圆柱,光线打到圆柱上时,一部分会正常发生镜面反射,另一部分会呈锥形散射出去,将这两种计算叠加起来就得到头发的渲染结果:
但是这样渲染出来的效果并不好,因为这和布林冯光照模型几乎一样,没有体现出头发的材质特性:
头发实际上是可以被光线穿过的,穿过头发的光线还会在头发内部发生反射再折射出去,因此人们把头发看作一个玻璃管:
射到头发表面的光线,一部分发生反射,即为 R,另一部分折射进头发内部再从另外一面折射出去,即为 TT,还有一部分在头发内部反射再从这边的表面折射出去,即为 TRT,这三部分的总和构成最终渲染结果。
同时我们把头发外表面称作 cuticle,头发内部称作 cortex,头发内部是有色素的,因此也决定了光线在内部传播的性质。这个方法称为Marschner model,效果非常不错:
但对于动物毛发,也是用这样的方法会得到不太好的结果:
这是由于动物毛发和人类毛发构造有些不同:
在头发中心还有一部分叫做髓质(Medulla),这部分非常复杂,光线进去之后会像在散射介质中一样发生复杂的散射,由于人类毛发髓质只占很小一部分,因此忽略掉也不会有太大影响,但是动物毛发中髓质占很大一部分,因此必须考虑光线在髓质中的散射。
可以看到髓质对渲染结果的影响非常大,因此使用双圆柱来描述头发的结构:
除了之前的 R 、T、TRT之外,双圆柱模型还考虑了光现在髓质中散射后的 TTs 和 TRTs:
这也是闫令琪老师的主要贡献之一,感兴趣可以找来论文细看。
4.3 颗粒材质
颗粒材质也非常复杂,可以定义在空间中,然后计算光线和每个小颗粒的作用。
4.4 半透明材质
半透明材质是因为光线打到物体表面后,在物体内部发生了多次散射,之后又从其表面的其他地方出去。光线在物体内部的散射称为次表面散射(Subsurface Scattering)。
按照这样的性质可以把 BRDF 稍作改进, BRDF 描述光线从一个方向入射会有多少从另一个方向射出,但是这两个方向都是从表面上同一个点出发的,次表面散射的 BRDF 称为 BSSRDF,描述的是光线从一个方向入射,会从表面的其他点沿着某个方向射出:
因此这回渲染方程的积分除了要对所有方向积分外,还要对整个表面进行积分。
后来人们发现半透明就好像物体内部有一个光源一样,所以可以按照这种思路在物体内部放一个光源来模拟半透明的效果,但是还要在外部有另一个虚拟光源才能达到正确的半透明效果。
次表面散射非常强大,因此应用非常广泛,比如人的皮肤,因为人的皮肤本身就是透光的,所以用 BSSRDF 会更加真实:
再比如玉质物体:
4.5 布料材质
布料是由一根根地线织成的,每根线又是由一股股纤维构成的,因此渲染布料可以像喧染头发一样对每根纤维进行渲染,但计算量自然非常庞大。
因此可以把布料当成一个表面,根据织物针织的方法,定义不同的 BRDF:
但对于天鹅绒这类布料,它的线是向外发散分布的,并不是按规律织起来的:
因此不适合当成一个表面去渲染,这时可以把它当成空间中的散射介质,像渲染云雾一样去渲染:
当然效果最好的还是一开始说的渲染每一根纤维,只是计算量太大:
4.6 细节材质
有时渲染的不真实不是因为渲染的不好,而是因为渲染出来的物体太过完美而显得不真实,比如:
而实际的车和鼠标的表面是这样的:
另外当光线在非常细小的地方传播的时候就不得不考虑光的波动性,而不能只考虑光的几何特性,比如渲染出金属表面的颗粒效果:
如何做出这些细节,这也是闫令琪老师的另一大贡献,更多可以看论文。
4.7 程序化生成材质
这个我们之前在纹理映射部分提到过,对于一些没有规律的花纹,比如花瓶以及它内部的纹路:
我们如果把这些空间中的每个点的材质都存下来是不现实的,因此会定义一个空间中的噪声函数去生成这样的噪声,这就是程序化生成材质,应用也非常广泛,除了上面的花瓶纹路,再比如木质品:
水面的波浪: