1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 04:35:28 +08:00

7-1.PBR理论章节校对

This commit is contained in:
yuyingnanb
2022-12-12 16:40:03 +08:00
committed by Gary Wang
parent d33979b034
commit bab6ad6715
2 changed files with 29 additions and 33 deletions

View File

@@ -4,7 +4,7 @@
---|---
作者 | JoeyDeVries
翻译 | [J.moons](https://github.com/JiangMuWen)
校对 | Krasjet(初校)
校对 | Krasjet, JeremyYvv
!!! note
@@ -20,11 +20,7 @@ PBR或者用更通俗一些的称呼是指<def>基于物理的渲染</def>(Ph
在这次的PBR系列教程之中我们将会把重点放在最先由迪士尼(Disney)提出探讨并被Epic Games首先应用于实时渲染的PBR方案。他们基于<def>金属质地工作流</def>(Metallic Workflow)的方案有非常完备的文献记录,广泛应用于各种流行的引擎之中并且有着非常令人惊叹的视觉效果。完成这次的教程之后我们将会制作出类似于这样的一些东西:
![](../img/07/01/preview.png)
!!! Important
注意这次的理论教程是一个三部曲系列(目前还在创作中)的一部分,所以这部分教程的内容有可能随着其他两部还没完成的教程的进展而发生变化。同样,这部教程的源代码也并不完整,所以上面的图片是取自一个私人项目之中,而非本教程的代码所生成的。不过在完成之后这个图片看上去应该会好很多。
![](../img/07/01/ibl_specular_result_textured.png)
请注意这个系列的教程所探讨的内容属于相当高端的领域因此要求读者对OpenGL和着色器光照有较好的理解。读者将会需要这些相关的知识[帧缓冲](../04 Advanced OpenGL/05 Framebuffers.md)[立方体贴图](../04 Advanced OpenGL/06 Cubemaps.md)[Gamma校正](../05 Advanced Lighting/02 Gamma Correction.md)[HDR](../05 Advanced Lighting/06 HDR.md)和[法线贴图](../05 Advanced Lighting/04 Normal Mapping.md)。我们还会深入探讨一些高等数学的内容,我会尽我所能将相关的概念阐述清楚。
@@ -38,31 +34,31 @@ PBR或者用更通俗一些的称呼是指<def>基于物理的渲染</def>(Ph
![](../img/07/01/microfacets_light_rays.png)
在微观尺度下,没有任何平面是完全光滑的。然而由于这些微平面已经微小到无法逐像素继续对其进行区分,因此我们只有假设一个<def>粗糙度</def>(Roughness)参数,然后用统计学的方法来概略的估算微平面的粗糙程度。我们可以基于一个平面的粗糙度来计算出某个向量的方向与微平面平均取向方向一致的概率。这个向量便是位于光线向量\(l\)和视线向量\(v\)之间的<def>中间向量</def>(Halfway Vector)。我们曾经在之前的[高级光照](../05 Advanced Lighting/01 Advanced Lighting.md)教程中谈到过中间向量,它的计算方法如下:
在微观尺度下,没有任何平面是完全光滑的。然而由于这些微平面已经微小到无法逐像素继续对其进行区分,因此我们假设一个<def>粗糙度</def>(Roughness)参数,然后用统计学的方法来估计微平面的粗糙程度。我们可以基于一个平面的粗糙度来计算出众多微平面中,朝向方向沿着某个向量\(h\)方向的比例。这个向量\(h\)便是位于光线向量\(l\)和视线向量\(v\)之间的<def>半程向量</def>(Halfway Vector)。我们曾经在之前的[高级光照](../05 Advanced Lighting/01 Advanced Lighting.md)教程中谈到过中间向量,它的计算方法如下:
$$
h = \frac{l + v}{\|l + v\|}
$$
微平面的向方向与中间向量的方向越是一致,镜面反射的效果就越是强烈越是锐利。然后再加上一个介于0到1之间的粗糙度参数这样我们就能概略估算微平面的取向情况了:
微平面的向方向与半程向量的方向越是一致,镜面反射的效果就越是强烈越是锐利。通过使用一个介于0到1之间的粗糙度参数我们就能概略估算微平面的取向情况了:
![](../img/07/01/ndf.png)
我们可以看到,较高的粗糙度显示出来的镜面反射的轮廓要更大一些。与之相反,较小的粗糙显示出的镜面反射轮廓则更小更锐利。
我们可以看到,较高的粗糙度显示出来的镜面反射的轮廓要更大一些。与之相反,较小的粗糙显示出的镜面反射轮廓则更小更锐利。
## 能量守恒
微平面近似法使用了这样一种形式的<def>能量守恒</def>(Energy Conservation):出射光线的能量永远不能超过入射光线的能量(发光面除外)。如图我们可以看到,随着粗糙度的上升镜面反射区域会增加,但是镜面反射的亮度却会下降。如果不管反射轮廓的大小而让每个像素的镜面反射强度(Specular Intensity)都一样的话,那么粗糙的平面就会放射出过多的能量,而这样就违背了能量守恒定律。这也就是为什么正如我们看到的一样,光滑平面的镜面反射更强烈而粗糙平面的反射更昏暗。
微平面近似法使用了这样一种形式的<def>能量守恒</def>(Energy Conservation):出射光线的能量永远不能超过入射光线的能量(发光面除外)。如图我们可以看到,随着粗糙度的上升镜面反射区域会增加,但是镜面反射的亮度却会下降。如果每个像素的镜面反射强度都一样(不管反射轮廓的大小),那么粗糙的平面就会放射出过多的能量,而这样就违背了能量守恒定律。这也就是为什么正如我们看到的一样,光滑平面的镜面反射更强烈而粗糙平面的反射更昏暗。
为了遵守能量守恒定律,我们需要对漫反射光和镜面反射光之间做出明确的区分。当一束光线碰撞到一个表面的时候,它就会分离成一个<def>折射</def>部分和一个<def>反射</def>部分。反射部分就是会直接反射开而不进入平面的那部分光线,就是我们所说的镜面光照。而折射部分就是余下的会进入表面并被吸收的那部分光线,也就是我们所说的漫反射光照。
为了遵守能量守恒定律,我们需要对漫反射光和镜面反射光做出明确的区分。当一束光线碰撞到一个表面的时候,它就会分离成一个<def>折射</def>部分和一个<def>反射</def>部分。反射部分就是会直接反射开而不进入平面的那部分光线,就是我们所说的镜面光照。而折射部分就是余下的会进入表面并被吸收的那部分光线,也就是我们所说的漫反射光照。
这里还有一些细节需要处理,因为当光线接触到一个表面的时候折射光是不会立即就被吸收的。通过物理学我们可以得知,光线实际上可以被认为是一束没有耗尽就不停向前运动的能量,而光束是通过碰撞的方式来消耗能量。每一种材料都是由无数微小的粒子所组成,这些粒子都能如下图所示一样与光线发生碰撞。这些粒子在每次的碰撞中都可以吸收光线所携带的一部分或者是全部的能量而后转变成为热量。
![](../img/07/01/surface_reaction.png)
一般来说,并非所有能量都会被全部吸收,而光线也会继续沿着(基本上)随机的方向<def>发散</def>,然后再和其他的粒子碰撞直至能量完全耗尽或者再次离开这个表面。而光线脱离物体表面后将会协同构成该表面的(漫反射)颜色。不过在基于物理的渲染之中我们进行了简化,假设对平面上的每一点所有的折射光都会被完全吸收而不会散开。而有一些被称为<def>次表面散射</def>(Subsurface Scattering)技术的着色器技术将这个问题考虑了进去,它们显著提升了一些诸如皮肤,大理石或者蜡质这样材质的视觉效果,不过伴随而来的是性能下降代价
一般来说,并非全部能量都会被吸收,而光线也会继续沿着(基本上)随机的方向<def>发散</def>,然后再和其他的粒子碰撞直至能量完全耗尽或者再次离开这个表面。而光线脱离物体表面后将会协同构成该表面的(漫反射)颜色。不过在基于物理的渲染之中我们进行了简化,假设对平面上的每一点所有的折射光都会被完全吸收而不会散开。而有一些被称为<def>次表面散射</def>(Subsurface Scattering)技术的着色器技术将这个问题考虑了进去,它们显著提升了一些诸如皮肤,大理石或者蜡质这样材质的视觉效果,不过伴随而来的代价是性能下降。
对于<def>金属</def>(Metallic)表面,当讨论到反射与折射的时候还有一个细节需要注意。金属表面对光的反应与非金属材料(也被称为<def>介电质</def>(Dielectrics)材料)表面相比是不同的。它们遵从的反射与折射原理是相同的,但是**所有的**折射光都会被直接吸收而不会散开只留下反射光或者说镜面反射光。亦即是说金属表面不会显示出漫反射颜色。由于金属与电介质之间存在这样明显的区别因此它们两者在PBR渲染管线中被区别处理而我们将在文章的后面进一步详细探讨这个问题。
对于<def>金属</def>(Metallic)表面,当讨论到反射与折射的时候还有一个细节需要注意。金属表面对光的反应与非金属(也被称为<def>介电质</def>(Dielectrics))表面相比是不同的。它们遵从的反射与折射原理是相同的,但是**所有的**折射光都会被直接吸收而不会散开,只留下反射光或者说镜面反射光。亦即是说,金属表面只会显示镜面反射颜色,而不会显示出漫反射颜色。由于金属与电介质之间存在这样明显的区别因此它们两者在PBR渲染管线中被区别处理而我们将在文章的后面进一步详细探讨这个问题。
反射光与折射光之间的这个区别使我们得到了另一条关于能量守恒的经验结论:反射光与折射光它们二者之间是**互斥**的关系。无论何种光线,其被材质表面所反射的能量将无法再被材质吸收。因此,诸如折射光这样的余下的进入表面之中的能量正好就是我们计算完反射之后余下的能量。
@@ -77,13 +73,13 @@ float kD = 1.0 - ks; // 折射/漫反射 部分
## 反射率方程
在这里我们引入了一种被称为[渲染方程](https://learnopengl.com/wiki-rendereuqation)(Render Equation)的东西。它是某些聪明绝顶人所构想出来的一个精妙的方程式,是如今我们所拥有的用来模拟光的视觉效果最好的模型。基于物理的渲染所坚定遵循的是一种被称为<def>反射率方程</def>(The Reflectance Equation)的渲染方程的特化版本。要正确理解PBR 很重要的一点就是要首先透彻理解反射率方程:
在这里我们引入了一种被称为[渲染方程](https://learnopengl.com/wiki-rendereuqation)(Render Equation)的东西。它是某些聪明绝顶人所构想出来的一个精妙的方程式,是如今我们所拥有的用来模拟光的视觉效果最好的模型。基于物理的渲染所坚定遵循的是一种被称为<def>反射率方程</def>(The Reflectance Equation)的渲染方程的特化版本。要正确理解PBR很重要的一点就是要首先透彻理解反射率方程:
$$
L_o(p,\omega_o) = \int\limits_{\Omega} f_r(p,\omega_i,\omega_o) L_i(p,\omega_i) n \cdot \omega_i d\omega_i
$$
反射率方程一开始可能会显得有些吓人,不过随着我们慢慢对其进行剖析,读者最终会逐渐理解它的。要正确理解这个方程式,我们必须要稍微涉足一些<def>辐射度量学</def>(Radiometry)的内容。辐射度量学是一种用来度量电磁场辐射(包括可见光)的手段。有很多种辐射度量(radiometric quantities)可以用来测量曲面或者某个方向上的光,但是我们将只会讨论其中和反射率方程有关的一种。它被称为<def>辐射率</def>(Radiance),在这里用\(L\)来表示。辐射率被用来量化单一方向上发射来的光线的大小或者强度。由于辐射率是由许多物理变量集合而成的,一开始理解起来可能有些困难,因此我们首先关注一下这些物理量:
反射率方程一开始可能会显得有些吓人,不过随着我们慢慢对其进行剖析,读者最终会逐渐理解它的。要正确理解这个方程式,我们必须要稍微涉足一些<def>辐射度量学</def>(Radiometry)的内容。辐射度量学是一种用来度量电磁场辐射(包括可见光)的手段。有很多种辐射度量(radiometric quantities)可以用来测量曲面或者某个方向上的光,但是我们将只会讨论其中和反射率方程有关的一种。它被称为<def>辐射率</def>(Radiance),在这里用\(L\)来表示。辐射率被用来量化来自单一方向上的光线的大小或者强度。由于辐射率是由许多物理变量集合而成的,一开始理解起来可能有些困难,因此我们首先关注一下这些物理量:
**辐射通量**:辐射通量\(\Phi\)表示的是一个光源所输出的能量以瓦特为单位。光是由多种不同波长的能量所集合而成的而每种波长则与一种特定的可见的颜色相关。因此一个光源所放射出来的能量可以被视作这个光源包含的所有各种波长的一个函数。波长介于390nm到700nm纳米的光被认为是处于可见光光谱中也就是说它们是人眼可见的波长。在下面你可以看到一幅图片里面展示了日光中不同波长的光所具有的能量
@@ -194,7 +190,7 @@ $$
Cook-Torrance BRDF的镜面反射部分包含三个函数此外分母部分还有一个标准化因子 。字母DF与G分别代表着一种类型的函数各个函数分别用来近似的计算出表面反射特性的一个特定部分。三个函数分别为法线分布函数(Normal **D**istribution Function),菲涅尔方程(**F**resnel Rquation)和几何函数(**G**eometry Function)
- **法线分布函数**:估算在受到表面粗糙度的影响下,向方向与中间向量一致的微平面的数量。这是用来估算微平面的主要函数。
- **法线分布函数**:估算在受到表面粗糙度的影响下,向方向与半程向量一致的微平面的数量。这是用来估算微平面的主要函数。
- **几何函数**:描述了微平面自成阴影的属性。当一个平面相对比较粗糙的时候,平面表面上的微平面有可能挡住其他的微平面从而减少表面所反射的光线。
- **菲涅尔方程**:菲涅尔方程描述的是在不同的表面角下表面所反射的光线所占的比率。
@@ -203,19 +199,19 @@ Cook-Torrance BRDF的镜面反射部分包含三个函数此外分母部分
### 法线分布函数
<def>法线分布函数</def>\(D\)或者说镜面分布,从统计学上近似表示了与某些(中间)向量\(h\)取向一致的微平面的比率。举例来说,假设给定向量\(h\)如果我们的微平面中有35%与向量\(h\)取向一致则法线分布函数或者说NDF将会返回0.35。目前有很多种NDF都可以从统计学上来估算微平面的总体取向度只要给定一些粗糙度的参数以及一个我们马上将要用到的参数Trowbridge-Reitz GGX
<def>法线分布函数</def>\(D\),从统计学上近似表示了与某些(半程)向量\(h\)取向一致的微平面的比率。举例来说,假设给定向量\(h\)如果我们的微平面中有35%与向量\(h\)取向一致则法线分布函数或者说NDF将会返回0.35。目前有很多种NDF都可以从统计学上来估算微平面的总体取向度只要给定一些粗糙度的参数我们马上将要用到的Trowbridge-Reitz GGX
$$
NDF_{GGX TR}(n, h, \alpha) = \frac{\alpha^2}{\pi((n \cdot h)^2 (\alpha^2 - 1) + 1)^2}
$$
在这里\(h\)表示用来与平面上微平面做比较用的中间向量,而\(a\)表示表面粗糙度。
在这里\(h\)表示用来与平面上微平面做比较用的半程向量,而\(a\)表示表面粗糙度。
如果我们把\(h\)当成是不同粗糙度参数下,平面法向量和光线方向向量之间的中间向量的话,我们可以得到如下图示的效果:
![](../img/07/01/ndf.png)
当粗糙度很低(也就是说表面很光滑)的时候,与中间向量取向一致的微平面会高度集中在一个很小的半径范围内。由于这种集中性NDF最终会生成一个非常明亮的斑点。但是当表面比较粗糙的时候微平面的取向方向会更加的随机。你将会发现与\(h\)向量取向一致的微平面分布在一个大得多的半径范围内,但是同时较低的集中性也会让我们的最终效果显得更加灰暗。
当粗糙度很低(也就是说表面很光滑)的时候,与半程向量取向一致的微平面会高度集中在一个很小的半径范围内。由于这种集中性NDF最终会生成一个非常明亮的斑点。但是当表面比较粗糙的时候微平面的取向方向会更加的随机。你将会发现与\(h\)向量取向一致的微平面分布在一个大得多的半径范围内,但是同时较低的集中性也会让我们的最终效果显得更加灰暗。
使用GLSL代码编写的Trowbridge-Reitz GGX法线分布函数是下面这个样子的
@@ -246,7 +242,7 @@ $$
G_{SchlickGGX}(n, v, k) = \frac{n \cdot v}{(n \cdot v)(1 - k) + k }
$$
这里的\(k\)是\(\alpha\)基于几何函数是针对直接光照还是针对IBL光照的重映射(Remapping) :
这里的\(k\)是\(\alpha\)的重映射(Remapping),取决于我们要用的是针对直接光照还是针对IBL光照的几何函数:
$$
k_{direct} = \frac{(\alpha + 1)^2}{8}
@@ -308,7 +304,7 @@ $$
![](../img/07/01/fresnel.png)
菲涅尔方程还存在一些细微的问题。其中一个问题是Fresnel-Schlick近似仅仅对<def>电介质</def>或者说非金属表面有定义。对于<def>导体</def>(Conductor)表面(金属),使用它们的折射指数计算基础折射率并不能得出正确的结果,这样我们就需要使用一种不同的菲涅尔方程来对导体表面进行计算。由于这样很不方便,所以我们预计算出平面对于<def>法向入射</def>\(F_0\))的反应(处于0度角好像直接看向表面一样然后基于相应观察角的Fresnel-Schlick近似对这个值进行插值用这种方法来进行进一步的估算。这样我们就能对金属和非金属材质使用同一个公式了。
菲涅尔方程还存在一些细微的问题。其中一个问题是Fresnel-Schlick近似仅仅对<def>电介质</def>或者说非金属表面有定义。对于<def>导体</def>(Conductor)表面(金属),使用它们的折射指数计算基础折射率并不能得出正确的结果,这样我们就需要使用一种不同的菲涅尔方程来对导体表面进行计算。由于这样很不方便,所以我们预计算出平面对于<def>法向入射</def>的结果\(F_0\)处于0度角好像直接看向表面一样然后基于相应观察角的Fresnel-Schlick近似对这个值进行插值用这种方法来进行进一步的估算。这样我们就能对金属和非金属材质使用同一个公式了。
平面对于法向入射的响应或者说基础反射率可以在一些大型数据库中找到,比如[这个](http://refractiveindex.info/)。下面列举的这一些常见数值就是从Naty Hoffman的课程讲义中所得到的
@@ -350,13 +346,13 @@ $$
这里可以观察到的一个有趣的现象所有电介质材质表面的基础反射率都不会高于0.17这其实是例外而非普遍情况。导体材质表面的基础反射率起点更高一些并且大多在0.5和1.0之间变化。此外,对于导体或者金属表面而言基础反射率一般是带有色彩的,这也是为什么\(F_0\)要用RGB三原色来表示的原因法向入射的反射率可随波长不同而不同。这种现象我们**只能**在金属表面观察的到。
金属表面这些和电介质表面相比所独有的特性引出了所谓的<def>金属工作流</def>的概念。也就是我们需要额外使用一个被称为<def>金属度</def>(Metalness)的参数来参与编写表面材质。金属度用来描述一个材质表面是金属还是非金属的。
这些金属表面相比于电介质表面所独有的特性引出了所谓的<def>金属工作流</def>的概念。也就是我们需要额外使用一个被称为<def>金属度</def>(Metalness)的参数来参与编写表面材质。金属度用来描述一个材质表面是金属还是非金属的。
!!! important
理论上来说一个表面的金属度应该是二元的要么是金属要么不是金属不能两者皆是。但是大多数的渲染管线都允许在0.0至1.0之间线性的调配金属度。这主要是由于材质纹理精度不足以描述一个拥有诸如细沙/沙状粒子/刮痕的金属表面。通过对这些小的类非金属粒子/刮痕调整金属度值,我们可以获得非常好看的视觉效果。
通过预先计算电介质与导体的\(F_0\)值我们可以对两种类型的表面使用相同的Fresnel-Schlick近似但是如果是金属表面的话就需要对基础反射率添加色彩。我们一般是按下面这个样子来实现的:
通过预先计算电介质与导体的\(F_0\)值我们可以对两种类型的表面使用相同的Fresnel-Schlick近似但是如果是金属表面的话就需要对基础反射率添加色彩。我们一般是按下面这来实现的:
```c++
vec3 F0 = vec3(0.04);
@@ -388,7 +384,7 @@ $$
## 编写PBR材质
在了解了PBR后面的数学模型之后最后我们将通过说明美术师一般是如何编写一个我们可以直接输入PBR的平面物理属性的来结束这部分的讨论。PBR渲染管线所需要的每一个表面参数都可以用纹理来定义或者建模。使用纹理可以让我们逐个片段的来控制每个表面上特定的点对于光线是如何响应的不论那个点是金属,粗糙或者平滑,也不论表面对于不同波长的光会有如何的反应。
在了解了PBR后面的数学模型之后最后我们将通过说明美术师一般是如何编写一个我们可以直接输入PBR的平面物理属性的来结束这部分的讨论。PBR渲染管线所需要的每一个表面参数都可以用纹理来定义或者建模。使用纹理可以让我们逐个片段的来控制每个表面上特定的点对于光线是如何响应的不论那个点是不是金属,粗糙或者平滑,也不论表面对于不同波长的光会有如何的反应。
在下面你可以看到在一个PBR渲染管线当中经常会碰到的纹理列表还有将它们输入PBR渲染器所能得到的相应的视觉输出
@@ -404,7 +400,7 @@ $$
**AO**<def>环境光遮蔽</def>(Ambient Occlusion)贴图或者说<def>AO</def>贴图为表面和周围潜在的几何图形指定了一个额外的阴影因子。比如如果我们有一个砖块表面反照率纹理上的砖块裂缝部分应该没有任何阴影信息。然而AO贴图则会把那些光线较难逃逸出来的暗色边缘指定出来。在光照的结尾阶段引入环境遮蔽可以明显的提升你场景的视觉效果。网格/表面的环境遮蔽贴图要么通过手动生成要么由3D建模软件自动生成。
美术师们可以在纹素级别设置或调整这些基于物理的输入值还可以以现实世界材料的表面物理性质来建立他们的材质数据。这是PBR渲染管线最大的优势之一因为不论环境或者光照的设置如何改变这些表面的性质是不会改变的这使得美术师们可以更便捷获取物理可信的结果。在PBR渲染管线中编写的表面可以非常方便的在不同的PBR渲染引擎间共享使用不论处于何种环境中它们看上去都会是正确的因此看上去也会更自然。
美术师们可以在纹素级别设置或调整这些基于物理的输入值还可以以现实世界材料的表面物理性质来建立他们的材质数据。这是PBR渲染管线最大的优势之一因为不论环境或者光照的设置如何改变这些表面的性质是不会改变的这使得美术师们可以更便捷获取物理可信的结果。在PBR渲染管线中编写的表面可以非常方便的在不同的PBR渲染引擎间共享使用不论处于何种环境中它们看上去都会是正确的因此看上去也会更自然。
## 延伸阅读

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB