2、光照基础理论:辐射度量学、BRDF、光照模型(Lambert、Blinn-Phong)
好,我们正式开始聊光照。说实话,很多刚入行的朋友一听到「辐射度量学」这几个字就头大,觉得这是搞物理的人该干的事。我当年也一样,心想我写个Shader要懂这些干嘛?直到我在项目中第一次被一个「看起来对但渲染出来就是假」的光照问题折磨了三天……嗯,从那以后我老老实实把基础补上了。
这一章,我们就从最底层的物理量开始,一步步搭建起光照的数学框架。你想想看,如果你连「光到底有多少能量」都说不清楚,那后面那些花里胡哨的渲染效果,说白了就是空中楼阁。
2.1 辐射度量学:给光一个「度量衡」
辐射度量学,说白了就是一套用来量化「光」的物理单位体系。在实时渲染里,我们最常打交道的四个量是:辐射通量、辐射强度、辐照度、辐射亮度。
我个人习惯把它们类比成「水龙头放水」的场景,这样好记:
| 物理量 | 符号 | 单位 | 水龙头类比 |
|---|---|---|---|
| 辐射通量 (Radiant Flux) | Φ | W (瓦特) | 水龙头每秒流出的总水量 |
| 辐射强度 (Radiant Intensity) | I | W/sr | 水柱朝某个方向喷出的「集中度」 |
| 辐照度 (Irradiance) | E | W/m² | 地面每平方米接到的水量 |
| 辐射亮度 (Radiance) | L | W/(m²·sr) | 你眼睛看到的「那片水幕的亮度」 |
核心要点:在渲染方程中,我们最终计算的是 Radiance (L)。因为只有它同时描述了「位置」和「方向」,正好对应像素的颜色值。
这里有个坑,我刚开始学的时候经常搞混辐照度和辐射亮度。你记住一句话:辐照度是「到达」表面的光,辐射亮度是「离开」表面的光。渲染的本质,就是计算从表面某个点、朝某个方向「离开」的辐射亮度。
2.2 BRDF:表面的「反射性格」
好,现在我们知道了光怎么度量。但光打到物体表面后,会发生什么?这就引出了渲染中最重要的一个概念——双向反射分布函数 (BRDF)。
BRDF 描述的是:给定一个入射方向 ωᵢ,表面朝某个出射方向 ωₒ 反射了多少光。数学上它定义为:
f(ωᵢ → ωₒ) = dLₒ(ωₒ) / dE(ωᵢ)
说白了,就是「出射的辐射亮度」除以「入射的辐照度」。这个比值越大,说明表面在这个方向上反射得越亮。
BRDF 有两个非常重要的物理性质,我建议你刻在脑子里:
- Helmholtz 互易性:交换入射和出射方向,BRDF 值不变。也就是说 f(ωᵢ→ωₒ) = f(ωₒ→ωᵢ)。
- 能量守恒:表面反射的能量不能超过入射的能量。所有出射方向的积分必须 ≤ 1。
注意:我曾经在项目中写了一个自定义 BRDF,结果渲染出来的金属球比太阳还亮。排查了半天,发现是能量守恒没处理好。记住,物理正确的 BRDF 必须满足这两个条件,否则你的渲染结果就是「物理错误」的。
2.3 经典光照模型:从 Lambert 到 Blinn-Phong
理论讲完了,我们来看看实际干活时用的东西。虽然现在 PBR 是主流,但 Lambert 和 Blinn-Phong 这两个模型依然是理解光照的基石。我建议你先把它们吃透。
2.3.1 Lambert 漫反射模型
Lambert 模型描述的是理想漫反射表面。它的核心思想很简单:表面朝各个方向均匀反射光。你想想看,一张白纸、一面粗糙的墙壁,从哪个角度看亮度都差不多,这就是 Lambert 行为。
数学表达式:
Lₒ = (c / π) * Lᵢ * max(0, n · l)
其中:
- c 是表面颜色(反照率)
- Lᵢ 是入射光的辐射亮度
- n · l 是表面法线与光线方向的点积,控制光照角度
- 除以 π 是为了满足能量守恒
个人经验:很多初学者会问「为什么除以 π?」。我告诉你,这是为了确保 BRDF 的半球积分等于 1(即能量守恒)。你不需要每次都手动算这个,但心里要清楚:没有这个 π,你的漫反射就会「过亮」。
2.3.2 Blinn-Phong 高光模型
Lambert 只能处理漫反射,但现实中的物体还有高光(镜面反射)。Blinn-Phong 模型就是用来模拟这个的。
它引入了一个关键概念——半程向量 h:
h = normalize(l + v)
然后高光项的计算为:
spec = (n · h)^s
其中 s 是光泽度(Shininess),值越大,高光越集中、越亮。
完整的 Blinn-Phong 光照模型:
Lₒ = (c / π) * Lᵢ * max(0, n · l)
+ Lᵢ * k_s * max(0, n · h)^s
前半部分是漫反射,后半部分是高光。k_s 是高光强度系数。
为什么用半程向量? 原始的 Phong 模型用的是反射向量 r 和视线 v 的夹角,计算量更大。Blinn 改用半程向量 h 和法线 n 的夹角,效果几乎一样但效率更高。我在移动端项目里就喜欢用 Blinn-Phong,省性能。
2.4 从经典到 PBR:一个自然的过渡
你可能会问:既然有了 Blinn-Phong,为什么还要搞 PBR?
原因很简单:Blinn-Phong 是「经验模型」,不是「物理模型」。它虽然好看,但无法准确模拟真实世界的材质。比如:
- 它没有考虑菲涅尔效应(Fresnel Effect)—— 掠射角时反射更强
- 它的高光项不满足能量守恒
- 它无法区分金属和非金属
我在做汽车渲染项目时,用 Blinn-Phong 调车漆,怎么调都像塑料。后来换成基于微表面理论的 Cook-Torrance BRDF,才真正做出那种「金属漆的质感」。这就是经验模型和物理模型的差距。
不过别急,PBR 我们后面有专门章节讲。你现在先把 Lambert 和 Blinn-Phong 吃透,它们是理解 PBR 的「前菜」。
2.5 本章小结
这一章我们干了三件事:
- 搞清楚了辐射度量学的四个基本量,尤其是 Radiance 和 Irradiance 的区别
- 理解了 BRDF 的定义和两个核心性质(互易性、能量守恒)
- 手把手推导了 Lambert 漫反射和 Blinn-Phong 高光模型
说实话,这些基础理论看起来枯燥,但它们是整个渲染大厦的地基。我见过太多人跳过这一步直接去调 PBR 参数,结果遇到问题完全不知道从哪下手。你既然选择了这门课,就踏踏实实把这一步走稳。
下一章,我们会把这些理论落地到 Unreal Engine 中,看看引擎内部是怎么实现这些光照模型的。到时候你会发现,理解了这些基础,看引擎源码就像看老朋友一样亲切。
课后练习建议:打开 Unreal,创建一个纯色材质,用 Custom 节点手写一个 Lambert 光照模型。别用引擎自带的节点,自己算 n·l,自己乘颜色。相信我,亲手写一遍比看十遍都管用。