本文继续对《UnityShader入门精要》——冯乐乐 第十八章 基于物理的渲染 进行学习
在https://github.com/candycat1992/Unity_Shaders_Book中,冯乐乐给出了2019年改版后的第18章,本文基于此版本进行学习。
一、引述
长期以来,图形学一直信奉着“如果这看起来是对的,那么这就是对的”的信条,这其中一方面的原因是由于当时计算机的计算能力较低,且硬件价格昂贵。随着计算机的处理能力越来越强,人们开始考虑使用更加复杂的算法来渲染更加真实的画面。
在二十世纪八十年代左右,基于物理的渲染技术(Physically Based Shading, PBS)首次被引入图形学的正统研究中,学者们提出了使用光线追踪的方法来渲染全局光照,由此打开了精确渲染光线传播的大门。然而,当时的工业界更加依赖于使用各种 tricks 来得到希望的艺术风格,而并不需要非常精确的物理模拟。因此,这种基于物理的渲染方法实际上是在二十世纪九十年代末才开始逐渐为工业界所接受。之后,随着 Mental Ray、Arnold、RenderMan 等渲染器的出世,基于物理的蒙特卡洛渲染方法在(离线渲染)工业界取得了巨大成功。
而在实时渲染领域,人们也发现了这种基于物理的光照模型的巨大优势。在这之前,Lambert光照模型、Phong 光照模型和 Blinn-Phong 光照模型等经验模型占据了主流。然而,这种不满足能量守恒的光照模型使得美术人员需要花费大量的时间在参数调节上。尤其是,美术人员往往好不容易为一个物体调节好了所有参数,使得它在当前的光照条件下看起来是满意的。然而,一旦光照环境发生了变化,这一切都得从头再来。因此,近年来游戏从业者开始着手把基于物理的光照模型应用于实时渲染中。
Unity 最早在 2012 年的《蝴蝶效应》( 英文名:Butterfly Effect)的 demo 中大量使用了 PBS,并在 Unity 5 中正式将 PBS 引入到引擎渲染中。Unity 5 引入了一个名为 Standard Shader 的可在不同材质之间通用的着色器,而该着色器就是使用了基于物理的光照模型。需要注意的是,PBS 并不意味着渲染出来的画面一定是像照片一样真实的,例如,Pixar 和 Disney 尽管长期使用 PBS 渲染电影画面,但它们得到的风格是非常有特色的艺术风格。相信很多读者或多或少看到过使用 PBS渲染出来的画面是多么的酷炫,并很想了解这背后的技术原理。如果你是一个程序员,可能有很大的冲动想要自己实现一个 PBS 渲染框架,但往往走到后面会发现有很多看不懂的名词以及一大堆与之相关的论文;如果你是一个美工人员,你可能会找到很多关于如何制作 PBS 中使用的纹理教程,但你大概也了解,想要使用 PBS 实现出色的渲染效果,并不是纹理+一个 Shader 这么简单的问题。
现在,我们有一个好消息和一个坏消息要告诉大家。先说好消息,Unity 5 引入的基于物理的渲染不需要我们过多地了解 PBS 是如何实现的,就能利用各种内置工具来实现一个不错的渲染效果。然而坏消息是,我们很难通过短短几万文字来非常详细地告诉读者这些渲染到底是如何实现的,因为这其中需要牵扯许多复杂的光照模型,如果要完全理解每一种模型的话,大概还要讲很多论文和其他参考文献。不过还有一个好消息是,我们相信读者在学完本章后可以了解 PBS 的基 本原理,并可以实现一个包含了简单的基于物理的光照模型的 Shader。如果你对 PBS 有着浓厚的兴趣,想要尝试自己构建一个更加复杂的 PBS 渲染框架,可以在本章的扩展阅读部分找到许多非常有价值的参考资料。
在本章中,我们首先会讲解 PBS 的基本原理,让读者了解它们与我们之前所学的渲染方式到底有哪些不同。接着,我们会按照 PBS的相关公式来实现一个非常简单的基于物理渲染的 Shader。尽管本书的定位并不是“教你如何使用 Unity”,但我们决定花一点时间来告诉读者 Unity 5 引入的 Standard Shader 是如何工作的,以及如何在 Unity 5 中使用它和其他工具来渲染一个场景,我们希望通过这些内容来让读者明白 PBS 中的一些关键因素。从本书第一版出版到现在,我们已经看到了越来越多的手机游戏也开始使用 PBS 进行渲染,我们相信这是未来的发展趋势,希望本章可以为读者打开 PBS 的大门。
在学习如何实现 PBS 之前,我们非常有必要来了解基于物理的渲染所基于的理论和数学基础。我们不会过多地牵扯一些论文资料,但如果在阅读过程中读者发现无法理解一些光照模型的实现原理,这可能意味着你需要阅读更多的参考文献。本节主要参考了 Naty Hoffman 在SIGGRAPH 2013 上做的名为 Background: Physics and Math of Shading 的演讲[1]以及 Brent Burley等人在 SIGGRAPH 2012 上做的名为 Physically-Based Shading at Disney 的演讲[2]。
在 Disney 的演讲中,作者介绍了 Disney 是如何把各种现有的基于物理的光照模型与自身需求结合起来,得到满足 Disney 渲染需求的 BRDF 光照模型,并成功应用在电影《无敌破坏王》(英文名:Wreck-It Ralph)的材质渲染中。自此之后,这个 Disney BRDF 模型被广泛应用于实时渲染领域,各大游戏引擎在此基础上实现了各自的 PBS 光照模型,大大提升了游戏画面渲染质量。那么,到底什么叫基于物理的渲染?什么又是 BRDF 呢?这就是我们现在要来学习的内容。既然要得到基于物理的光照模型,我们首先必须了解在真实的物理世界中光是什么以及它是如何与各种材质发生交互的。
一、光是什么
尽管我们之前一直讲光照模型,但要问读者,光到底是什么,可能没有多少人可以解释清楚。在物理学中,光是一种电磁波。首先,光由太阳或其他光源中被发射出来,然后与场景中的对象相交,一些光线被吸收(absorption),而另一些则被散射(scattering),最后光线被一个感应器(例如我们的眼睛)吸收成像。
通过上面的过程,我们知道材质和光线相交会发生两种物理现象:散射和吸收(其实还有自发光现象)。光线会被吸收是由于光被转化成了其他能量,但吸收并不会改变光的传播方向。相反的,散射则不会改变光的能量,但会改变它的传播方向。在光的传播过程中,影响光的一个重要的特性是材质的折射率(refractive index)。我们知道,在均匀的介质中,光是沿直线传播的。但如果光在传播时介质的折射率发生了变化,光的传播方向就会发生变化。特别是,如果折射率是突变的,就会发生光的散射现象。
实际上,在现实生活中,光和物体之间的交互过程是非常复杂的,大多数情况下并不存在一种可分析的解决方法。但为了在渲染中对光照进行建模,我们往往只考虑一种特殊情况,即只考虑两个介质的边界是无限大并且是光学平滑(optically flat)的。尽管真实物体的表面并不是无限延伸的,也不是绝对光滑的,但和光的波长相比,它们的大小可以被近似认为是无限大以及光学平滑的。在这样的前提下,光在不同介质的边界会被分割成两个方向:反射方向和折射方向。而有多少百分比的光会被反射(另一部分就是被折射了)则是由菲涅耳等式(Fresnel equations)来描述的,如图 18.1 所示。
图18.1 在理想的边界处,折射率的突变会把光线分成两个方向
但是,这些与光线的交界处真的是像镜子一样平坦吗?尽管在上面我们已经说过,相对于光的波长来说,它们的确可以被认为是光学平坦的。但是,如果想象我们有一个高倍放大镜,去放大这些被照亮的物体表面,就会发现有很多之前肉眼不可见的凹凸不平的平面。在这种情况下,物体的表面和光照发生的各种行为,更像是一系列微小的光学平滑平面和光交互的结果,其中每个小平面会把光分割成不同的方向。
这种建立在微表面的模型更容易解释为什么有些物体看起来粗糙,而有些看起来就平滑,如图 18.2 所示。
图18.2 左图:光滑表面的微平面的法线变化较小,反射光线的方向变化也更小。右图:粗糙表面的微平面的法线变化较大,反射光线的方向变化也更大
想象我们用一个放大镜去观察一个光滑物体的表面,尽管它的表面仍然由许多凹凸不平的微表面构成,但这些微表面的法线方向变化角度小,因此,由这些表面反射的光线方向变化也比较小,如图 18.2 左图所示,这使得物体的高光反射更加清晰。而图 18.2 右图所示的粗糙表面则相反,由此得到的高光反射效果更模糊。
在上面的内容中,我们并没有讨论那些被微表面折射的光。这些光被折射到物体的内部,一部分被介质吸收,一部分又被散射到外部。金属材质具有很高的吸收系数,因此,所有被折射的光往往会被立刻吸收,被金属内部的自由电子转化成其他形式的能量。而非金属材质则会同时表现出吸收和散射两种现象,这些被散射出去的光又被称为次表面散射光(subsurface-scattered light)。在图18.3 中,我们给出了一条由微表面折射的光的传播路径(如图 18.3 所示的蓝线,读者可参考随书资源中的彩图)。
图18.3 微表面对光的折射。这些被折射的光中一部分被吸收,一部分又被散射到外部
现在,我们把放大镜从物体表面拿开,继续从渲染的层级大小上考虑光与表面一点的交互行为。那么,由
微表面反射的光可以被认为是该点上一些方向变化不大的反射光,如图 18.4 中的黄线所示(可参考随书资源中的彩图)。
图18.4 次表面散射。左图:次表面散射的光线会从不同于入射点的位置射出。如果这些距离值小于需要被着色的像素大小,那么渲染就可以完全在局部完成(右图)。否则,就需要使用次表面散射渲染技术
而折射光线(蓝线)则需要更多的考虑。那些次表面散射光会从不同于入射点的位置从物体内部再次射出,如图 18.4 左图所示。而这些离入射点的距离值和像素大小之间的关系会产生两种建模结果。如果像素要大于这些散射距离的话,意味着这些次表面散射产生的距离可以被忽略,那我们的渲染就可以在局部进行,如图 18.4 右图所示。如果像素要小于这些散射距离,我们就不可以选择忽略它们了,要实现更真实的次表面散射效果,我们需要使用特殊的渲染模型,也就是所谓的次表面散射渲染技术。
我们下面的内容均建立在不考虑次表面散射的距离,而完全使用局部着色渲染的前提下。
二、渲染方程
在了解了上面的理论基础后,我们现在来学习如何用数学表达式来表示上面的光照模型。这意味着,我们要对光这个看似抽象的概念进行量化。我们可以用辐射率(radiance)来量化光。辐射率是单位面积、单位方向上光源的辐射通量,通常用 L 来表示,被认为是对单一光线的亮度和颜色评估。在渲染中,我们通常会使用入射光线的入射辐射率 Li来计算出射辐射率 Lo,这个过程也往往被称为是着色(shading)过程。
James Kajiya 在他 1986 年那篇著名的 The Rendering Equation 论文中给出了渲染方程的表述形式,由此在理论上完美地给出了基于物理渲染的方向。这个公式第一次从数学建模的角度描述了渲染到底是在解决什么问题,可以说自此之前人们都是在靠各种各样的 hacks 来尝试进行各种渲染,当渲染方程横空出世后,人们终于不用再盲人摸象,人们有了统一的目标,那就是如何更快更好地去求解渲染方程。
这个在图形学中大名鼎鼎的渲染方程公式如下:
image.png
尽管上面的式子看起来有些复杂,但很好理解,即给定观察视角 v,该方向上的出射辐射率Lo(v)等于该点向观察方向发出的自发光辐射率 Le(v)加上所有有效的入射光 Li(ωi)到达观察点的辐射率积分和。图 18.5 给出了渲染等式中各个部分的通俗解释。
图18.5 渲染方程参数的通俗解释
渲染方程是计算机图形学的核心公式,当去掉其中的自发光项 Le(v)后,剩余的部分就是著名的反射等式(Reflectance Equation)。我们可以这样理解反射等式:想象我们现在要计算表面上某点的出射辐射率,我们已知到该点的观察方向,该点的出射辐射率是由从许多不同方向的入射辐射率叠加后的结果。其中,f (ωi, v)表示了不同方向的入射光在该观察方向上的权重分布。我们把这些不同方向的光辐射率(Li(ωi)部分)乘以观察方向上所占的权重(f (ωi, v)部分),再乘以它们在该表面的投影结果((n·ωi)部分),最后再把这些值加起来(即做积分)就是最后的出射辐射率。
在实时渲染中,自发光项通常就是直接加上某个自发光值。除此之外,积分累加部分在实时渲染中也基本无法实现,因此积分部分通常会被若干精确光源的叠加所代替,而不需要计算所有入射光线在半球面上的积分。
三、精确光源
在真实的物理世界中,所有的光源都是有面积概念的,即所谓的面光源。由于面光源的光照计算通常要耗费大量的时间,因此在实时渲染中,我们通常会使用精确光源(punctual light sources)来近似模拟这些面光源。图形学中常见的精确光源类型有点光源、平行光和聚光灯等,这些精确光源被认为是大小为无限小且方向确定的,尽管这并不符合真实的物理定义,但它们在大多数情况下都能得到令人满意的渲染效果。
我们使用 lc来表示它的方向,使用 clight表示它的颜色。使用精确光源的最大的好处在于,我们可以大大简化上面的反射等式。我们在这里省略推导过程(有兴趣的读者可以阅读参考文献[1]),直接给出结论,即对于一个精确光源,我们可以使用下面的等式来计算它在某个观察方向 v 上的出射辐射率:
image.png
和之前使用积分形式的原始公式相比,上面的式子使用一个特定的方向的 f (lc, v)值来代替积分操作,这大大简化了计算。如果场景中包含了多个精确光源,我们可以把它们分别代入上面的式子进行计算,然后把它们的结果相加即可。也就是说,反射等式可以简化成下面的形式:
image.png
那么,现在剩下的问题就是,f (lc, v)项怎么算呢?f (lc, v)实际上述了当前点是如何与入射光线进行交互的:当给定某个入射方向的入射光后,有多少百分比的光照被反射到了观察方向上。
在图形学中,这一项有一个专门的名字,那就是双向反射分布函数,即 BRDF。
四、双向反射分布函数(BRDF)
BRDF(Bidirectional Reflectance Distribution Function,中文名称为双向反射分布函数)定量描述了物体表面一点是如何和光进行交互的。大多数情况下,BRDF 可以用 f (l, v)来表示,其中 l 为入射方向和 v 为观察方向(双向的含义)。这种情况下,绕着表面法线旋转入射方向或观察方向并不会影响 BRDF 的结果,这种 BRDF 被称为是各项同性(isotropic)的 BRDF。与之对应的则是各向异性(anisotropic)的 BRDF。
那么,BRDF 到底表示的含义是什么呢?BRDF 有两种理解方式—第一种理解是,当给定入射角度后,BRDF 可以给出所有出射方向上的反射和散射光线的相对分布情况;第二种理解是,当给定观察方向(即出射方向)后,BRDF 可以给出从所有入射方向到该出射方向的光线分布。一个更直观的理解是,当一束光线沿着入射方向 l 到达表面某点时,f (l, v)表示了有多少部分的能量被反射到了观察方向 v 上。
下面,我们来看一下反射等式中的重要组成部分—BRDF 是如何计算的。可以看出,BRDF决定了着色过程是否是基于物理的。这可以由 BRDF 是否满足两个特性来判断:它是否满足交换律(reciprocity)和能量守恒(energy conservation)。
交换律要求当交换 l 和 v 的值后,BRDF 的值不变,即
image.png
而能量守恒则要求表面反射的能量不能超过入射的光能,即对(任意)
image.png
,要求
image.png
基于这些理论,BRDF 可以用于描述两种不同的物理现象:表面反射和次表面散射。针对每种现象,BRDF
通常会包含一个单独的部分来描述它们—用于描述表面反射的部分被称为高光反射项(specular term),以及用于描述次表面散射的漫反射项(diffuse term),如图 18.6所示。
那么,我们如何得到不同材质的 BRDF 呢?一种完全真实的方法是使用精确的光学仪器在真实的物理世界中对这些材质进行测量,通过不断改变光照入射方向和观察方向并对当前材质的反射光照进行采样,我们就可以得到它的 BRDF 图像切片。一些机构和组织向公众公开了他们测量出来的 BRDF 数据库,以便供研究人员进行分析和研究,例 如 MERL BRDF 数据库( http://www.merl.com/brdf/ )以及 MIT CSAIL 数据库(http://people.csail.mit.edu/addy/research/brdf/),这些真实材质的 BRDF 数据反映了它们在不同光
照和观察角度下的反射情况。
在学术界,学者们也基于复杂的物理和光学理论分析归纳出了一些通用的 BRDF 数学模型,来对 BRDF 分析模型中的高光反射项和漫反射项进行数学建模。这些由研究人员得到的 BRDF 模型也可以被称为是分析型 BRDF 模型,这些 BRDF 模型通常包含了大量的物理和光学参数。通过对真实材质的 BRDF 图像和现有的分析型 BRDF 模型进行对比,研究人 员发现,其实很多材质是无法被现有的任何一种分析型 BRDF 模型所良好的描述出来。因此,许多最新的研究都选择使用基于数据驱动的方法,来开发出一些新的分析型 BRDF 模型,从而使其可以和真实材质的 BRDF 图像尽可能地接近。
但遗憾的是,由于真实世界的光照和材质都非常复杂,因此很难有一种可以满足所有真实材质特性的 BRDF 模型。Disney 向公众开源了一个名为BRDF Explorer(http://github.com/wdas/brdf)的软件,来让用户可以直观地对比各种分析型 BRDF模型与真实测量得到的 BRDF 值之间的差异。
可以认为,这些测量得到的真实 BRDF 数据库是研究人员在开发新的基于物理的 BRDF 光照模型的重要依据,除了满足交换律和能量守恒两个条件外,一个分析型 BRDF 模型应当与测量得到的 BRDF 数据在尽可能多得材质范围内(或这些特定的材质)、具有尽可能得相似的表现才可能被广泛应用。Disney 通过对大量现有的分析型 BRDF 模型进行对比,并结合对真实材质的 BRDF数据的观察,开发出了适用于 Disney 动画渲染流程的 BRDF 模型,也被称为 Disney BRDF。在下面的内容中,我们会介绍漫反射项和高光反射项的一些常见的 BRDF 数学模型,同时给出 Disney BRDF 模型中的相应表示。
五、漫反射项
我们之前所学习的 Lambert 模型就是最简单、也是应用最广泛的漫反射 BRDF。准确的Lambertian BRDF 的表示为:
<div class="image-view" data-width="189" data-height="45">
image.png
其中,cdiff表示漫反射光线所占的比例,它也通常被称为是漫反射颜色(diffuse color)。与我们之前讲过的 Lambert 光照模型不太一样的是,上面的式子实际上是一个定值,我们常见到的余弦因子部分(即(n·l))实际是反射等式的一部分,而不是 BRDF 的部分。上面的式子之所以要除以π,是因为我们假设漫反射在所有方向上的强度都是相同的,而 BRDF 要求在半球内的积分值为 1。因此,给定入射方向 l 的光源在表面某点的出射漫反射辐射率为:
image.png
可以看出,最右项和我们之前一直使用的漫反射项基本一样。尽管 Lambert 模型简单且易于实现,但真实世界中很少有材质符合上述 Lambert 的数学描述,即具有完美均匀的散射。不过,一些游戏引擎和实时渲染器出于性能的考虑会使用 Lambert 模型作为它们 PBS 模型中的漫反射项,例如虚幻引擎 4(Unreal Engine 4)[11]。
通过对真实材质的 BRDF 数据进行分析,研究人员发现许多材质在掠射角度表现出了明显的高光反射峰值,而且还与表面的粗糙度有着强烈的联系。粗糙表面在掠射角容易形成一条亮边,而相反地光滑表面则容易在掠射角形成一条阴影边。这些都是 Lambert 模型所无法描述的。图 18.7显示了这样的例子,注意图中在掠射角的光照效果。
图 18.7 从左到右:粗糙材质和光滑材质的真实漫反射结果,以及 Lambert 漫反射结果
因此,许多基于物理的渲染选择使用更加复杂的漫反射项来模拟更加真实次表面散射的结果。例如,在 Disney BRDF[2]中,它的漫反射项为:
image.png
其中,baseColor 是表面颜色,通常由纹理采样得到,roughness 是表面的粗糙度。上面的漫反射项既考虑了在掠射角漫反射项的能量变化,还考虑了表面的粗糙度对漫反射的影响。Disney使用了 Schlick 菲涅耳近似等式[7]来模拟在掠射角的反射变化,同时使用表面粗糙度来进一步修改它,这使得光滑材质可以在掠射角具有更为明显的阴影边,而又使得粗糙材质在掠射角具有亮边。而上面的式子也正是 Unity 5 内部使用的漫反射项。六、高光反射项
在现实生活中,几乎所有的物体都或多或少有高光反射现象。John Hable 在他的文章中就强调了 Everything is Shiny。但在许多传统的 Shader 中,很多材质只考虑了漫反射效果,而并没有添加高光反射,这使得渲染出来的画面并不那么真实可信。
在基于物理的渲染中,BDRF 中的高光反射项大多数都是建立在微面元理论(microfacet theory)的假设上的。微面元理论认为,物体表面实际是由许多人眼看不到的微面元组成的,虽然物体表面并不是光学平滑的,但这些微面元可以被认为是光学平滑的,也就是说它们具有完美的高光反射。当光线和物体表面一点相交时,实际上是和一系列微面元交互的结果。正如我们在 18.1.1 节中看到的,当光和这些微面元相交时,光线会被分割成两个方向—反射方向和折射方向。这里我们只需要考虑被反射的光线,而折射
光线已经在之前的漫反射项中考虑过了。当然,微面元理论也仅仅是真实世界的散射的一种近似
理论,它也有自身的缺陷,仍然有一些材质是无法使用微面元理论来描述的。
假设表面法线为 n,这些微面元的法线 m 并不都等于 n,因此,不同的微面元会把同一入射方向的光线反射到不同的方向上。而当我们计算 BRDF 时,入射方向 l 和观察方向 v 都会被给定,这意味着只有一部分微面元反射的光线才会进入到我们的眼睛中,这部分微面元会恰好把光线反射到方向 v 上,即它们的法线 m 等于 l 和 v 的一半,也就是我们一直看到的半角度矢量 h(half angle vector,也被称为 half vector),如图 18.6(a)所示。
然而,这些 m = h 的微面元反射也并不会全部添加到 BRDF 的计算中。这是因为,它们其中一部分会在入射方向 l 上被其他微面元挡住(shadowing),如图 18.6(b)所示,或是在它们的反射方向 v 上被其他微面元挡住了(masking),如图 18.6(c)所示。微面元理论认为,所有这些被遮挡住的微面元不会添加到高光反射项的计算中(实际上它们中的一些由于多次反射仍然会被我们看到,但这不在微面元理论的考虑范围内)。
基于微面元理论的这些假设,BRDF 的高光反射项可以用下面的通用形式来表示:
image.png
图18.6 (a)那些m=h的微面元会恰好把入射光从I反射到v上,只有这部分微面元才可以添加到BRDF的计算中。(b)一部分满足(a)的微面元会在I方向上被其他微面元遮挡住,它们不会接受到光照,因此会形成阴影。(c)还有一部分满足(a)的微面元会在反射方向v上被其他微面元挡住,因此,这部分反射光也不会被看到
这就是著名的 Torrance-Sparrow 微面元模型[5](Torrance 和 Sparrow 来源于两个作者的姓名)。上面的式子看起来难以理解,实际上其中的各个项对应了我们之前讲到的不同现象。D(h)是微面元的法线分布函数(normal distribution function,NDF),它用于计算有多少比例的微面元的法线满足 m=h,只有这部分微面元才会把光线从 l 方向反射到 v 上。G(l, v, h)是阴影—遮掩函数(shadowing-masking function),它用于计算那些满足 m=h 的微面元中有多少会由于遮挡而不会被人眼看到,因此它给出了活跃的微面元(active microfacets)所占的浓度,只有活跃的微面元才会成功地把光线反射到观察方向上。F(l, h)则是这些活跃微面元的菲涅尔反射(Fresnel reflectance)函数,它可以告诉我们每个活跃的微面元会把多少入射光线反射到观察方向上,即表示了反射光线占入射光线的比率。事实上,现实生活中几乎所有的物体都会表现出菲涅耳现象。最后,分母4(n l)(n v)是用于校正从微面元的局部空间到整体宏观表面数量差异的校正因子。
这些不同的部分又可以衍生出很多不同的 BRDF 模型。首先是菲涅耳反射函数部分 F(l, h)。
七、菲涅耳反射函数
菲涅耳反射函数计算了光学表面反射光线所占的部分,它表明了当光照方向和观察方向夹角逐渐增大时高光反射强度增大的现象。完整的菲涅耳等式非常复杂,包含了诸如复杂的折射率等与材质相关的参数。为了给美术人员提供更加直观且方便调节的参数,大多数 PBS 实现选择使用Schlick 菲涅耳近似等式[7]来得到近似的菲涅尔反射效果:
image.png
其中,cspec 是材质的高光反射颜色。通过对真实世界材质的观察,人们发现金属材质的高光反射颜色值往往比较大,而非金属材质的反射颜色值则往往较小。
八、法线分布函数
法线分布函数 D(h表示了对于当前表面来说有多少比例的微面元的法线满足 m=h,这意味着只有这些微面元才会把光线从 l 方向反射到 v 上。对于大多数表面来说,微面元的法线朝向并不是均匀分布的,更多的微面元会具有和表面法线 n 相同的面法线。法线分布函数的值必须是非负的标量值,它决定了高光区域的大小、亮度和形状,因此是高光反射项中非常重要的一项。一个直观的感受是,当表面的粗糙度下降时,应该有更多的微面元的面法线满足 m=n。因此法线分布函数应该考虑到表面粗糙度的影响。
我们之前学习的 Blinn-Phong 模型[7]就是一种非常简单的模型。Blinn 在他的论文中改进了Phong 模型并提出了 Blinn-Phong 模型,使它更贴合微面元 BRDF 模型的理论。Blinn-Phong 模型使用的法线分布函数 D(h)为:
image.png
其中,gloss 是与表面粗糙度相关的参数,它的值可以是任意非负数。上面的式子和我们之前所见的 Blinn-Phong 模型有所不同,这是因为我们在里面加入了归一化因子,这是因为法线分布函数必须满足一个条件,即所有微面元的投影面积必须等于该区域宏观表面的投影面积。因此,上述公式也被称为是归一化的 Phong 法线分布函数。
但实际上,Blinn-Phong 模型并不能真实地反映很多真实世界中物体的微面元法线方向分布,它其实完全是一种经验型模型,因此,很多更加复杂的分布函数被提了出来,例如 GGX[3]、Beckmann[4]等。
Beckmann 分布来源于高斯粗糙分布的一种假设,而且在表现上和 Phong 分布非常类似,但它的计算却要复杂很多。 GGX 分布(也被称为 Trowbridge-Reitz 法线分布函数)是一种更新的法线分布函数,它的公式如下:
image.png
其中,参数 α 是与表面粗糙度相关的参数。与 Blinn-Phong 的法线分布相比,GGX 分布具有更明亮、更狭窄且拖尾更长的高光区域,它的结果更接近于一些测量得到的真实材质的 BRDF 分布。在 Disney BRDF 中,Disney 认为对于很多材质来说,GGX 表现出来的高光拖尾仍然不够长。他们选择使用一种更加广义的法线分布模型,即 Generalized-Trowbridge-Reitz(GTR)分布。GTR分布于 GGX 分布很类似,但它的分母部分的指数不是 2,而是一个可调参数。
Disney 使用两个不同指数的 GTR 分布作为两个高光反射片,其中第一个反射片用于表示基本材质层,第二个反射片用于表示基本材质表面的清漆层。除此之外,他们还发现令 α = roughness2可以在材质粗糙度上得 到更加线性的变化。否则,直接使用 roughness 作为参数的话会导致在光滑材质和粗糙材质之间插值出来的材质总是偏粗糙的。
九、阴影-遮挡函数
阴影-遮挡函数 G(l, v, h)也被称为几何函数(geometry function),它表明了具有给定面法线 m的微面元在沿着入射方向 l 和观察方向 v 上不会被其他微面元挡住的概率。在微面元理论的 BRDF中,m 可以使用半向量 h 来代替,因为只有这部分微面元才会把光线从 l 方向反射到 v 上。
由于G(l, v, h)表示的是一个概率值,因此它的值是一个范围在 0 到 1 之间的标量。学术界发表了许多对于 G(l, v, h)的分析模型,这些公式大多建立在一些简化的表面模型基础下。许多已发表的微面元 BRDF 模型习惯把 G(l, v, h)和高光反射项的分母(n l)(n v)部分结合起来,即把 G(l, v, h)除以(n l)(n v)的部分合在一起讨论,这是因为这两个部分都和微面元的可见性有关,因此 Naty Hoffman在他的演讲[1]中称这个合项为可见性项(visibility term)。
一些 BRDF 模型选择完全省略可见性项,即把该项的值设为 1。这意味着,这些 BRDF 中的G(l, v, h)表达式等同于:
image.png
上述的 Gimplicit 实现不需要任何计算量(因为可以直接和高光反射项的分母进行抵消),并且在一些程度上可以反映正确的变化趋势。例如,当从掠射角进行观察或光线从掠射角射入时,该项会趋近于 0,这是符合我们的认知的,因为在掠射角时微面元被其他微面元遮挡的概率会非常大。然而,这种 Gimplicit的实现忽略了材质粗糙度的影响,缺乏一定的物理真实性,因为我们希望粗糙的表面具有更高阴影和遮挡概率。
通常,阴影-遮挡函数 G(l, v, h)依赖于法线分布函数 D(h),因为它需要结合 D(h)来保持 BRDF能量守恒的规定。最早的阴影-遮挡函数之一是 Cook-Torrance 阴影遮挡函数[9](Cook 和 Torrance来源于两个作者的姓名):
image.png
Cook-Torrance 阴影遮挡函数在电影行业被应用了很长时间,但它实际上是基于一个非真实的微几何模型,而且同样不受材质粗糙度的影响。后来,Kelemen 等人[10]提出了一个对于 Cook-Torrance 阴影遮挡函数非常快速且有效的近似实现:
image.png
目前在图形学中广受推崇的是 Smith 阴影-遮掩函数[6]。Smith 函数比 Cook-Torrance 函数更加精确,而且考虑进了表面粗糙度和法线分布的影响。原始的 Smith 函数是为 Beckmann 法线分布函数所涉及的,而 Walter 等人[3]随后将其通用化,使其可以匹配任何法线分布函数,并给出了针对 Beckmann 和 GGX 法线分布函数的更加高效的近似 Smith 模型。在 Disney 的 BRDF 模型[2]中,它的阴影-遮掩函数 G(l, v, h)就使用了 Walter 等人[3]提出的为 GGX 设计的 Smith 模型:
image.png
上述公式中的 θv表示观察方向 v 和表面法线 n 之间的夹角。根据艺术家的反馈以及对测量得到的 BRDF 图像的观察,Disney 在上述式子中重新映射了 αg和 roughness 之间的关系,由此得到了一个在视觉上让艺术家更加满意的效果。这种 Smith 阴影-遮掩函数被广泛应用在电影行业中,但可以看出,相比于 Kelemen 改进后的 Cook-Torrance 阴影遮挡函数,Smith 函数的计算量要明显高很多。
<hr>
至此,我们已经介绍完了基于物理的 BRDF 模型的基础理论,并给出了一些常见的 BRDF 模型,例如 Phong、Beckmann、GGX 模型以及 Disney BRDF 模型的实现等。尽管存在很多基于物理的 BRDF 模型,但在真实的电影或游戏制作中,我们希望在直观性和物理可信度之间找到一个平衡点,使得实现的 BRDF 既可以让美术人员直观地调节各个参数,而又有一定的物理可信度。
当然,有时候为了满足直观性我们不得不牺牲一定的物理特性,得到的 BRDF 可能不是严格基于物理原理的。Disney 的 BRDF 模型就是一个很好的例子,它使用尽可能少的若干直观参数来代替那些晦涩难懂的物理变量,而且这些参数的范围被精妙地设计为 0 到 1,为此 Disney 会在必要时重新映射 BRDF 中的变量范围,例如在阴影-遮掩函数中他们重新映射了粗糙度变量的范围。
十、PBS 中的光照
尽管基于物理渲染的理论比较复杂,但在实际应用中绝大部分情况下我们其实只需要按照上面提到的各种公式来实现相应的 BRDF 模型即可。然而,要想得到画面出色的渲染效果,仅仅应用这些公式是远远不够的,我们还需要为这些 PBS 材质搭配以出色的光照。
在上面的内容中我们已经介绍了精确光源。随着新的技术不断被提出,实时面光源也不再是一个奢侈的梦想。在 SIGGRAPH 2016 上,Eric Heitz 和 Stephen Hill 在他们名为 Real-Time Area Lighting: a Journey from Research to Production 的演讲中就分享了如何实现实时面光源的渲染,这也是 Unity 的 Adam Demo 中使用的技术,读者可以在 Unity Labs 的相关文章①中找到相关内容和源码实现。除了上述两种光源外,基于图像的光照(image-based lighting, IBL)同样是非常重要的光照来源。
基于图像的光照通常指的是把场景中远处的光照存储在类似环境贴图的图像中。这些环境贴图可以表示光滑物体表面反射的环境光,从而允许我们可以快速得到拥有很高细节的真实光照效果。
在 Unity 中,这种光照通常是由反射探针(Reflection Probes)机制来实现的,我们可以在 Shader中获取当前物体所在的反射探针并在需要时对它们的采样结果进行混合。当然,我们也可以实现一套自己的 IBL 机制,Sébastien Lagarde 在他的博文②里详细介绍了 IBL 的一些实现方法以及如何得到视差正确的局部环境贴图的方法,非常值得一看。
在实际开发过程中,如何放置各种光源以及调整它们和材质的参数绝对是一门学问,对场景美术人员和灯光师来说也是一项挑战。而采用 PBS 的好处之一就是,我们暴露给美术人员的材质编辑页面可以是统一的,而不再是各种令人眼花缭乱的光照模型的“大杂烩”。
① https://labs.unity.com/article/real-time-polygonal-light-shading-linearly-transformed-cosines
② https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
十一、Unity 中的 PBS 实现
在下面的内容中,我们将给出 Unity 中 PBS 的实现。需要注意的是,随着 Unity 的不断更新,其选择使用的 BRDF 模型也可能会发生变化,例如在 Unity 5.3 之前,Unity 的 PBS 中的法线分布函数 D(h)采用的是我们之前提到的归一化的 Phong 法线分布函数,而在 Unity 5.3 及其之后的版本(截止到本书完成时为 Unity 5.6)中,法线分布函数改为采用 GGX 分布。因此,我们这里旨在让读者了解完整的 PBS 数学模型,如果读者希望了解当前所用 Unity 版本的 PBS 所使用的 BRDF模型,我们强烈建议读者去翻看内置的 Shader 文件。
在之前的内容中,我们提到了 Unity 5 的 PBS 实际上是受 Disney BRDF[2]的启发。这种 BRDF 最大的好处之一就是很直观,只需要提供一个万能的 Shader 就可以让美术人员通过调整少量参数来渲染绝大部分常见的材质。我们可以在 Unity 内置的 UnityStandardBRDF.cginc 文件中找到它的实现。
总体来说,Unity 5 一共实现了两种 PBS 模型。一种是基于 GGX 模型的,另一种则是基于归一化的 Blinn-Phong 模型的,这两种模型使用了不同的公式来计算高光反射项中的法线分布函数D(h)和阴影-遮掩函数 G(l, v, h)。Unity 5.3 以前的版本默认会使用基于归一化后的 Blinn-Phong 模型来实现基于物理的渲染,但在 Unity 5.3 及后续版本中,默认将使用 GGX 模型,这和很多其他主流引擎的选择一致。
在这两种实现中,Unity 使用的 BRDF 中的漫反射项都与 Disney BRDF 中的漫反射项相同,即:
漫反射项:
image.png
baseColor 一般由纹理采样和颜色参数共同决定。
高光反射项中的菲涅耳反射函数 F(l, h)也与 Disney BRDF 中的一致,即使用的 Schlick 菲涅耳近似等式[7]:
菲涅耳反射函数:
image.png
其中,cspec一般由纹理采样或高光颜色所决定。
Unity 5 两种 PBS 模型的主要区别在于它们所选择的法线分布函数及其对应的阴影-遮掩函数的不同。基于 GGX 模型的 PBS 的法线分布函数为 GGX 分布,基于归一化 Blinn-Phong 模型的PBS 的法线分布函数则为归一化后的 Phong 分布。它们的公式分别如下:
法线分布函数:
image.png
需要注意的是,不同 Unity 版本在上述实现上可能会略有不同,比如 roughness 的指数部分会有所不同。
阴影-遮掩函数的选择更加复杂一些。在 Unity 5.3 之前的版本中,基于 GGX 模型和归一化Blinn-Phong 模型的 PBS 的阴影-遮掩函数分别是为 GGX 和 Beckmann 设计的 Smith-Schlick 模型[8]。 它们的公式分别如下:
Unity 5.3 之前的阴影-遮掩函数:
image.png
尽管很多文献都曾推荐使用上述的 Smith-Schlick 阴影-遮掩函数,然而,Naty Hoffman[1]和 Eric Heitz[12]都指出,这种 Smith-Schlick 阴影-遮掩函数是作者 Schlick 对一个错误版本的 Smith 模型的近似公式,这意味着这些 Smith-Schlick 阴影-遮掩函数并不是基于物理的,因为它不能保证微面元投影区域面积的守恒定律。在 Unity 5.3 及其后续版本中,Unity 为基于 GGX 的 PBS 模型改用了Smith-Joint 阴影-遮掩函数[12]。Smith-Joint 阴影-遮掩函数的公式如下:
Unity 5.3 以后 GGX 的阴影-遮掩函数:
image.png
在上述的式子中,Λ(ωo) 和 Λ(ωi)分别评估出射方向和入射方向上的阴影和遮掩,基于这种分开计算的 Λ(ωo) 和 Λ(ωi)的 Smith 模型,Eric Heitz[12]针对 Λ(ωo) 和 Λ(ωi)的不同组合方式列举了四种形式的阴影-遮掩函数。
上述的公式显示了其中一种被称为 Height-Correlated Masking and Shadowing 的组合方式,也是 Eric 建议在实践中使用的一种方式。由于原始的 Smith-Joint 阴影-遮掩函数涉及两个开根号操作,处于性能方面的考虑,Unity 在实现上选择使用上述仅包含乘法的近似公式来简化计算。尽管在数学上这个近似公式并不正确,但从效果上来看是足够接受的。
<hr>
尽管我们已经省略了大量的数学推导和物理原理,上面大量的公式对于某些读者来说可能仍然十分晦涩难懂,这也是为什么 PBS 总是令人望而却步的原因之一。如果读者想要深入了解基于物理的渲染的数学原理和应用的话,可以参见本章的扩展阅读部分。需要再次强调的是,由于 Unity版本的不同,内置 PBS 的实现也可能会发生变化。除此之外,在学术界和工业界仍然不断有新的或改良后的 BRDF 模型的出现,读者也可以根据项目需要选择与 Unity 实现不同的 BRDF 模型。
尤其是如果需要在移动端应用基于物理的渲染,除了效果外性能是我们最应当关心的问题之一,此时我们可能需要针对移动平台对采用的 BRDF 模型进行一些修改,读者可以在本章的扩展阅读部分中找到更多的资料。 |