2、BRDF的数学定义:辐射度量学基础
好,咱们正式开始啃BRDF。很多同学一看到数学公式就头大,其实别怕。BRDF的数学定义,说白了就是描述「一束光打过来,有多少光反射到了你眼睛的方向」。我当年刚入行时也觉得这东西太抽象,直到有一次做汽车漆面渲染,怎么调参数都不对,最后回头重新捋了一遍辐射度量学,才发现是基础概念搞混了。
这一节,咱们先把辐射度量学的几个核心物理量讲清楚,然后自然引出BRDF的正式定义。
2.1 辐射度量学四大金刚
辐射度量学是图形学里描述光能量的数学工具。你不需要成为物理学家,但必须搞懂下面这四个量。我习惯把它们叫做「四大金刚」:
| 物理量 | 符号 | 单位 | 一句话理解 |
|---|---|---|---|
| 辐射通量 | Φ | W(瓦特) | 光源每秒发出的总能量 |
| 辐照度 | E | W/m² | 单位面积接收到的能量 |
| 辐射亮度 | L | W/(m²·sr) | 单位面积、单位立体角内的能量 |
| 立体角 | ω | sr(球面度) | 二维角在三维空间的扩展 |
核心记忆点:辐照度E是「到达」表面的光,辐射亮度L是「从表面离开或穿过」的光。BRDF就是连接这两者的桥梁。
2.2 辐射通量(Φ)—— 总能量
辐射通量是最基础的量。它表示光源在单位时间内辐射出的总能量,单位是瓦特(W)。
举个例子:一个100W的灯泡,它的辐射通量就是100W。当然,实际灯泡有一部分能量转化成了热能,但概念上就是这么回事。
在渲染中,我们很少直接操作辐射通量,但它是一切推导的起点。你想想看,没有总能量,后面那些「单位面积」「单位立体角」就无从谈起。
2.3 辐照度(E)—— 单位面积的能量
辐照度描述的是:单位面积上接收到的辐射通量。
公式很简单:
E = dΦ / dA
其中dA是微分面积。单位是W/m²。
这里有个关键点:辐照度只关心「到达」表面的光,不关心光从哪个方向来。它是个标量,把所有方向的光通量累加起来。
我的经验:做PBR材质时,辐照度经常被用来计算漫反射光照。你只需要知道「有多少光打到了这个点」,而不需要知道具体方向——这正是漫反射的特性。
2.4 辐射亮度(L)—— 带方向的能量
辐射亮度比辐照度多了一个维度:方向。它描述的是单位面积、单位立体角内的辐射通量。
公式:
L = d²Φ / (dA · dω · cosθ)
这里多了两个东西:
- dω:微分立体角,表示一个极小的方向锥
- cosθ:表面法线与光线方向的夹角余弦,用于面积投影
为什么要乘cosθ?因为当光线斜着照射表面时,同样的光束覆盖了更大的面积,单位面积接收到的能量自然就少了。这个投影因子在图形学里无处不在。
辐射亮度的单位是W/(m²·sr),其中sr是球面度(立体角的单位)。
注意:辐射亮度是渲染方程中最核心的量。你看到的最终像素颜色,本质上就是辐射亮度的数值映射。我曾经在项目中遇到一个bug,就是因为把辐照度和辐射亮度搞混了,结果整个场景的亮度都不对——排查了整整两天。
2.5 立体角(ω)—— 三维的角度
立体角是二维角在三维空间的推广。一个完整的球面对应的立体角是4π sr。
微分立体角的计算公式:
dω = sinθ dθ dφ
其中θ是极角,φ是方位角。这个公式在半球积分中会反复出现。
你不需要死记硬背,但要知道:立体角是用来描述「方向锥」大小的。在BRDF中,入射方向和出射方向都是用立体角来描述的。
2.6 BRDF的正式定义
好了,有了上面的基础,BRDF的定义就水到渠成了。
BRDF的全称是Bidirectional Reflectance Distribution Function(双向反射分布函数)。它的正式定义是:
f(ωi, ωr) = dLr(ωr) / dEi(ωi)
其中:
- ωi:入射方向(光来的方向)
- ωr:出射方向(观察方向)
- dLr(ωr):出射方向上的微分辐射亮度
- dEi(ωi):入射方向上的微分辐照度
说白了,BRDF就是回答一个问题:从ωi方向来的光,有多少被反射到了ωr方向?
注意,这里用的是微分形式。BRDF描述的是「单位入射辐照度」产生的「出射辐射亮度」。它是一个比值,单位是1/sr。
重要性质:
- 非负性:f(ωi, ωr) ≥ 0(能量不能为负)
- 能量守恒:所有出射方向的积分 ≤ 1(反射的能量不能超过入射的能量)
- 互易性:f(ωi, ωr) = f(ωr, ωi)(交换入射和出射方向,结果不变)
互易性这个性质很有意思。它意味着BRDF在物理上是可逆的:光从A方向打到B方向,和从B方向打到A方向,反射特性是一样的。我在做双向路径追踪时,这个性质帮了大忙——可以复用很多计算结果。
2.7 知识结构图
下面这张图帮你理清辐射度量学和BRDF的关系:
2.8 实战中的注意事项
搞清楚了定义,咱们聊聊实际项目中容易踩的坑:
- 单位混淆:辐照度和辐射亮度单位不同,千万别直接加减。我见过有人把E和L直接相加,结果画面亮得离谱。
- cosθ因子:很多BRDF实现里忘了乘cosθ,导致掠射角(grazing angle)处的能量异常。检查你的渲染方程,看看有没有遗漏这个投影项。
- 立体角积分:做蒙特卡洛积分时,立体角的采样权重一定要算对。我曾经因为立体角公式写错,导致整个半球采样结果偏了30%。
调试技巧:如果你不确定自己的BRDF实现是否正确,可以用一个简单的Lambertian漫反射模型做验证。它的BRDF值是常数 ρ/π(ρ是反射率),如果连这个都算不对,那肯定是辐射度量学的基础出了问题。