# 光打到表面之后：金属、塑料、玻璃为什么长得完全不一样

从菲涅耳反射率讲起，看清漫反射与镜面反射的分工、metallic 和 roughness 各自控制什么，以及粗糙反射为什么是实时渲染里最难算清的一段

> 渲染原理 · 实时光线追踪 · PBR 材质 · 微表面模型 · 约 7 分钟 · 10 月 17 日

## 本篇要点

1. 光线碰到表面只有两个出口：被弹回去，或进入材料；两者比例由菲涅耳反射率决定，垂直看塑料、玻璃约反射 4%，水约 2%，金属几乎全部反射。
2. 进入材料的光在内部散射后被颜料染色再射出，方向随机，所以从各个角度看亮度一样，这就是漫反射；颜色的深浅取决于哪种波长的光被吸收得多。
3. 没进材料、直接从表面弹回去的那部分不带材料的颜色，走严格反射方向，呈出的是环境的像——这就是为什么红塑料上的高光可以是白的。
4. 现实表面微观上是大量朝向杂乱的小平面，粗糙度描述这些朝向散得多开：越光滑反射越清晰、高光越小越亮，越粗糙反射越糊、高光越大越暗。
5. 渲染器实际要算的是一个像素在以理想反射方向为中心的锥内所有入射光的平均值，锥宽由粗糙度决定；游戏滑杆常见 $\alpha = \text{perceptualRoughness}^2$ 的映射，所以粗糙度值越小，拨动带来的变化越剧烈。
6. 非金属 = 有颜色的漫反射 + 无色的弱镜面反射；金属 = 没有漫反射 + 带颜色的强镜面反射，金属的镜面颜色就是它自己的颜色（金约 (1.00, 0.85, 0.57)，银约 (0.97, 0.96, 0.91)）。
7. metallic 因此不是亮度滑块而是开关：它决定 baseColor 被当作漫反射颜色还是镜面反射颜色，中间值在物理上只对应锈迹一类过渡。
8. 菲涅耳随角度变化，掠射时反射率趋近 100%，这解释了湿路面顺看反光、玻璃杯斜看能照出人影；玻璃就是典型的非金属，垂直入射 4% 反射、96% 透射折射，有色玻璃的颜色来自光在体内被吸收。
9. 粗糙反射难算在于：锥宽使一条光线只是一个高方差样本；相邻像素光线散开、丢失局部性；粗糙端的可见法线采样会有一半方向落在表面背面被丢弃；单次散射还会让粗糙表面丢失能量而变暗。
10. 最难的是中间那段半光滑反射：糊不掉又必须发够光线，所以引擎常按粗糙度阈值把光滑端交给光追、粗糙端交给探针，甚至用第二层反射叠加来同时呈现清晰与粗糙两种成分。

---

上一篇讲的是光追画面上的颗粒从哪来、降噪器怎么补。但降噪要补的那个“正确值”到底是什么？对颜色的判断，最终都要落回同一件事：光线碰到表面之后去了哪里。

这一篇回答三个连着的问题：为什么同一束光打在金属、塑料、玻璃上会变成三种不同的东西；游戏里的 roughness 和 metallic 各自在控制什么；以及为什么“有点粗糙的反射”是实时渲染里最难算清的。

## 一个表面只有两个出口

光线碰到表面，可能发生的事只有两件：被弹回去，或者进入材料内部。哪个发生、各占多少，由界面决定，这个比例叫菲涅耳反射率。

垂直看过去，塑料、玻璃这类非金属只反射百分之四左右（水约 2%，宝石可以到 16%），其余九成多进了材料；金属则相反，光几乎进不去，大部分从表面弹回来，没弹回来的被吸收掉。“光进不去”是理解金属的钥匙，它后面所有特殊表现都从这句推出来 [1]。

## 进去的那部分：漫反射

进入非金属的光在材料内部来回散射，一路被颜料吸收掉一部分，最后从表面某个随机方向钻出来。方向既然是随机的，你从正面看、从侧面看亮度都一样——这就是漫反射，哑光的来源。颜色也来自这里：哪种颜色的光被吸收得多，物体就显出剩下的颜色。

有个容易被忽略的结果：漫反射的颜色来自材料内部，而镜面反射那部分光没进过材料，所以不带材料的颜色。红塑料球上的白色高光就是这么来的——高光可以是白的，球本身是红的。

## 弹回去的那部分：镜面反射

弹回去的光走一条严格的路径，入射角等于反射角，方向完全由表面法线说了算。所以镜面反射给你的不是“材料的样子”，而是环境的像：看到的是它对面那面墙、那片天。

现实中不存在数学意义上完美的平面。把表面放大到微观，是一大片朝向各不相同的小平面。粗糙度描述的就是这些朝向散得多开：接近 0 时小平面几乎同向，等于一面镜子，高光又小又亮、反射清晰；粗糙度变大，朝向散开，每个方向都反射一点，高光摊开变暗，反射糊成一片；接近 1 时，反射已经糊得和漫反射差不多。

在渲染器眼里，这个“糊”有确切含义：一个像素的镜面反射要的，是以理想反射方向为中心、一个锥形范围内所有方向入射光的平均值，锥有多宽由粗糙度决定 [3]。这句话是理解后半部分全部代价的钥匙。

顺带一个实用细节：游戏里的 roughness 滑杆和锥的实际宽度通常不是线性关系，常见做法是先把数值平方（$\alpha = \text{perceptualRoughness}^2$）再拿去算锥宽 [2]。所以滑杆从 0.1 拨到 0.2，画面变化远比从 0.8 拨到 0.9 剧烈——“0.2 还像镜子、0.3 就明显糊了”是正常现象。

## metallic 这根滑杆在切什么

把两类材料并排看：非金属（塑料、木头、皮肤、玻璃、水）有被材料染色的漫反射，外加一层很弱、无色的镜面反射（4% 上下）；金属（金、银、铜、铝）没有漫反射——光进不去，没有内部散射来染色——而镜面反射很强，并且这个镜面反射本身带颜色。

金属的镜面颜色就是金属自己的颜色。金在垂直入射时的反射率大约是 $(1.00,\ 0.85,\ 0.57)$：红光几乎全被弹回，蓝光被吃掉大半，所以金是黄的。银是 $(0.97,\ 0.96,\ 0.91)$，三色几乎全弹回，所以银看起来是白的——“银色”其实是接近无色的高反射，不是某种颜料 [1]。

所以 metallic 不是“亮不亮”的滑块，而是个开关：它决定 baseColor 这张贴图该被读成“漫反射的颜色”还是“镜面反射的颜色”。设成 0.5 在物理上并不存在，只用来表示锈迹这类过渡 [2]。

![metallic 从 0 变到 1，同一张贴图被读成漫反射颜色或镜面反射颜色，观感截然不同](https://google.github.io/filament/images/materials/metallic.png)

## 掠射角：为什么所有东西在边缘都变反光

菲涅耳反射率还随角度剧烈变化。垂直看塑料只有 4% 被反射，越接近擦着表面看，反射率越趋近 100%：

$$F = F_0 + (1 - F_0)(1 - \cos\theta)^5$$

$F_0$ 是垂直入射时的值，$F$ 是当前角度下的反射率 [1]。这一条解释了：下过雨的柏油路顺着路面看出去能拖出长长一条反光，低头看却是黑的；玻璃杯正面看几乎透明，斜着看却能映出整间屋子。

玻璃放进这套框架里很朴素：它就是典型的非金属，垂直入射 4% 反射、96% 透射并折射进去；因为玻璃通常很光滑，那 4% 反射是清晰的像而不是一团高光。有颜色的玻璃，是进去的光在体内走了一段路、被吸收掉一部分的结果。折射、吸收、色散留给下一篇。

![显微镜下的表面：平整界面只把一个方向的入射光弹回去，杂乱的小平面把光散到一大片方向上](https://google.github.io/filament/images/diagram_microfacet.png)

## 粗糙的反射为什么最难算

回到那个锥。

**完美镜面反而最便宜。** roughness 为 0 时反射方向只有一个，一条光线就给出精确答案，方差为零。它的麻烦在别处——清晰度要够、光线要连贯，但“算准”这件事不费劲。

**粗糙表面相反：一条光线只是一个随机样本。** 你要的是锥内的平均值，随机抽一条光线只是这个平均的一个样本；锥越宽，样本彼此差别越大，估计越不可靠。按上一篇的结论，误差大致按 $1/\sqrt{N}$ 下降，实时预算下这点采样远远不够，缺口只能交给降噪器去猜 [6]。

**光线会散开。** 相邻像素各自在锥里随机取样，落点散得很开，同一束光线打到哪里毫无规律，硬件求交和缓存都失去局部性。AMD 一篇做实时光泽反射的文章说得很直白：表面越粗糙，光线越发散，整体性能越差 [4]。

**采样算法在粗糙端也变钝。** 通用的做法是按可见法线采样：先抽一个微平面朝向，再按它算反射方向。当粗糙度拉到 1 且正对观察时，这套采样吐出的反射方向会均匀铺满整个球面，其中一半落在表面背面、只能丢弃——比“在上半球均匀乱扔”还浪费一倍 [5]。

**还有能量的账。** 只让光线在小平面之间弹一次，粗糙度越高，被相邻小平面挡住、因而丢失的能量越多，表面越粗糙越暗。这在金属上尤其明显（金属全靠镜面反射），粗糙金属会暗到像深色塑料；要补回来，就得把微表面之间的多次弹射也算进去 [1]。

所以真正难的不是两端，而是中间。太光滑的一端，一条光线就是答案；太粗糙的一端，反射已经接近漫反射，可以交给低分辨率的探针或光照缓存去糊——很多实时方案确实按一个粗糙度阈值把两边分开处理 [4]。夹在中间的“半光滑”最难：既糊不掉（一糊就丢掉反射里那个物体的轮廓，一眼假），又必须发够光线才不吵。材质作者多半都撞过这堵墙：车漆、清漆、抛光瓷砖这类表面，一个锥描述不完，所以引擎干脆允许叠第二层反射——一层很光的镜面加一层粗糙的底，各管一段 [2]。

## 从画面反推参数

- 金属看起来像深色塑料：可能缺了菲涅耳，也可能粗糙度太高、单次散射把能量丢光了。
- 物体边缘没有变亮：菲涅耳缺失，模型还停留在老式的“高光强度”。
- 反射里该有的东西不见了，或者糊得离谱：反射档位过低，光追反射被换成了探针。

## 术语表

- 漫反射（diffuse）：光进入材料内部反复散射、被颜料吸收一部分后，从随机方向射回表面，因此各角度看亮度一致，呈现哑光与材料本身的颜色。
- 镜面反射（specular）：光在表面直接弹回，入射角等于反射角，方向由表面法线决定，呈出的是环境的像。
- 菲涅耳反射率与 F0：决定入射光里多少被反射、多少进入材料；$F_0$ 是垂直入射时的反射率（塑料、玻璃约 4%，金属由自身颜色决定），角度越接近掠射反射率越高。
- 介电体与导体（非金属与金属）：非金属有漫反射、镜面反射无色且弱；金属没有漫反射、镜面反射强且被自身颜色染色。metallic 参数就是在这两种读法之间切换。
- 微表面与粗糙度：把表面看作大量朝向随机的小平面，粗糙度描述朝向的分散程度，决定反射锥的宽窄——锥越宽，反射越糊、高光越大越暗。
- 锥内平均：一个像素的镜面反射要的是锥形范围内所有方向入射光的平均值；锥越宽，单条光线作为该平均的样本就越不可靠（方差越大）。
- 可见法线采样（VNDF）：通用的粗糙表面采样方式，先抽一个可见的微平面朝向再算反射方向；在极高粗糙度下会产生大量被表面挡住、只能丢弃的方向，采样效率下降。
- 多散射能量补偿：只算一次小平面间弹射会让粗糙表面因相互遮挡而丢失能量、显得偏暗，补上多次弹射才能恢复亮度。

## 来源

1. [Filament: Physically Based Rendering — 微表面模型、菲涅耳与 F0、金属反射率数值表、单次散射能量损失与多散射补偿](https://google.github.io/filament/Filament.html)
2. [Filament: Materials — metallic 为二值开关、非金属反射率表、α = perceptualRoughness² 重映射、第二层镜面反射](https://google.github.io/filament/main/materials.html)
3. [Physically Based Rendering (4th ed.): Roughness Using Microfacet Theory — 微表面理论、反射分类、按可见法线采样](https://www.pbr-book.org/4ed/Reflection_Models/Roughness_Using_Microfacet_Theory)
4. [Real-time Rendering of Glossy Reflections using Ray Tracing and Two-level Radiance Caching — 表面越粗糙光线越发散、性能越差，粗糙度阈值以上回退到漫反射与探针](https://dl.acm.org/doi/fullHtml/10.1145/3610543.3626167)
5. [Bounded VNDF Sampling for Smith–GGX Reflections — 粗糙表面的可见法线采样会产生大量落在表面背面、必须丢弃的反射方向](https://dl.acm.org/doi/fullHtml/10.1145/3610543.3626163)
6. [Ray Tracing Gems 第 32 章: Accurate Real-Time Specular Reflections with Radiance Caching — 单像素采样下的镜面反射噪声与时空滤波](https://doi.org/10.1007/978-1-4842-4427-2_32)

---

原文：https://pangzhengboyin.com/articles/diffuse-specular-roughness-metallic-explained-15bfe314

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
