Cocs Creator 3.x 开始,PBR 就作为了标准材质,本文和大家一起学习一下 PBR的 渲染。
为什么会出现PBR?
从古至今,每一个新东西的出现,一定伴随着它的存在价值。要么是为了提高产能,要么是为了解决某个问题,PBR 渲染也是如此。
PBR 全称 Physically Based Rendering,基于物理的渲染。
长期以来,图形学一直信奉着一句话:“如果看起来是对的,那么就是对的”,这是因为当时的技术有限。
在 PBR 出现之前,主流的是 Blinn-Phong 这类传统光照模型属于经验模型,美术人员一般是凭感觉来调整参数,制作贴图,行业内并没有一个固定的标准。
(暴雪使用传统光照模型开发的游戏《魔兽世界》)
那如果制作出来的美术效果符合 A 的审美,但不符合 B 的审美,又该如何处理呢?这就产生了第一个问题:没有统一的美术标准。
由于制作出来的贴图是固定的,当光照位置变化或者视线调整的时候,就需要重新制作贴图,这会产生第二个问题:游戏开发工作效率低下。
传统光照模型毕竟是由“人为经验”产生的,它并不符合真实的物理原则,渲染出来的效果也差强人意,因此产生了第三个问题:渲染缺乏真实感。
与此同时,硬件技术也在不断发展,人们开始不满足于当前的画面表现,开始追求更加真实的渲染,于是 PBR 渲染应运而生。
迪士尼白皮书创造统一标准
2012年,迪士尼发布PBR 白皮书(《Physically Based Shading at Disney》),为行业创造了一个共同的标准。
Disney PBR 提供了一组标准化的材质参数,通过调整 subsurface, metallic, specular, roughness, sheen 等参数的值,就能控制物体的材质效果。
这给行业提供了一个共同的使用框架,让美术调节起来更加方便。
然而,虽然有了固定的标准,但 Disney PBR 却不一定符合物理规则。但白皮书的发布推动了 PBR 在游戏开发、电影制作等领域的广泛应用。
发展到我们现在使用的 PBR,它模拟的就是真实世界中光线和材质之间的相互作用,以呈现出更加真实的效果。
需要注意的是,这里基于物理的渲染,依然是对现实世界的近似,只是它更加贴近我们真实的物理世界。
PBR 的主要核心有两个:
-
基于物理的光照 -
基于物理的材质
通过模拟光照和材质的物理特性,就可以渲染出更加逼真的图形效果。
PBR的两套工作流
在谈光照和材质之前,我们先来了解 PBR 的工作流。
PBR 有两套工作流:
-
Metallic-Roughness Workflow(金属度-粗糙度工作流):
通过调整 Metallic 和 Roughness 的值来调整材质,Metallic 和 Roughness 是一个0~1之间的值。
-
Specular-Glossiness Workflow(反射率-光泽度工作流):
通过调整 Specular(高光)和 Glossiness(光泽度)的值来调整材质。Specular 用 RGBA 颜色来表示 ,Glossiness 是一个0~1之间的值。
主流游戏引擎如 Cocos 等用的 Metallic-Roughness 工作流;而有一些引擎则同时支持 Specular-Glossiness 工作流和 Metallic-Roughness 工作流。
这两种工作流都是用来定义材质表现的,区别是两者用于处理材质的参数不同。
(两种工作流)
从上图中可以看到,在 Specular-Glossiness 工作流中, Specular 是通过调整 RGBA 颜色来控制的,而在 Metallic-Roughness 中,只需要调整 0~1 的值。
相比起来,Specular-Glossiness 不够简捷方便。因此在实际中,用的更多的还是 Metallic-Roughness 这一套工作流。
PBR 几个理论
PBR 遵循几个基本理论:
1. 微平面理论
在微观下,没有任何平面是完全光滑的,表面都有小凹凸。越粗糙的物体,微表面的凹凸越多,越光滑的物体,微表面的凹凸越少,这个很好理解。

2. 能量守恒
能量守恒规定,在不考虑自发光的情况下,出射光线的能量永远不能超过入射光线的能量。
换句话说,当一束光照射到物体表面后,要么产生了能量损耗,要么没有。
即:反射光的能量 ≤ 入射光的能量。

这就可以解释我们平时看到的一些现象。
比如当物体表面的粗糙度比较高时,由于微表面的凹凸不平,镜面反射形成的高光区域会变大;但为了保持能量守恒,镜面反射的亮度就会下降。而粗糙度低的时候,则刚好相反。
所以我们可以看到,表面越光滑的物体,镜面反射越强烈,而表面越粗糙的物体,反射却越昏暗。
3. 菲涅尔反射
菲涅尔反射也比较好理解。
当我们看一潭水时,看离视线越近的地方,水面反射越弱,容易看到水底;而看离视线越远的地方,水面反射越强,越看不到水底。
这就是菲涅尔反射,它和光线的入射角度以及物体的材质有关。

基于物理的贴图
上面提到,一个物体要渲染出真实感,离不开 PBR 材质 和 PBR 光照。
而 PBR 材质,通常依赖于 PBR 贴图。
(通过PBR贴图渲染的闹钟)
PBR 贴图可以描述材质的各种属性。通过 PBR 贴图,就可以模拟物体的基础颜色、金属度、粗糙度、法线方向、环境遮蔽等。
对于不同的工作流,需要用到的 PBR 贴图也有所不同。
-
Metallic-Roughness Workflow:
BaseColor + Roughness + Metallic + Ambient Occlusion + Nomal + Height
-
Specular-Glossiness Workflow:
Diffuse + Glossiness + Specular + Ambient Occlusion + Normal + Height

两种工作流在贴图制作中,主要是前三张图不同,如 Ambient Occlusion、Normal、Height 贴图是可以共用的。
基于物理的光照
在聊光照之前,首先我们要明确一个概念,无论是经验光照模型 Blinn-Phong,还是基于物理的光照 PBR,都遵循最基本的光照模型:
物体最终颜色 = Ambient(环境光)+ Diffuse(漫反射)+ Specular(高光反射)+ Emissive(自发光)
只是不同模型在处理这四个部分的计算时,采用的方法不同。
(不包含自发光的 Blinn-phong 光照模型)
PBR则使用了 渲染方程 来计算物体的最终颜色。
渲染方程是目前用来模拟光和材质的交互表现时,视觉效果最好的模型。
渲染方程的公式如下图所示。
它使用的是数学建模的方式来处理光照中的四个组成部分 —— Ambient、Diffuse、Specular 和 Emissive。
使用数学的方式可以让渲染的画面更加贴近真实的物理世界,PBR 渲染做的就是这么一件事。
渲染方程不需要我们自己计算,游戏引擎会帮我们做好一切,自动计算好 Ambient、Diffuse 和 Specualr 的光照,然后根据引擎内置的公式,分配给 Roughness, Metallic 等参数。
因此,我们在调整 PBR 材质时,可以通过调整这几个值,来调整材质的参数,从而实现想要的材质效果。
而 Emissive 被认为是物体主动发出的光,所以在游戏引擎中通常单独计算。
各个游戏引擎都提供了一种方式来独立配置和处理自发光,它不会与其他光照项混合,而是单独影响物体的外观。我们也可以在材质的属性中自行设置自发光的颜色和强度。

渲染方程与BRDF
渲染方程看上去好像有点复杂,但是不要慌,下面玉兔就带大家来理解这个方程。
我们要观察到某个物体,需要以下几个动作:
-
有光照:没有光照,物体看上去是黑的。 -
用眼睛看:有看的方向。 -
要看到物体:有物体的颜色表现。
整个渲染方程,做的就是一件事 —— 计算人眼在某个观察点上,看到的物体的颜色。
整个方程由3个部分组成,等号左边 1 个,等号右边 2 个。
-
等号左边:Lo(v) ,表示到达观察点的总光照。 -
等号右边第一项:Le(v),表示物体的自发光 -
等号右边第二项:∫ fr(ωi, v)(Li(p,ωi)(n·ωi)) dωi,表示物体表面真正接收到的,来自各个入射方向上的入射光线。
直接解释可能不太好理解,我们再回顾一下刚刚上面提到的光照模型公式:
物体最终颜色 = Ambient(环境光)+ Diffuse(漫反射)+ Specular(高光反射)+ Emissive(自发光)
我们可以把渲染方程中的各项,和光照模型对应起来:
-
Lo(v) --> 物体最终颜色
-
Le(v) --> Emissive
-
∫ fr(ωi, v)(Li(p,ωi)(n·ωi)) dωi --> Ambient + Diffuse + Specular
其中,比较难理解的是积分部分 ∫ fr(ωi, v)(Li(p,ωi)(n·ωi)) dωi,我们把积分拆成三个部分,来具体理解:
-
内项1:fr(ωi, v) -
内项2:Li(p,ωi)(n·ωi) -
积分项:∫ ( 内项1 * 内项2) dωi
先来看 Li(p,ωi)(n·ωi)。
Li(p,ωi),表示来自方向ωi的入射光线的光照。
由于入射光线的方向不同,物体表面接收到的能量也不同。当光线和物体法线的夹角呈 θ 角时,物体表面的受光其实是 光照 * cosθ,写成点积的形式,即:n·ωi。

因此,Li(p,ωi)(n·ωi) 表示:物体表面真实接收到的,来自ωi方向上的入射光线。
而 fr(ωi, v)表示:表面反射模型。
什么是表面反射模型呢?
不同的材质,对光线的反射程度不同,而表面反射模型,考虑是材质表面如何反射光线,应该反射多少。
(不同的材质对光线的反射程度不同)
fr(ωi, v) 描述的是:来自入射方向ωi的光,有多少反射到了出射方向v上。这就是大名鼎鼎的 BRDF(Bidirectional Reflectance Distribution Function)—— 双向反射分布函数。
最后在入射光所形成的半球 Ω 上,对所有可能的入射方向 ωi 进行积分求和,就可以计算出最终的出射光光照。
∫ fr(ωi, v)(Li(p,ωi)(n·ωi)) dωi 表示的就是:物体表面真正接收到的,来自各个入射方向上的入射光线。

物体接受到的来自外部的光线(∫fr(ωi, v)(Li(p,ωi)(n·ωi))dωi) + 物体的自发光(Le(v)),就可以计算出到达观察点的总光照(Lo(v))。
这就是渲染方程。
今天的目的是科普扫盲,不再给大家细讲具体的公式计算,因为还需要补充辐射度量学的知识,文字太多,不方便大家消化,玉兔把这部分放在了 知识星球 里。
不同的游戏引擎可能使用不同的 BRDF 模型,来计算 Diffuse,Specular 和 Ambient,这里不多加赘述。
渲染方程不需要我们自己计算,大家了解即可,游戏引擎通常会帮我们做好一切,自动计算光照。我们在材质中,调节 Metallic, Roughness 等值,就能实现想要的材质效果。
(Metallic = 1.0, Roughness = 0.0~1.0时的材质表现)
看到这里,你有没有感觉,数学其实也没那么难。
写在最后
想要更深入体会 PBR 与传统光照模型的区别,建议大家看一下我之前的视频:基础光照,可以在玉兔的 视频号:-不捣药的玉兔-,复习回顾。