使用球谐函数(Spherical Harmonics, i.e. SH)模拟动态全局光照是游戏引擎里通用的解决方案。针对SH的介绍大部分过于偏学术,在实际的应用中去理解会更浅显易懂一些。
实时计算间接光照是一个难题,因为要计算最少一次积分。数学上常常把很难在某个空间得到求解的问题,转换到另外一个空间里,利用新空间的某些特性,降低求解难度。其中泛函分析是以函数空间为研究对象,利用某些已知函数空间的特性,去简化问题求解。其中SH为基的函数空间就是常用的工具之一。SH除了满足作为函数空间basis的基本条件外,还有以下特性:
- 针对处处光滑连续的问题,SH basis的解快速收敛。这个性质说明,像间接光照这样的低频问题(高频的问题可以用小波求解),可以在SH空间用极少的basis项去快速得到近似解(3 bands, 9 coefficients)。
- 旋转不变。这个性质保证当环境光照发生相对旋转的时候,不会出现计算结果的闪烁。
- Lighting function和max(cos(theta), 0) transfer function的卷积(即我们要求解的环境光照的积分)正好可以压缩存贮在一个Matrix4x4里,对法线运算后重构环境光照。另外光滑连续函数在3D空间的卷积等于SH空间的点积。这个性质可以用来计算更复杂的动态光照效果(Precomputed Radiance Transfer)。
以Unity为例,其对天空盒的SH计算参考《Stupid Spherical Harmonics(SH) Tricks》里的算法。实现的步骤首先是Prefiltering,先对环境贴图的像素逐个对SH Basis做一次加权采样投影。第二步是提取用于法线重构光照环境需要的矩阵信息。《An Efficient Representation for Irradiance Environment Maps》里有完整的推导过程。这一步Unity的算法和Paper里给出的常数C1-C5差了一个PI,是在实际运算中抵消了。
知道原理后,可以把引擎的这部分功能提取出来给美术人员使用。一个应用场景就是角色的光照。比如有些游戏里在夜晚的场景为了突显角色, 想让角色的受光强度和色调比场景要明亮强烈一些,即自定义天光。
一种方案是单独一个角色编辑场景烘培SH,然后直接从引擎中提取unity已经计算好的SH。这种方案优点是烘培速度快。缺点是不直观,美术人员不能立即查看角色在关卡场景里的最终效果,需要反复在两个场景之间切换,调整参数。另外一种方案是在关卡场景里烘培和查看角色的天光效果,每次把调好的天光烘培完以后,提取给角色使用,然后再把关卡场景测试角色用的light probe信息revert。这种方案优点是可以在关卡场景直接查看角色的天光效果色调强度是否合适。缺点是unity 5.0以后的版本不能单独烘培light probe, 每次场景的光照烘培时间都很长, 调整反馈慢。
下图是一个自定义烘培角色光照结果(左边是Unity引擎烘培的天光。 中间是直接从同样的Irradiance Map计算的结果,和Unity的计算结果是一样的,但是更快,方便在场景里预览。 右边是随意指定的一张HDR Irradiance Map的结果。) 另外角色的Glossy Reflection Map也可以单独指定,方便自定义一些金属质感的表现,同样是一键烘培,不再需要引擎计算。
![42a1d4f0a3cc47185d1417689685f22a.png](https://i-blog.csdnimg.cn/blog_migrate/94a6163fecc0471bd0d87f8125546a86.jpeg)