微表面模型思想:BRDF 的 D、G、F 项从哪来
「粗糙度」为什么能同时控制高光的粗细和强度?PBR 参数为什么敢叫金属度?答案都在微表面模型里。这篇不写完整实现(下一篇写),只把反射方程和 BRDF 的 D、G、F 三项从物理直觉推到公式形状——每一项都会对应到一行代码。
反射方程:光照的总账
出射辐射 = 对所有入射方向积分:
Lo(x, ωo) = ∫_Ω f_r(x, ωi, ωo) · Li(x, ωi) · (n·ωi) dωi
Li:从方向 ωi 射来的光;f_r:该点把 ωi 的光反射到 ωo 的比例——BRDF。- 实时渲染没法积分整个半球,工程拆法:直接光对每个灯取一个采样点(就是 /notes/unity/lighting-1/ 里
dot(N,L)在做的事);间接光预烘焙进 lightmap/light probe(见 /notes/unity/lighting-4/)或环境贴图 IBL。 - 所以「PBR」在实时里不是更高级的光照算法,而是把 f_r 换成有物理约束的形式,让参数可以按物理标定。
微表面假设
肉眼平滑的表面,微观上是海量微小镜面(microfacet),每个小镜面按自己的法线做完美反射。表面「粗糙」= 小镜面法线方向分散;「光滑」= 法线集中朝向宏观法线 N。
高光为什么存在:只有法线恰好等于 半程向量 H(ωi 与 ωo 的角平分线,见 /notes/unity/lighting-1/)的那批小镜面,能把光反射进眼睛。粗糙度 α 就是小镜面法线的分散程度——这一个假设直接生出 BRDF 三项:
D — Normal Distribution(有多少镜面朝向 H)
D = 法线为 H 的微表面占比密度
常用 GGX/Trowbridge-Reitz:
D_GGX(N·H, α) = α² / π · 1 / ( (N·H)²(α²−1) + 1 )²
直觉:α 小 → D 在 N·H≈1 处极尖(锐利高光);α 大 → D 摊开(宽而柔的高光)。高光「粗细」全部由 D 决定——这就是粗糙度滑条的物理含义。GGX 的长尾比老式 Blinn 指数更重,所以 PBR 材质边缘有一圈淡淡的掠射反光,观感比 Blinn 更「真」。
G — Geometry/Masking(镜面互相遮挡)
小镜面不是都露着的:凹凸之间会互相挡光、挡视线。α 越大遮挡越严重,高光在掠射角额外衰减。工程用 Smith 分解 G = G_L · G_V,直接光常用 Schlick-GGX 近似(k 由 α 导出):
G_Schlick(n·v, k) = (n·v) / ( (n·v)(1−k) + k ), k = α/2(直接光)
G 项肉眼效果:粗糙材质在边缘处高光明显变暗,Blinn-Phong 没有这个衰减。
F — Fresnel(掠射角反射更强)
F_Schlick(uv, F0) = F0 + (1 − F0)(1 − u·v)⁵
视线越贴近表面(掠射),反射比例越高——湖面远处比脚下更反光。F0 是正视反射率:电介质(塑料、水、木头)约 0.04,金属接近 1 且带颜色。F 项是「边缘高光」的物理来源,风格化写法见 /notes/unity/effects-2/。
组装:Cook-Torrance 的形状
f_r = D·G·F / ( 4 (N·L)(N·V) )
分母是微表面模型坐标变换的几何修正(把「微法线分布」换算回宏观立体角)。下一篇 /notes/unity/lighting-3/ 把这三项写成可跑的代码,并补上最后一块拼图:能量守恒与金属度。
与 Blinn-Phong 的对应关系
| Blinn-Phong | 微表面 |
|---|---|
pow(N·H, shininess) | D 项(指数分布 ≈ GGX 的近似) |
| 无 | G 项 |
| 常数高光色 | F 项(Blinn 把 F 当常数,所以金属调不对) |
| 高光色与漫反射色独立调,能量不守恒 | F 反射多少,漫反射就少多少 |
Blinn-Phong 不是「错」,是只实现了 D 的近似、砍掉了 G 和 F 的简化版——所以它调不出金属,也调不出「粗糙度」这一个统一参数。
自检三问
- 粗糙度滑条在公式里控制哪一项?肉眼效果是什么?
- 为什么 Blinn-Phong 材质在掠射角看起来「塑料」?
- 反射方程的直接光/间接光,在实时管线里各由什么机制承担?