Skip to content

feat: optimize IBL and SH baking#15

Merged
GuoLei1990 merged 4 commits intomainfrom
feat/filament-ibl-sh-optimization
Mar 11, 2026
Merged

feat: optimize IBL and SH baking#15
GuoLei1990 merged 4 commits intomainfrom
feat/filament-ibl-sh-optimization

Conversation

@GuoLei1990
Copy link
Member

@GuoLei1990 GuoLei1990 commented Mar 10, 2026

概述

将 IBL(基于图像的光照)和 SH(球谐光照)烘焙算法全面对齐 Google Filament 的实现,修复多个影响画面质量的核心问题。

改动内容

IBL 预过滤卷积(把环境贴图按不同粗糙度模糊成多层 mip)

  • GGX 分布函数精度优化:用 (a-1)(a+1) 替代 a²-1,减少浮点误差(数学上等价,但浮点计算更精确)
  • 采样概率密度清理(PDF):去掉之前的 + 0.0001 防除零 hack,改用 MIN_ROUGHNESS 从源头保证 D 值不会导致除零
  • mip 层级采样修正:加入 K=4 重叠补偿(采样点之间有约 4 倍的立体角重叠,需要补偿 +1 级 mip 来消除采样噪点),之前缺少这个补偿导致反射模糊、太阳扩散。参考:Real-time Shading with Filtered Importance Sampling - Krivanek
  • 最小粗糙度保护:增加 0.002025 下限(与 engine 渲染端的 MIN_ROUGHNESS 一致),防止极低粗糙度时除零
  • 超亮像素压缩(compressHDR):在卷积前压缩超亮像素(>1024),防止太阳等极端光源在加权平均时导致周围大面积异常偏亮。参考:Tone Mapping - Brian Karis (Epic Games)

GGX 重要性采样(决定往哪些方向采样环境贴图)

  • 对齐 Filament 的 cosTheta 计算公式,减少浮点误差

SH 球谐光照(用 9 个系数近似表示低频环境光)

  • 精确立体角计算:用 Filament 的精确公式(atan2 积分)替代之前的近似公式(4 / r³),SH 系数更准确
  • 消除振铃伪影(deringing):加入 sinc 窗函数,自动寻找最优平滑参数消除高对比 HDR 环境下的异常色斑。参考:Deringing Spherical Harmonics - Peter-Pike Sloan

解决的问题

问题 原因 修复
太阳区域在反射贴图中扩散过大 mip 层级缺少重叠补偿,采样了过于模糊的 mip 层 加入 K=4 重叠补偿
低粗糙度材质(金属、玻璃)反射模糊不清晰 同上 同上
超亮像素导致周围大面积异常偏亮 太阳等极端光源值过高,在卷积加权平均时拉高周围区域 compressHDR 在卷积前压缩超亮像素
暗部可能出现异常色斑 球谐函数只有 3 阶,截断高频信息导致振铃 窗函数自动消除振铃

价值

  1. 反射质量大幅提升:镜面反射从模糊变为清晰锐利,金属、玻璃等材质表现力显著增强
  2. 光照更真实:太阳高光形状准确,不再异常扩散,与物理渲染预期一致
  3. 消除 HDR 伪影:超亮像素不再导致周围区域异常偏亮,暗部不再出现异常色斑
  4. 与业界标准对齐:核心算法与 Google Filament 完全一致,烘焙质量对标业界顶级引擎

测试计划

  • 用含强光源(太阳)的 HDR 环境烘焙 — 验证太阳区域紧凑,周围无异常偏亮
  • 检查低粗糙度镜面反射 — 应清晰锐利
  • 对比 SH 光照 — 高对比场景无异常色斑
  • 验证完美镜面(roughness=0)路径正常工作

🤖 Generated with Claude Code

- IBL specular: use Filament's D_GGX with (a-1)(a+1) fp accuracy optimization
- IBL specular: correct PDF calculation (D * 0.25) and LOD bias K=4
- IBL specular: add HDR luminance compression (compressHDR) to prevent super-bright pixel bleeding
- IBL specular: add MIN_ROUGHNESS (0.002025) to prevent division by zero
- Importance sampling: use Filament's cosTheta2 formulation for better fp accuracy
- SH: replace approximate solid angle with Filament's exact sphereQuadrantArea
- SH: add sinc⁴ windowing deringing (Peter-Pike Sloan) with auto-cutoff binary search
- SH: add SH rotation (band1/band2) for optimal deringing direction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@GuoLei1990 GuoLei1990 requested review from hhhhkrx and zhuxudong March 10, 2026 17:02
…erences

Filament is an implementation, not the origin of these algorithms.
Updated comments to reference the actual papers and authors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@hhhhkrx
Copy link
Contributor

hhhhkrx commented Mar 11, 2026

roughness == 0 这条路径也做了 compressHDR(),会把 mip0 从原始环境改成预压缩结果,而且如果运行时还有 tonemapping,会和这里叠加,建议只在 mipLevel > 0 的卷积路径做压缩。

@GuoLei1990
Copy link
Member Author

roughness == 0 这条路径也做了 compressHDR(),会把 mip0 从原始环境改成预压缩结果,而且如果运行时还有 tonemapping,会和这里叠加,建议只在 mipLevel > 0 的卷积路径做压缩。

done

@zhuxudong
Copy link
Member

rotateSHBand2() 我建议重写成和 Filament 更同构的形式,而不是继续保留现在这版“隐式矩阵约定”的实现。

当前写法里 M 实际上大概率是在按列向量语义使用,但 number[][] + mulMat3Vec3() 非常不直观,review 和后续维护都很容易把 row/column 约定搞反。

更稳的做法是直接按 Filament 构造 ROverK:project(M[0])、project(M[2])、project(n*(M[0]+M[1]))、project(n*(M[0]+M[2]))、project(n*(M[1]+M[2]))。这样可以直接对照上游实现,也更不容易引入转置错误。

建议同时补最小数值测试锁住 identity / 90° rotation / 随机正交矩阵 case。

@GuoLei1990
Copy link
Member Author

rotateSHBand2() 我建议重写成和 Filament 更同构的形式,而不是继续保留现在这版“隐式矩阵约定”的实现。

当前写法里 M 实际上大概率是在按列向量语义使用,但 number[][] + mulMat3Vec3() 非常不直观,review 和后续维护都很容易把 row/column 约定搞反。

更稳的做法是直接按 Filament 构造 ROverK:project(M[0])、project(M[2])、project(n*(M[0]+M[1]))、project(n*(M[0]+M[2]))、project(n*(M[1]+M[2]))。这样可以直接对照上游实现,也更不容易引入转置错误。

建议同时补最小数值测试锁住 identity / 90° rotation / 随机正交矩阵 case。

done

…tter readability

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@GuoLei1990 GuoLei1990 merged commit 4e634e7 into main Mar 11, 2026
@GuoLei1990 GuoLei1990 changed the title feat: optimize IBL and SH baking to match Filament feat: optimize IBL and SH baking Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants