前言
在实时渲染的领域里,所有的东西都是胡诌的,只有相对胡诌和没那么胡诌的区别。PBR材质就是相对没那么胡诌的那个,当中还是有大量的东西是很随便的。
材质参数
我们都知道经典的Phong材质控制五个参数,除去Ambient之外,有:
Diffuse Intensity
Diffuse Color
Specular Intensity
Specular Color
Specular Hardness
反正就是这五个自由量了,我们把它转换成另外的一些参数:
Albedo Color:反照颜色
Metalness:金属性,或导电性
Fresnel Color:菲涅耳颜色,即反射颜色
Roughness:粗糙度,即1 - Glossiness(光滑度)
略有差别,但是大都是对应的,除了Diffuse Intensity,因为从现在开始Diffuse Intensity是一个常量了,与材质无关的常量。
光照模型
$$
L = (f_{\text {Albedo}}(v, l, c_{\text {Albedo}}) + f_{\text {Specular}}(n, l, v, c_{\text {Fresnel}})) \otimes c_\text {Light} \cdot \pi (n \cdot l)
$$
我们看这个公式总体上是一种(A+B)*C的感觉。C是一切视觉的源头 —— 光,所以它作为整个式子的一个因子乘进去。$\pi (n \cdot l)$跟我们以前用Phong模型的时候算diffuse部分的方式一样:不难理解,越是斜的面越难以接收到光。$c_\text {Light}$是光的颜色,你可以根据距离衰减即很多其它的因素,决定这个颜色,也不必局限在0到1的范围内,反正我们有HDR。
剩下的A+B,就分别是Albedo项和Specular项了。跟Phong模型相比,而Specular仍然是完美的镜面反射。但是Diffuse项不见了,变成了Albedo项。
不知大家还记不记得Diffuse的意义:表面均匀反射光源的方向到半球各个方向。而Albedo是这样一个意义:不知道从哪里来但是在经过若干(物体内部或者表面的)反射散射之后,总而言之,这表面上这一点射出的一堆杂乱的光线”。两者不同的是,Diffuse我们知道光线是从哪里射入的,也知道从哪里射出。但是Albedo我们不知道光线是从哪里射入的,包括漫反射和次表面散射。这个非常难以估量。
“哦,非常难以估量对吧”。游戏程序员听完光学专家的报告后,一摔笔记本,“那我们他妈就不算了”。从此在很多游戏里,就有:
$$
f_{\text {Albedo}}(v, l, c_{\text {Albedo}}) = \frac 1 \pi c_{\text {Albedo}}
$$
也就是说直接乘了一个系数平衡一下外面光照的那个$\pi$。对就是这么任性。我们可以看到把这一项提到括号外面之后,是不是有一种Lambertian模型漫反射的感觉,虽然它的意义是反照。这就是为什么我刚才说漫反射系数变成了常数(1)。而很多地方在讲这一项的时候,还是把它说成是Diffuse或者Lambertian Model。但是要记住,这其实是Albedo,只不过我们在简化它的时候不精确地简化成了漫反射而已。
BRDF和微表面理论
讲完了胡诌的Albedo,就是没那么胡诌的BRDF了。讲数学、讲物理,我是怎么都不够那些大神来的了。大家在读这一节的时候,记得要跟龚敏敏的文章和Real Time Rendering一起看。
BRDF(双向反射分布函数)是仅仅对表面反射的度量,表面以下的散射情况是不考虑的。它是一个描述“从某个方向射入的光线,从哪些方向上反射出去了呢?”的分布,或者“从某个方向看到了一束光线,它可能是由哪些方向射进来的光线的反射光组成的呢?”的分布,这是它“双向”的意义所在。分布是Solid Angle空间上的,也就是弧度角的三维版,不过我们大可不去关心它。
BRDF虽然度量所有的反射光线,但是没有规律可循的反射,我们刚才放在Albedo里一起算了。所以现在算的就只有有规律可循的,也就是镜面反射的。所以我们引进了微表面模型来度量镜面反射。总结来说,我们对射出光线的三种分类:
* | 次表面散射(SSS) | 漫反射(Diffuse) | 镜面反射(Specular) |
---|---|---|---|
实时渲染 | Albedo | Albedo | Microfacet |
简化模型 | 0 | Albedo | Microfacet |
物理度量 | BSSDF | BRDF | BRDF |
微表面模型的核心是假设了物体由很多微小的__完美镜面__组成,并且创造出“宏观法线”和“微观法线”的概念。所谓宏观法线,就是在描述物体形状时计算出来的法线,或者法线贴图中采出来的法线。而微观法线,是用来衡量物体微观、微表面下的粗糙程度用的,它对材质的光学性质有很大影响,但是不描述物体的几何性质。
两个法线是有一定联系的,毕竟宏观是由微观组成的。微表面大多数还是和宏观表面同向,但是呈现一定的概率分布。对于粗糙的表面来说,貌合神离,很多微表面朝向其它方向;对于光滑的表面来说,众志成城,大家都向反射同一个方向的光。
微表面度量镜面反射,抛弃所有无法将光线反射到人眼中的微表面。没有被抛弃的那些微表面,拥有Half Vector,它们是光源和人眼之间的完美镜面。Half Vector是什么?记不记得以前算Specular是怎么算的,用视线和光线之和,跟法线求点积。对,现在你知道Half Vector是什么了。
$$
h = \text{normalize}(v + l)
$$
Cook-Torrance Model
Cook-Torrance是在微表面理论上建立的模型,引入了Roughness这一个参数,作为整个模型的核心,核心思想是度量拥有Half Vector的可见微表面数量。我们先回顾一下刚才谈到的概念:
只有拥有Half Vector的微表面能提供Specular高光
微表面法线(就是微观法线)总体跟宏观表面一致,但是有一定的分布
微表面有可能不可见,稍微要调整一下
我们为了计算Specular高光,就是要计算表面上__可见的、拥有的Half Vector的微表面__。所以,我们一个一个解决这些问题。
$$
f_\text{CookTorr}(n, v, l) = \frac{DGF}{4(n \cdot l)(v \cdot n)}
$$
分母是用来保持能量和一些经验参数,不去深究。我们来一个一个看看DFG分别解决的是什么问题:
Distribution(n, h): 分布项。解决的最基本的数量问题。
Geometry(l, v, h, n): 几何项。解决的是可见的问题。
Fresnel(n, l, h): 菲涅耳反射项。解决的是颜色和反射强度的光学问题。
Distribution
单纯按照一个表面的法线未必能把光源的光反射给你,但是它下面的一个微表面或许可以。显然,这样的微表面的法线与宏观表面越是接近,出现的机率就越大。这很容易用一个概率密度函数去表达。只要是围绕一个中心分布,你喜欢的话可以用正态分布、学生氏分布 —— 但是在图形学里我们更喜欢Beckmann分布,它更有物理背景。
$$
\alpha = \text{Roughness}^2 \\
D(n, h) = \frac{\alpha^2}{\pi((n \cdot h)^2 (\alpha^2 - 1) + 1)^2}
$$
Geometry
这个因子在考虑光线的射入和射出可能会被遮挡的问题。
$$
k = \frac {(\text{Roughness} + 1)^2}{8} \\
G_1(x, n) = \frac{n \cdot x}{(n \cdot x)(1 - k) + k} \\
G(l, v, h, n) = G_1(l, n)G_2(v, n)
$$
握草这一大堆什么来的。不急不急我们慢慢看一下。k就是遮挡率了,一个由粗糙度算出来的经验参数。在遮挡率接近0的时候,G1也接近1,也就是几乎所有的微表面都能被看到,当然,不可能是0,因为算不出来(笑)。在遮挡率接近1的时候,G1接近nx,也就是越是垂直于表面的光线难以被遮挡,越是斜的光线越是被遮挡得多。
Fresnel
刚才我们一直都在算微表面的数量,而现在做的则是类似于以前算反射强度的那一步,并且把反射颜色引入进来。当然了,现在算的就不是什么点积了,那不物理。物理的是Fresnel方程,它描述了反射光强度和反射角度的关系。
不知道大家以前学大学物理光学的时候,有没有接触过偏振光。一束自然光里常常会有两种偏振态的偏振光,两种的电场方向相互垂直。电场方向与反射介质平面的夹角越是小的一方,就越容易被反射。以前做过相关练习题,到现在还有印象。大家也可以试着回忆一下以前物理老师讲过的偏振原理。
根据物理测量,Fresnel方程可以通过Schlick等式去近似:
$$
F_{\text{Schlick}}(l, h) = c_\text{Fresnel} + (1 - c_\text{Fresnel})(1 - (l * h)^5)
$$
这里倒没有太多我们非物理专业可以折腾的事情了。
金属和塑料
根据物理测量,导体的Albedo Color几乎为0,而Frenel Color各异且较高。而绝缘体的Albedo Color各异,但Fresnel Color略低(0.04),且均匀反射。游戏程序员于是又动了歪脑筋:他们一直嫌GBuffer的空间太少了。
他们把两个颜色合并成了一个颜色,称为Base Color(基调色),然后根据材质的导电程度,看看这个基调色究竟是作为反照色还是反射色。又或者是半导体 —— 既组成反照色也组成反射色。
多光源和环境贴图
光学原理很基础的一条就是线性性:光的叠加就是线性叠加,不是混合,没有先后。所以多光源的材质,只需要多遍渲染,然后用Plus Blend混合起来就可以了。
在多光源达到一个极致的情况下,就是到处都是光源。很多时候我们用环境贴图来描述这些极致多的光源,通常用来描述镜面反射的结果。因为之前我们曾经有一个Distribution项目,它让光不仅仅作用在正对着光源的方向,还成概率地作用在周围。也就是一个扩散。
不知道说到Distribution大家想到什么。我想到了高斯分布、高斯卷积核、高斯滤波。我一年多以前曾经发过一篇博客[1],讲的是卷积,希望大家还记得那只模糊的Saber。当每一点都产生了一个形状的扩散的时候,事实上就是一个卷积或者一个滤波。结果就是模糊。
在实时渲染时,我们常常会把纹理预先滤好波,然后放在不同Level的Mipmap上。然后在画的时候,只要替换掉刚才的Fresnel Color,就可以做出不同粗糙程度的环境贴图了。
参考资料
[2] 龚敏敏讲金属和塑料的文章:https://zhuanlan.zhihu.com/p/...
[3] BRDF的详细推导:https://zhuanlan.zhihu.com/p/...
[4] 插图集中来源:Real Time Rendering
对,但是本文没有插图,因为我太懒了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。