多图预警

高级光线传播方式

首先需要引入数理统计中关于有偏和无偏的概念

什么是无偏估计:https://www.zhihu.com/question/22983179

之前提到的蒙特卡洛方法是一种光线追踪中常用的估计方法,具体来说,是在求解渲染方程时,以特定的pdf分布对被积函数进行采样,再用采样到的样本来估计积分值的一种方法,但那时我们并没有提及什么样的pdf采样是最好的,这就涉及有偏和无偏的概念

如果样本得到的期望值与总体的期望值相等,那么这种估计就被称为无偏的,反之则有偏

除了无偏性,还有两种判断估计的准确性的评判标准——有效性和一致性(相合性)

暂且不提有效性,如果采样的样本数量趋近于无穷时,样本统计量的期望收敛于总体统计量的期望,则称这种估计是一致的

有了以上统计学概念,再继续分类来看现代图形学的几种高级光线传播方式

无偏光线传播方法

双向路径追踪(BDPT)

之前所说的路径追踪利用了光路可逆性,通过形成相机到光源的==单向路径==来计算光照结果

而双向路径追踪,顾名思义,就是从光源和相机分别打出一些半路径,最后连接两条半路径的端点,形成整条路径

BDPT原理

请注意,BDPT的原理看起来很简单,但实际实现起来非常困难(如果能实现,那么独立写渲染器也应该不在话下了)

这种方法适用于那些光线传播在光源一侧比较好计算的情况

BDPT效果

就如上图所示,整个场景的光源只有左上角的聚光灯和右侧打向左侧的聚光灯,其余部分都由环境光照照亮,这就意味着使用传统路径追踪打出的路径的第一个弹射点大概率是漫反射表面,反射路径弹向光源的概率小,没弹几次就被俄罗斯轮盘终止了,这就会很难计算到光源的信息,从而形成大量噪点。为了解决这个问题,从光源采样是一个优化方法,而BDPT则是另一个更高级的解决方案,从图中可以看出,双向路径追踪的效果是非常好的

Metropolis光线传播

Metropolis光线传播方法主要利用了马尔科夫链做蒙特卡洛估计(Markov Chain Monte Carlo,MCMC,马尔科夫链蒙特卡洛法),这种估计方法与之前介绍的蒙特卡洛方法的主要区别在于采样方式,之前在对像素多重采样的时候,我们所用的蒙特卡洛估计都是均匀采样,而马尔科夫链通俗来讲就是在已采样样本附近生成一个新样本继续做后续估计,每个样本之间不再独立,也就是说每次对当前像素的采样都基于上次对该像素的采样,这种采样方法得到的pdf可以与被积函数形状保持基本一致,采样的效果也就比均匀采样更好

MLT原理

上图所示原理,即在已有路径(蓝)基础上加以扰动,得到新光路(橙)

注意这里是对像素采样,而不是在解渲染方程

MLT效果

从图中也明显可以看出MLT的强大

这种方法尤其适用于复杂的光线传播情况,如半掩着门的房间,或者发生焦散的水体(SDS路径,specular→diffuse→specular)等,因为这些复杂的光线传播一旦找到一条路径,就可以不断在周围找到更多的路径,从而达到以更快速度获得更高质量渲染结果的目的

但是,这不代表这种方法没有它的局限

MLT缺点

用了这种算法之后,对于每个像素来说,其渲染时间是很难从理论上计算出来的,也就很难用来去渲染动画,并且,因为他所有的操作过程都是局部的,每个像素渲染时收敛所需的时间都不一样,这就导致图片看上去比较脏(图中砖缝尤为明显)

有偏光线传播方法

光子映射(Photon Mapping)

光源打出光线的过程可以被理解为不断打出光子的过程,光子映射(PM)就利用了这一想法

PM原理

整个过程分为两步

  • 先从光源出发打出光子,让其在空间内传播散射,直到打到漫反射表面为止
  • 然后再从摄像机打出路径,进行着色计算,着色点的亮度取决于光子的密度

具体做法是对每个着色点,取其附近的N个光子,做密度估计(树状结构实现算法),$\rho=\frac{N}{A}$

A可以由球形包围盒与表面求交得到(方法不唯一)

但这又有一个问题,我们直接来看效果

PM效果

很容易发现,在做密度估计的时候,N小了噪声会非常大,N大了图像又会变得模糊

这是因为光子映射本身就是一个有偏的方法,算密度应该用$\frac{N}{dA}$,而我们的密度估计时用的是$\triangle A$,$\frac{N}{dA}\neq\triangle A$,只有$\triangle A$足够小才能做到正确估计,否则多少会有点糊

为了让$dA$足够小,可以在一开始发射光子的时候就多发射点,提高采样数,那么同样多的N对应的$dA$就会相对小,也就是说,这种方法虽然有偏,但他是一致的

那么为什么不能取固定的$\triangle A$来数里面的N呢?因为这样一来$\triangle A$就锁死了,永远不会靠近$dA$,采样多,$\triangle A$里的N确实是会变多,但那也只是结果变亮而已,换句话说这样的结果是有偏且不一致的,因此我们通常采用前一种方法

顶点连接/合并(VCM)

VCM(Vertex connection and merging)就是把双向路径追踪和光子映射结合起来的一种方法

VCM

双向路径追踪会发生两条子路径端点非常接近的情况(在同一个局部面积内),这时候BDPT就认为这种路径无效,就是一种浪费

对于这种情况,VCM就认为其中一条路径打过来的不是光线而是光子,用光子映射的方法把两条路径的贡献结合起来,避免了这种浪费

现实在电影行业以及许多实践中,也确实使用了VCM这种方法

实时辐射度(Instant Radiosity)

有时候也被称为“很多光源的算法”(VPL / many light methods),核心思想是将每个被照亮的表面都作为虚拟的点光源来看待,再具体点,这种算法是把光源打出的光线所打到的地方作为二级光源,计算着色时遍历这些二级光源叠加计算

优点:速度快,在漫反射场景中效果很好

缺点:当虚拟光源离着色点特别近的时候,会出现反常亮点,类似漏光的现象,这和之前路径追踪对光源采样的距离平方项有关;另外,这种方法无法处理光泽材质

高级外观建模方法

非表面模型

散射介质

光线进入散射介质会发生两件事——被吸收或者散射

光线走多远被吸收,由介质的吸收能力决定;光线以何种方式散射,由介质的相位函数决定

相位函数

渲染方法:直线传播 -> 散射 -> 直线传播 -> 散射 -> 直线传播 -> … -> 吸收

对每个发生散射的着色点,与光源连接,计算路径的贡献

散射介质渲染

电影《超能陆战队》中旧京山(San Fransokyo,三藩京,虚构城市)场景的雾效就应用了散射介质

Big Hero

头发/毛发

先来看一个简单的模型

Kajiya Kay Kajiya Kay效果

首先,Kajiya-Kay模型将头发丝看做一个可弯曲的圆柱,这也是之后所有其他方法的基础

然后该模型认为,光线打到头发上会呈圆锥状散射(类似specular),同时又会被散射到四面八方(类似diffuse)

可以看到,这种diffuse+specular 的模拟效果并不尽如人意,但值得肯定的是,Kajiya-Kay模型为后续模型的提出奠定了基础

后来提出的Marschner模型,在Kajiya-Kay模型基础上,得到了广泛应用

Marschner Marschner效果

这个模型不再简单将头发丝视为圆柱,而是更进一步认为“圆柱”由“角质层”和“皮质层”组成

而光线的作用过程也更加复杂,总共分为三类:

  • T:直接反射
  • TT:穿进“皮质层”,再从“角质层”穿出
  • TRT:穿进“皮质层”,在内部反射,再从“角质层”穿出
T TT TRT
Marschner (2) Marschner (1) Marschner (3)

可以看到效果还是非常不错的

以上模型都是对人类头发来说的,那么更进一步,应用到动物毛发效果如何?

动物毛发

明显不一样,显然右图更接近真实我们想要的效果

下面从生物学角度深入探讨人类动物毛发的结构区别

动物毛发生物学结构1 动物毛发生物学结构2

除了角质和皮质,毛发还具有髓质结构,并且动物毛发的髓质明显比人类毛发的髓质粗不少

于是我们的闫令琪老师就提出了一种双层圆柱模型来模拟这种情况

double cylinder double cylinder效果

该模型在Marschner模型的T,TT,TRT基础上又加了两个计算项:TTs和TRTs

  • TTs:TT传进“皮质层”时打到髓质发生散射,再从“角质层”穿出
  • TRTs:TRT进入“皮质层”时发生发射,来回打到两次髓质,最后从“角质层”穿出

可以看到,髓质对毛发色彩表现的影响还是非常大的,相关理论已被应用到《狮子王》《猩球崛起》等影视作品中

颗粒材质

砂砾,谷物,粉末这些材质都属于颗粒材质,这些材质渲染的计算量非常大,但可以做一些简化,用百分比来表示单个渲染单元的组成成分,不过即使如此,颗粒材质至今仍然没有得到有效的优化

颗粒材质

表面模型

半透明材质

玉石这类材质是半透明材质(Translucent)的典型代表,注意translucent和semitransparent的区别,这里说的半透明是光线在材质内发生散射,最后从另一个点出来,对应到物理,这种现象被称为次表面散射

次表面散射

现实中可能用到次表面散射的情景有如渲染人耳,牛奶等材质,可以看到,光线通过人耳后并未被完全阻挡,而是表现为红光

BSSRDF

在图形学中,通常使用BSSRDF方程来描述次表面散射,它可以被认为是BSDF的拓展,BSDF计算贡献时只会计算当前着色点,而BSSRDF还需要考虑其他渲染单元射入的光线,因为这些光线在材质内发生散射后,同样有可能对当前着色点的能量造成影响

来看看BSSRDF的效果

BSSRDF效果1(1) BSSRDF效果1(2)
BSSRDF效果2 BSSRDF效果3

在应用时,我们也可以用Dipole方法做近似,即在表面上下各假设一个虚拟光源,来模拟次表面散射的光照效果

Dipole近似

布料模拟

我们先来看布料的微观组成:纤维 -> 纱线 -> 布料

布料组成

其中编制方法还分woven和knitted两种,不再细说

下面来看布料模拟中常用的几种方法,最简单粗暴的,直接根据不同布料给出BRDF,但这种方法无法渲染天鹅绒等材质

布料模拟2

因为天鹅绒本身就不能归为表面模型,所以接下去我们直接把布料看做是空间中的微小体积的集合,当做散射介质就像渲染云雾那样去渲染布料,这个计算量是肉眼可见的大

布料模拟3

当这些体积被细分到纤维级别时,计算量是难以想象的,但效果也无限接近真实

布料模拟4

细节模型

至今为止讲的所有真实感渲染都忽略了一件事,那就是现实世界中的物体大多数都是不完美的,多多少少都会带点瑕疵,比如风雨灰尘在车漆上留下的细微划痕,或物件老化磨损,等等等等,现实世界的情况往往比理论更加复杂

想要在渲染时考虑这些微小的因素,我们在之前提到微表面模型的时候有强调过使用法线分布来描述微观表面的起伏,但那时候说的法线分布,大部分是正态分布之类的简单分布,这并不是我们真正想要的

微表面回顾 微表面回顾2

我们当然可以人为的往这些分布上加一些细节扰动,但想真正把它渲染出来是非常困难的

细节模型

闫神:《关于自己的头像是自己渲染了一个月的研究结果这档事》

除此之外,细节模型还存在一个问题,就是在计算镜面反射时,如果法线分布比较复杂,就很难建立有效的,从光源到微表面再到摄像机的光线通路,为了解决这个问题,我们让每个像素打出路径时都对应一个范围,如图,把整块范围内的法线分布整合起来得到P-NDF,从而简化计算

P NDF1 P NDF2

单独看这些P-NDF,单个像素覆盖的微表面范围大小不同,P-NDF所呈现出来的特点也各不相同

当范围选取的大,P-NDF会趋于符合一些统计学规律,而当范围选取的小,这些P-NDF则会展现出一些很奇妙的形态

并且,不同类型的法线分布也会得到不同的P-NDF图像,各向同性的P-NDF与各向异性材质完全不同

P NDF3 P NDF4

再深入,就要考虑到微表面上光的波粒二象性了,比如干涉衍射,这些太复杂,并且只有在很小的尺度下,波动性才会起作用,在这里就不细说了,但可以看看考虑了波动光学的BRDF和几何光学BRDF的区别:

微表面的波动性 考虑微表面的波动性的BRDF

结果和几何光学极为相近,但它的图像是不连续的

程序化生成材质

之前再说纹理的时候就有简单提到过程序纹理,对应到材质这块,这个过程就是通过程序来指导材质的生成

这里的程序化生成并没有真正的生成材质,而是将这个材质信息定义为空间中的一些噪声函数,在后续生成时动态的查询它

(存储三维的纹理会耗费很多内存)

噪声函数的应用非常广泛,比如可以二值化定义车锈

程序化生成车锈

现在应用最广泛的噪声函数是柏林噪声(Perlin Noise),有了这些噪声函数,我们不仅可以程序化生成材质,还可以程序化生成地形,程序化生成水面等,另外,由于这个噪声函数是定义在空间中的,所以如果我们在空间里切割一块木头(或其他材质),是能看到里面的纹理的,这是二维材质做不到的

Substance Designer是目前工业上用来程序化生成材质的工具之一,它并非如上所述定义了函数供后续查询,而是直接生成了材质拿去用…

这个工具也渐渐的成为了目前游戏TA必备的工具技能之一