关于Disney PBR的理解(1)
关于Disney PBR的理解
1 普通光照
光照和阴影决定了渲染出来的模型的着色表现。在光栅化的渲染管线中,顶点着色器组装图元传递到片段着色器中对图元覆盖的像素计算颜色,这个计算颜色的过程也就是光照方程具体应用阶段。从很久之前人类就开始对散射、透射、反射等物理现象进行建模,期待通过有限的参数描述具体的物理变化过程。Phong式光照模型因为其结构简单、计算方便、效果显著,所以代表了早期普通光照模型。其包含了三个部分,分别是环境光项、漫反射项、高光项。光源通常分为直接光和间接光,直接光是模型对光源光照的反射,间接光是模型对其他模型光照的反射。在Phong模型中,间接光被简单的环境光项表示。根据Lambert定律,理想的漫反射表面的反射光强度与表面法线和入射光反向夹角的余弦成正比,建模得到Phong光照的漫反射项:
而Phong光照的高光项为经验观察得来,反射光强度和反射光的方向与视线的夹角的余弦成正比:
根据反射定律,入射光 \(\vec{L}\) 关于法线 \(\vec{N}\) 的反射方向:
2 Disney PBR直接光照
光照更一般意义上的物理过程可以描述为:模型表面接收某个方向的一束光线,然后根据某种规则吸收一部分能量,最后将剩余的能量反射出去。直接光照只需要考虑有限个数的光源,而间接光照需要在半球空间上对所有光源做积分。首先定义直接光照光源\(L_i\),我们知道大概有点光、方向光、聚光、面光等几种不同类型的光源,它们具有位置、强度、颜色中的部分物理参数。因此要在方程中完整描述光源入射光线的强度,需要综合考虑模型表面点\(P\)和入射方向\(w_i\),定义\(Li(P,w_i)\)的物理意义为到达模型表面点\(P\)沿着方向\(w_i\)入射的辐射亮度,单位为瓦特(\(W\))。
光源的入射光并不能完全被点\(P\)接收到,需要根据模型表面的几何信息也就是法线\(n\)计算接收率,得到\(Li(P,w_i)max(0,n·w_i)\)即最终点p接收到单个直接光源的辐射亮度。
前面说到模型表面点\(P\)接收光线后,会根据某种规则将光线反射出去,这种规则描述了如何计算反射率,如何得到反射分布(光线会往哪些方向反射,又会反射多少)。可以分析到模型表面点\(P\)自身的物理属性比如粗糙度、法线、颜色等会影响反射率的计算,另外反射率也应该和入射方向\(w_i\)有关系,最后反射率会受到观察方向\(w_o\)的影响,因为一束光被模型吸收后会出现散射,光子在模型表面其他位置朝着任意方向出射,能量是一个分布,我们只关注出射后被相机接收到的光线能量。因此得到反射率函数\(fr(p,w_i,w_o)\),称为双向反射分布函数BRDF(Bidirection Reflection Distribution Function),“双向”的意思是根据互易性,交互光源和视点的位置BRDF计算结果不变。
将所有的光源都计算一遍就会得到视点看到的点\(P\)的辐射亮度,总结为下面的渲染方程:
Disney Principled BRDF革命性的地方在于,它将大量复杂而不直观的参数替换为了直观的少量参数,渲染的结果更偏向于艺术导向而不是物理正确。它实际上是一种分层混合模型,如下图所示:

从上图可以发现,分为金属层、非金属层、清漆层,然后非金属层又分为基础层和sheen层,基础层又分为次表面散射层和漫反射层。根据能量守恒原理,能量不会凭空产生或消失,Disney brdf函数反映了点\(P\)的反射分布,在半球上积分后反射的所有能量必须小于或等于入射能量。这些层通过混合系数最终组合在一起,符合能量守恒原则,并且每一项都基于微平面理论构建。
(1)清漆层(Clearcoat Layer)
清漆层本质上是一个处于最顶层的微表面层。在理想情况下,如果清漆层完全覆盖(clearcoat = 1),它理应屏蔽掉下方材质的大部分细节(像打了一层蜡)。但为了艺术上的可控性,我们不希望清漆层完全覆盖掉底部材质的颜色或纹理。这个 0.25 是为了让 GTR1 分布函数在高光叠加时,亮度能与底层的 Specular 层及 Diffuse 层达成视觉均衡,同时作为一个“软限制”防止由于简单加法导致的能量爆炸。
clearcoat 的存在是为了解决单一微表面模型无法模拟复杂分层材质的问题。它让一个物体同时具备“自身粗糙的质感”(由底层的 Roughness 决定)和“外部平滑的镜面反光”(由 Clearcoat 决定)。clearcoat 是一个 [0, 1] 的权重值, = 0 时,这层贡献消失,完全遵循底层材质表现, = 1 时,表面被清漆完全覆盖。
\(Gr\)为几何函数。微平面理论认为物体表面是由一个个微小的绝对光滑平面组成的,粗糙度越高,各个平面的方向越乱,粗糙度越低,各个平面的方向越统一。当模型表面足够粗糙时,一方面会影响光线接收率产生几何阴影,另一方面也会影响光线反射率产生几何遮蔽。所以最后使用相同的几何函数,和不同的视线和光线方向输入。
float Gr = smithG_GGX(NdotL, .25) * smithG_GGX(NdotV, .25);
float smithG_GGX(float NdotV, float alphaG)
{
float a = alphaG*alphaG;
float b = NdotV*NdotV;
return 1 / (NdotV + sqrt(a + b - a*b));
}
其中\(alphaG\)为粗糙度的平方,取 0.25 目的是强制给清漆层设定一个“标准平滑度”的几何基础。它给\(G\) 函数提供了一个非常平稳的遮蔽曲线。它既不会让高光在掠射角消失得太快(导致漆面看起来像干瘪的纸),也不会让它在掠射角处过亮(导致清漆看起来像金属)。这使得渲染出来的清漆层无论在什么角度下,都表现出符合物理直觉的“漆面”质感,而不需要让艺术家再去担心清漆层表面的几何遮蔽细节。
\(Fr\)为菲涅尔反射函数。菲涅尔效应描述了一个现象:物体在不同观察角度下,反射能力是不同的。垂直观察时(正常入射):光线更多地进入物体内部,反射较弱。此时反射率为 \(F_0\)。掠射角观察时(接近平行):光线几乎在表面“擦过”,无法进入内部。此时几乎所有的光线都会发生反射,反射率趋近于 100%。
float Fr = mix(.04, 1.0, FH);
float FH = SchlickFresnel(LdotH);
float SchlickFresnel(float u)
{
float m = clamp(1-u, 0, 1);
float m2 = m*m;
return m2*m2*m; // pow(m,5)
}
由上面的代码可以发现,实时渲染几乎总是使用 Schlick 近似公式计算菲涅尔系数,因为它计算极其高效,且误差极小。其中基础反射率\(F_0\)指光线垂直入射时的反射比例。清漆层(作为一种典型的电介质/塑料材料)的 \(F_0\)为0.04,所以,清漆层在正对观察者时反射 4% 的光,在掠射角处反射 100% 的光。
\(Dr\)为法线分布函数的一种。粗糙度越高,微平面的法线朝向越乱,统计了有多少比例的微小平面朝向“中间方向 \(H\)”(即反射光线的半程向量)。如果所有的微平面法线都一致,那么反射光就是镜面反射(像镜子);如果法线方向极其混乱,反射光就会四散开来(像磨砂表面)。
float Dr = GTR1(NdotH, mix(.1,.001,clearcoatGloss));
float GTR1(float NdotH, float a)
{
if (a >= 1) return 1/PI;
float a2 = a*a;
float t = 1 + (a2-1)*NdotH*NdotH;
return (a2-1) / (PI*log(a2)*t);
}
\(clearcoatGloss\)清漆光泽度用于调节清漆层(Clearcoat Layer)高光锐利程度。值越接近 1(最光滑):清漆层表面极度平整,类似于刚抛光过的玻璃或极薄的油膜。此时高光点极其锐利、聚焦,倒影非常清晰。值越接近 0(较粗糙):清漆层表面存在微小的起伏或磨损,虽然它依然保持清漆的质感,但高光会变得扩散、朦胧,倒影变得模糊,不再有“如镜子般”的锐利感。
清漆层用 GTR1 而不是 GTR2 ,一方面GTR1 相比于 GTR2,在中心高光部分表现得更加集中(更亮),但在周围有更显著的“尾部(Tail)”。这完美模拟了清漆层那种表面光滑但底层有轻微起伏的物理质感。另一方面使用 GTR1 渲染出的清漆层,其高光核心极其锐利,但在边缘又会有平滑的过渡,这比 GGX 看起来更像是一层覆盖在物体上的“亮膜”。

(2)金属层(Metal Layer)
金属层只处理高光,并且反射带有金属自身的颜色。
\(Gs\) 类似于\(Gr\) 为几何函数。金属层的几何函数特殊在于它考虑了各向异性,粗糙度不再是一个标量,而是一个二元组 \((ax, ay)\),当光线顺着拉丝方向入射时,它遇到的遮蔽程度会比顺着纹理垂直方向入射时更小(看起来更亮)。
float aspect = sqrt(1-anisotropic*.9);
float ax = max(.001, sqr(roughness)/aspect);
float ay = max(.001, sqr(roughness)*aspect);
Gs = smithG_GGX_aniso(NdotL, dot(L, X), dot(L, Y), ax, ay);
Gs *= smithG_GGX_aniso(NdotV, dot(V, X), dot(V, Y), ax, ay);
float smithG_GGX_aniso(float NdotV, float VdotX, float VdotY, float ax, float ay)
{
return 1 / (NdotV + sqrt( sqr(VdotX*ax) + sqr(VdotY*ay) + sqr(NdotV) ));
}
\(Fs\) 类似于\(Fr\) 为菲涅尔反射函数,代表了微表面法线与光线半程向量夹角处的反射比率。
float FH = SchlickFresnel(LdotH);
vec3 Fs = mix(Cspec0, vec3(1), FH);
垂直入射时 (\(FH = 0\)): \(Fs\) 等于 Cspec0。
掠射角时 (\(FH = 1\)): \(Fs\) 强制变为 白色。无论材质是什么(金属、塑料、木头),在光线几乎平行于表面掠过时,所有材质都会倾向于成为理想镜面(反射率趋近 100%),且反射光为光源色。
\(Cspec0\) 为基础反射率 \(F_0\)。
vec3 Cspec0 = mix(specular*.08*mix(vec3(1), Ctint, specularTint), Cdlin, metallic);
非金属 (metallic = 0): \(F_0\) 被设定为 specular * 0.08。通常 specular 默认为 0.5,则 \(F_0 \approx 0.04\)(即 4%),这是塑料、玻璃等绝缘体的标准折射率反射率。通过 specularTint,我们可以微调非金属高光的颜色。
金属 (metallic = 1): \(F_0\) 直接等于 Cdlin(即 baseColor)。这就是金属反射颜色的物理来源,金属的镜面反射直接表现为金属的固有色。
\(Cdlin\)(Color-Diffuse-Linear)是经过线性化处理后的漫反射颜色值。它代表了物体表面在物理世界中对可见光各个波段的反射率(Albedo)。baseColor 通常以 sRGB 空间(监视器色彩空间)存储,而渲染计算必须在线性空间(Linear Space)中进行。因此需要调用mon2lin将基础色转换到线性空间。
\(Ds\)类似于\(Dr\)为法线分布函数的一种。金属层的法线分布函数同样考虑了各向异性,将粗糙度拆分为\(X\) 切线方向(通常是纹理的拉丝方向)和\(Y\) 副切线方向。最终使用的GTR2分布函数如下图所示。
float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay);
float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
{
return 1 / (PI * ax*ay * sqr( sqr(HdotX/ax) + sqr(HdotY/ay) + NdotH*NdotH ));
}

(3)非金属层(Dielectric Layer)
((1/PI) * mix(Fd, ss, subsurface)*Cdlin + Fsheen)* (1-metallic)
非金属层通过金属度 metallic系数计算对整体反射率贡献比例,分为基础层和sheen层。
a. 基础层
基础层又分为次表面散射层和漫反射层,它们通过subsurface 参数在完全不透明材质和半透明散射材质之间进行精细控制。subsurface = 0:物体完全表现为标准的漫反射(Fd)。光线被视为立即在表面发生反射。subsurface = 1:物体表现为完全的次表面散射(ss)。材质会显得更加通透,光照下的“暗部”和“亮部”边缘会变得非常模糊和柔和。
在 Disney BRDF 中,漫反射层不再是简单的 Lambertian(兰伯特漫反射),而是一个考虑了掠射角增强效应的漫反射模型。
float FL = SchlickFresnel(NdotL), FV = SchlickFresnel(NdotV);
float Fd90 = 0.5 + 2 * LdotH*LdotH * roughness;
float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
float SchlickFresnel(float u)
{
float m = clamp(1-u, 0, 1);
float m2 = m*m;
return m2*m2*m; // pow(m,5)
}
它由三部分组成:兰伯特漫反射、掠射角衰减因子、双向菲涅尔补偿项。掠射角衰减因子 (Fd90)模拟粗糙度带来的“后向反射” (Retro-reflection),粗糙表面(如织物、磨砂金属)的微观结构类似于无数微小的空洞或凸起。当光线从很小的夹角入射时,这些微结构会产生复杂的多次散射,使得反射光不只是向外扩散,还会出现“后向反射”(即光线倾向于沿入射路径反射回一部分)。双向菲涅尔补偿项 (mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV)),解决“边缘镂空”问题,传统的 Lambertian 模型在掠射角(接近 90 度)时,漫反射数值会迅速趋近于 0。这在视觉上会导致物体边缘看起来像被“切掉”了一样。引入双向菲涅尔补偿项,使得材质边缘依然保留一定比例的漫反射能量,模拟了粗糙微表面在边缘处的漫反射叠加。
Disney BRDF的次表面散射 (Subsurface Scattering, SSS) 层是 Hanrahan-Krueger (HK) 模型的简化近似,用于模拟光线在半透明介质内部的长距离散射。
float Fss90 = LdotH*LdotH*roughness;
float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
float ss = 1.25 * (Fss * (1 / (NdotL + NdotV) - .5) + .5);
其中,Fss90为次表面散射的掠射角系数,它定义了当视角或光照方向达到掠射角(90度)时,次表面散射效果应该呈现出多大的强度。Fss为次表面散射的菲涅尔总权重,它决定了次表面散射在整个材质表面的分布范围。通过乘积,它确保了散射效果在光照和观察方向上都遵循物理对称性。
几何因子 (1 / (NdotL + NdotV) - 0.5)是 HK 模型对半球空间内散射光分布的近似,通过几何归一化处理了光线出射的概率。
b. Sheen层
Disney BRDF的Sheen层引入了一个非常独特的视觉层面,用于模拟细微表面纤维对光线的散射。
float Cdlum = .3*Cdlin[0] + .6*Cdlin[1] + .1*Cdlin[2]; // luminance approx.
vec3 Ctint = Cdlum > 0 ? Cdlin/Cdlum : vec3(1); // normalize lum. to isolate hue+sat
vec3 Csheen = mix(vec3(1), Ctint, sheenTint);
vec3 Fsheen = FH * sheen * Csheen;
Cdlum用于亮度提取 (Luminance Approximation),将一个三维的颜色向量(RGB)压缩成一个标量(灰度值)。Ctint 代表了材质的颜色倾向,比如一个深红色,Cdlum 记录了它很暗,Ctint 记录了它是红色的。在 Disney 模型中,非金属材质的高光通常是白色的,但有些材质(如某些塑料或油漆)的高光会带有一点点材质本身的颜色。Ctint 的加入使得 Fsheen 可以带上材质的基色(例如深红色的天鹅绒在边缘会呈现出亮红色的光泽),这极大地增强了材质的色彩丰富度。
(4)Disney BRDF 参数总结
| 参数 | 物理意义 |
|---|---|
| baseColor | 漫反射/金属反射颜色 |
| metallic | 金属程度 |
| roughness | 微表面粗糙程度 |
| specular | 电介质F0强度 |
| specularTint | 高光颜色偏移 |
| anisotropic | 各向异性 |
| sheen | 布料边缘光 |
| clearcoat | 透明漆强度 |
| clearcoatGloss | 透明漆粗糙度 |
| subsurface | 次表面散射 |
| subsurfaceRadius | 散射距离 |

浙公网安备 33010602011771号