Real-time Physically-based Materials

PBR:Physically-Based Rendering:基于物理的渲染

通常也把基于物理的材质叫做 PBR

Microfacet BRDF

1. Fresnel term

反射能量的多少取决于入射光的角度,入射光与法线接近垂直时,反射光是最多的

菲涅尔项计算公式过于复杂,一般采用 Schlick 近似

η 表示折射率,θ 是入射角度

2. NDF

Normal Distribution Function:法线分布

法线集中就是 Specular,分散就是 Diffuse,之间就是 Glossy

关于法线分布,人们发明了许多分布的模型去描述它,实时渲染中常用的模型就是 Beckman 模型和 GGX 模型

Beckman

Beckmann NDF 模型很像高斯分布,它有两个参数,α 也就是 roughness 粗糙度 ,α 越小 **D(h) **的值自然也就越大,物体看上去也就更光滑,反之则越粗糙

从数学角度上,α 实则对应了高斯中的 σ,也就是标准差,它决定了分布的胖瘦

GGX

GGX模型有一个非常典型的特点那就是拖尾或者说长尾

Beckmann 的高光边缘比较锐利,界限比较分明因为它描述的分布就是从较高的峰值很快衰减到 0

而 GGX 则不同,在它高光的周围有一圈光晕现象,也就是略微模糊

GTR

Generalized Trowbridge-Reitz

增加一个 γ 参数,可以控制尾巴长短,可以选择趋近于 GGX 还是 Beckmann

3. Shadowing-Masking Term

解决微表面自遮挡问题

对于边缘处,入射光 i、反射光 o 和法线 n 都垂直,分母很小,因此 f 值很大,球的边缘就全白了,不合理。

通常在 i、o 和 n 垂直时,物体自遮挡情况很难严重,因此 G 项会很小,从而平衡。

Smith shadow-masking term

先假设一个法线分布,然后推导出一个 G 项。可以看到在 i 和 m 垂直时,G 项趋近于 0,发生剧烈遮挡。

Multiple Bounces

随着物体粗糙度越大,物体变得越暗,因为粗糙物体发现分布更散,自遮挡现象严重。

但其实自遮挡并不一定能完全挡住,光线可能会有多次 Bounce 从而跳出自遮挡。

Kulla-Conty Approximation

E 是反射出去的能量(渲染方程,积分写法不同),1 - E 就是损失的能量,想办法补回来。

也就是说我们要设计一种函数使得它的积分为 **1-E(μo)**。首先,考虑到 BRDF 的可逆对称性,我们需要把视角因素考虑进去,所以乘上 **1-E(μi)**,然后乘上个 c,解 c 就是我们需要的操作。

Eavg 表示光一次弹射后我们眼睛能接受到的平均能量

算 c 就是算 Eavg,Eavg 的值可以预计算打表。

以上并没有考虑物体颜色,有颜色则意味着能量被吸收。

我们先不考虑颜色带来的损失,先求出补充的 BRDF,然后再算颜色损失了多少

Favg 是 fresnel 的平均,即有多少能量能反射的百分比的平均

Eavg 是某个点接收的能量

多次弹射计算方式如下

最后和之前求出的补充 BRDF 结合

LTC

Linearly Transformed Cosines

解决多边形光源下的 shading

LTC 的思路就是找到一种变换,使得从不同入射方向形成的对不同方向的 lobe 都可以变成一种余弦形式的分布,同时原来的光源也跟着变换也会变成一个新的面积光源。简单地说,我们通过一种变换把任意 BRDF 的 lobe 都变换成了固定的 cos 项,而多边形光源经过相同的变换最终不会影响计算结果,并且这种方法可以得到解析解。

LTC 没法考虑阴影

Disney‘s Principled BRDF

微表面模型很强,但不够真实。尤其是当多层次材质叠加。

创造一个有参数、可以叠加、通俗易懂、效果合理的 BRDF。

NPR

Non-Photorealistic Rendering

为了生成艺术外观,可以不真实

1. 粗线条

首先定义线条

[B]oundary / border edge简写做B

[C]rease,代表折痕,也就是图示两个面的交界处

[M]aterial edge自然就是材质的边界

[S]ilhouette edge表示属于外廓的折痕,也就是图中的CS,它在图像上反应的是不同物体的分界,而在三维空间中反应不同面的交界

Shading 处理

和我们视角方向垂直的法线所属的这些点正好就在我们上面提到的 S 边缘上,设置角度阈值达到描边效果,但因为几何有些地方变化较小,一小片区域都在阈值外,可能会描的很粗。

Geometry 处理

对已经渲染了的模型在它后面渲染一个更大的纯色的黑色的模型,自然就实现了描边的效果

优化:通过法线是可以区分模型的背面和正面的,那么对于背面我们可以对它单独扩大一圈渲染,然后指定为黑色,这样就避免了渲染两个模型

Image 处理

Sobel 锐化来找到边缘

可以利用 shadow map 和 法线来求边缘,更加准确。

2. 色块

阈值化处理

也可以多值化,不同区域有不同的阈值

也可以和描边相组合

3. Strokes Surface Stylization

素描风格的 NPR

用格子的密度来表现明暗的变化。所以我们要想的自然就是如何在渲染的时候把不同点的明暗转变成格子的密度,以及这些格子密度变化的时候做出连续的感觉。于是我们想到了纹理。

事先定义好格子密度不同的纹理,渲染时根据着色点的明暗去不同密度的纹理上去查询就可以了

其次,我们还要考虑,无论物体离我们多远多近,格子的密度都不应该随着距离增改变,而只取决于着色点的明暗。而实际渲染中,由于远处物体 UV 的缩小,远处物体的纹理密度自然会减小,我们是不希望看到的。所以我们会对不同的纹理做一个 Mipmap,而且这个 Mipmap 是不改变纹理的密度的,这样不管离多远我们得到的密度就都相同了