UE5.8 Substrate Glint 笔记
1. Glint 是什么
Glint 用于表现大量稀疏、细小、明亮的微表面闪点。
适合:
- 金属粉末
- 珠光漆
- 钻石或宝石闪烁
- 细小晶体
- 湿润颗粒
- 闪粉、亮片
普通 GGX 高光会把大量微小高光平均成一个连续高光,无法表现真实的颗粒闪烁。Glint 保留了这些离散的微晶体高亮事件。
2. Glint 和普通高光的区别
普通 GGX:
整个像素使用一个连续的微表面分布
Glint:
一个像素覆盖多个微晶体 Cell
每个 Cell 拥有独立的随机微表面状态
分别评估后再过滤合成
因此 Glint 的亮度会随着以下因素变化:
- 摄像机移动
- 光源方向变化
- 物体旋转
- UV 变化
- 微晶体密度变化
- 微表面粗糙度变化
3. 微表面斜率是什么
微表面不是完全平的,每个微表面都有自己的倾斜方向。
用两个数表示微表面倾斜程度:
slope = (sx, sy)
例如:
(sx, sy) = (0, 0) 表示平面
(sx, sy) = (0.3, 0) 向 X 方向倾斜
(sx, sy) = (0, -0.2) 向 Y 负方向倾斜
根据光线方向 L 和视线方向 V,先计算半角向量:
H = normalize(L + V);
然后把半角向量转换成目标斜率:
slope_h = float2(
-H.x / H.z,
-H.y / H.z
);
这个目标斜率表示:
微表面需要倾斜成什么样,才能把光反射到摄像机。
假设两个目标半角方向拥有相同的 NoH:
目标 A:H = (0.6, 0.0, 0.8)
目标 B:H = (0.0, 0.6, 0.8)
两者都有:
NoH = 0.8
如果你只使用:
D(NoH)
那么 A 和 B 的微表面概率一定相同。
但它们的斜率分别是:
Slope A = (-0.75, 0.0)
Slope B = ( 0.0, -0.75)
现在假设材质中有一种方向性微晶体分布:
X 方向容易出现长条微晶体
Y 方向几乎没有微晶体
那么真实结果应该是:
P22(Slope A) 很高
P22(Slope B) 很低
但 NoH 无法区分它们,因为两者的 NoH 都是 0.8。
这就是斜率的实际好处:
NoH 只能表达"距离中心多远"
Slope 还能表达"具体朝哪个方向"
4. P22 是什么
P22 可以理解为微表面斜率的概率分布。
它回答的问题是:
当前材质中,有多少微表面拥有这个倾斜方向?
如果目标斜率在分布中很常见:
P22 较高
→ 高光较强
如果目标斜率很罕见:
P22 较低
→ 高光较弱
Glint 中的 P22_M 是针对某个具体 Cell 的局部斜率分布评估。
5. Beckmann 在 Glint 中的作用
UE5.8 Glint 使用 Beckmann 形式的微表面斜率分布。
源码中会根据粗糙度创建 Beckmann 描述:
FBeckmannDesc Beckmann = GGXToBeckmann(SafeRoughness);
粗糙度较低:
微表面方向集中
高光更尖锐
粗糙度较高:
微表面方向分散
高光更宽、更柔和
Glint 并不是简单读取一张噪声贴图,而是根据目标斜率评估微表面匹配概率。
6. Glint 的完整处理流程
Glint UV
↓
计算 UVDDX / UVDDY
↓
构建当前像素 footprint
↓
把 footprint 近似成椭圆
↓
计算 major / minor 轴
↓
根据 minorLength 选择 LOD
↓
遍历椭圆包围盒中的候选 Cell
↓
计算每个 Cell 的 P22_M
↓
根据椭圆距离计算 EWA 权重
↓
对所有 Cell 加权累积
↓
sum / sumWts 归一化
↓
相邻 LOD 插值
↓
输出 Glint_D
↓
进入 Substrate 的光照计算
7. Footprint 是什么
Footprint 表示:
当前屏幕像素在 Glint UV 空间中覆盖的区域。
由于一个屏幕像素通常不只对应一个 UV 点,而是覆盖一小片 UV 区域,所以不能只采样一个微晶体。
通过 UV 导数得到 footprint:
UVDDX = ddx(GlintUV);
UVDDY = ddy(GlintUV);
这两个导数描述:
- 屏幕像素向 X 方向移动时,UV 如何变化;
- 屏幕像素向 Y 方向移动时,UV 如何变化。
它们形成一个 UV 平行四边形,Glint 将其进一步近似为椭圆。
8. 为什么要用椭圆 footprint
椭圆可以表示:
- footprint 的长轴;
- footprint 的短轴;
- footprint 的旋转方向;
- 当前像素覆盖的微晶体范围。
Glint 会计算:
majorLength
minorLength
eccentricity
并限制最大各向异性,源码中使用:
MaxAnisotropy = 4
这样可以避免极端拉伸的 footprint 导致性能和稳定性问题。
9. LOD 的作用
根据 footprint 的大小选择微晶体分布的 LOD。
源码逻辑大致是:
l = NLevels - 1 + log2(minorLength);
il = floor(l);
w = frac(l);
得到:
il 当前 LOD
il + 1 相邻 LOD
w 两个 LOD 的插值权重
最后进行:
P22 = lerp(P22_il, P22_il_plus_1, w);
LOD 的作用:
- footprint 很小时使用更细的微晶体分布;
- footprint 很大时使用更粗的统计分布;
- 避免远处闪点过密;
- 减少远距离闪烁;
- 减少 LOD 切换跳变。
10. Cell 遍历
Glint 不会遍历无限范围,而是先计算椭圆的包围盒。
对于包围盒内的每个候选 Cell,计算它相对于椭圆中心的位置:
ss = Cell 局部坐标 X
tt = Cell 局部坐标 Y
然后计算椭圆距离:
r2 = A * ss * ss
+ B * ss * tt
+ C * tt * tt;
判断:
r2 < 1
只有在椭圆 footprint 内的 Cell 才参与计算。
椭圆外的 Cell 会被直接跳过。
11. P22_M 的处理内容
每个候选 Cell 会进行局部微晶体评估,主要包括:
- 稳定哈希;
- 随机序列生成;
- 随机旋转;
- 微晶体相对面积判断;
- LOD 对应的微晶体密度;
- 目标斜率计算;
- Beckmann 斜率分布评估;
- Glint LUT 查询;
- 返回该 Cell 的局部响应。
可以概括为:
P22_M =
微晶体密度
× 斜率匹配概率
× 随机微晶体状态
12. EWA 权重
Glint 使用椭圆加权思想,对 footprint 内的 Cell 进行空间过滤。
源码中的权重大致为:
W = exp(-2 * r2) - exp(-2);
权重特点:
r2 越小 → 越接近椭圆中心 → 权重越大
r2 越接近 1 → 越接近边缘 → 权重越小
r2 ≥ 1 → 不参与计算
累积过程:
sum += P22_M * W;
sumWts += W;
最后归一化:
filtered = sum / max(epsilon, sumWts);
这样可以把一个像素覆盖的多个闪点合成为稳定结果。
13. Glint 为什么不会简单地闪烁失控
Glint 不是简单地给每个像素生成随机噪声,也不是简单叠加上一帧结果。
它主要依靠:
- 稳定哈希;
- UV footprint;
- 椭圆 Cell 过滤;
- EWA 权重;
- LOD 选择;
- 相邻 LOD 插值;
- 微表面斜率分布。
因此它属于:
当前像素空间范围内的统计过滤
而不是:
上一帧画面累积
14. Glint 的主要性能开销
Glint 比普通 GGX 贵,原因不是单独的 NoH 或一次法线匹配,而是多个步骤叠加:
- 计算 UV 导数;
- 构建 footprint;
- 计算椭圆包围盒;
- 遍历多个候选 Cell;
- 每个 Cell 执行哈希和随机化;
- 计算微晶体斜率;
- 查询 Glint LUT;
- 计算 EWA 权重;
- 对两个相邻 LOD 分布进行评估;
- 归一化并进行最终插值。
简化表示:
Glint 成本
≈ Cell 数量
× 每个 Cell 的斜率分布计算
× LOD 数量
× LUT / SampleGrad 成本
footprint 越大,候选 Cell 越多,成本越高。
15. Glint 的性能控制方向
可以从以下方面控制成本:
- 降低 Glint Density;
- 降低 Glint 覆盖范围;
- 限制最大各向异性;
- 远距离降低 Glint 强度;
- 远距离使用更粗 LOD;
- 只对重要材质启用;
- 使用平台质量开关;
- 避免在大量屏幕像素上同时使用;
- 避免和高成本透明、折射、复杂 Substrate lobe 叠加。
Glint 适合用于:
少量高价值材质
不适合默认应用到整个场景。
16. Glint 和 Fuzz 的区别
Glint
稀疏、离散、闪烁的微晶体高光
适合:
- 金属闪粉;
- 宝石;
- 珠光漆;
- 水晶;
- 亮片;
- 微小晶体。
Fuzz
连续、柔和、掠射角明显的高光 lobe
适合:
- 短绒;
- 毛发边缘;
- 天鹅绒;
- 布料;
- 纤维表面;
- 柔软织物。
核心区别:
Glint:离散的闪点事件
Fuzz:连续的掠射反射 lobe
17. 普通 Noise 能不能替代 Glint
可以做出类似的视觉效果,但不能完全替代 Glint。
普通 Noise 叠加高光通常缺少:
- 微表面斜率匹配;
- 真实的半角方向响应;
- footprint 过滤;
- Cell 级别的随机微晶体;
- LOD 统计;
- EWA 空间积分;
- 稳定的远距离表现。
所以普通 Noise 更像:
颜色噪声 + 人工亮度权重
Glint 更像:
微晶体分布 + 光学方向匹配 + 空间过滤
18. 最终理解
Glint 的核心不是"生成很多随机亮点",而是:
根据光线和视线计算目标微表面斜率
↓
判断每个微晶体是否拥有接近这个斜率
↓
根据当前像素 footprint 过滤多个微晶体
↓
使用 EWA 权重和 LOD 插值合成最终高光
最简公式:
GlintPixel
≈
Σ(
P22_M(目标斜率)
× 微晶体密度
× EWA footprint 权重
)
÷
Σ(EWA 权重)
一句话总结:
Glint 是对离散微晶体斜率分布进行 footprint 感知的空间过滤,从而得到稳定、稀疏、随视角变化的闪烁高光。
