起源引擎(Source Engine)在 2000 年的 SIGGRAPH 上第一次亮相,是 GoldSource 的继任者。它的静态光照走的是基于辐射度(Radiosity)的预计算路线——也就是先把光烘进贴图,运行时不再实时算。这篇文章想从实现的角度,把 VRAD 这套工具到底怎么干活、光照贴图又是怎么编码的,尽量讲清楚。
辐射度光传输方程
辐射度算法要解的其实是漫反射全局光照。漫反射时 BRDF 退化成常数,渲染方程也就跟着简化成下面这样:
$$L_o = L_e + \sigma_s \int_A L_i F(x,x') dA(x')$$
式子里 σs 是漫反射 Albedo(在 VTF 材质里对应 $reflectivity 参数),F 是几何项,把可见性、距离衰减和角度关系都包了进去。这是第二类 Fredholm 积分方程,没有解析解,只能靠数值方法去逼近。
有限元离散化
VRAD 用的是有限元法(Finite Element Method)把连续的光照方程拆开。大致分这么几步:
- 面片细分:地图里每个 brush 表面都被切成一块块 patch,靠
CreateChildPatch()和SubdividePatch()两个函数完成。 - 可见性计算:先建一个 transfer list,再用 Ray Casting 判断哪些面片之间真的有光路。VVIS 阶段生成的 PVS 数据可以拿来做个粗筛。
- 空间索引:面片用空间哈希表来索引,这种思路在 RTXGI 2.0 这类新方案里也还在用。
离散之后,原来的连续积分就变成了线性方程组:
$$(I - \sigma F)L = L_e$$
这里 F 是 form factor 矩阵,L 是要求解的辐射度向量。VRAD 最多开 16 个线程(threadnum),通过 GatherLight() 并行地把这方程组解出来。
Form Factor计算
Form Factor 是辐射度算法的核心,说白了就是两个面片之间的几何关系。VRAD 里给了两种算的方式:
面片到微分面片(FormFactorPolyToDiff):来自 Philip Dutre 那本 Global Illumination Compendium 的公式 81,适合近距离精细算。
微分面片到微分面片(FormFactorDiffToDiff):基于 Pat Hanrahan 的课件,距离超过 patch 尺寸 5 倍时可以用近似公式。
光照贴图处理
解完之后,光照贴图还是一块块粗糙的方块,得靠 自适应超采样 把它磨平:
ComputeLightmapGradients() 会先算每个采样点的梯度。梯度小于 0.0625,说明这块地方变化很平缓,没必要再超采样;否则就调用 SupersampleLightAtPoint() 做 4 倍超采样。
到了《半条命2》二十周年更新,Valve 头一回把线性插值换成了双三次插值(Bicubic),光照过渡明显柔和了。这也是 2000 年以来这个算法第一次被动。
Radiosity Normal Mapping编码
传统光照贴图只存每个像素的总辐射度,方向信息就丢掉了。表面一旦有法线贴图,那些凹凸细节就吃不到正确的光。
起源引擎用了 Radiosity Normal Mapping(也叫 HL2 Basis),把光照投影到三个正交基底上。运行的时候,采样法线贴图里的 normal 向量,分别和三个基向量做点积,加权加起来就是这个点的静态光照:
$$L_{final} = (n \cdot b_0) L_0 + (n \cdot b_1) L_1 + (n \cdot b_2) L_2$$
它基于的是半球空间(跟球谐函数用的球空间不一样),能保住光照的方向性,于是法线贴图的凹凸和静态光照就能自然叠在一起,自阴影这类细节也出来了。
性能特征
VRAD 的编译时间主要跟这几样有关:
- 面片数量:patch 越多,线性方程组维度越大。
- 反弹次数:多反弹就得反复迭代。
- 光照贴图精度:
lightmap scale参数直接决定采样密度。
地图要是出现 leak(泄漏),VRAD 会去给一个无限大的外部空间算光照,编译时间一下就爆了。多线程在带 -final 的室外场景里还有瓶颈,这个 Valve 在 SDK 2013 里给了个补丁。
社区里有人做 GPU VRAD 想加速,但问题不少。到了起源2,VRAD3 转去了 Path Tracing 框架,还带了 Vulkan 硬件光追扩展,复杂场景编译时间缩了一大截。
技术限制
辐射度算法默认所有表面都是理想漫反射体,镜面反射和折射它就管不了了。碰到高频光照细节(比如很硬的阴影边缘),要么把 patch 密度提上去,要么换别的方法,比如光子映射。
另外光照贴图在运行期是死的,跟不上动态光源的变化。像手电筒这种会动的光,得另接一套动态光照系统才行。
参考文献
- Chris Green. "Efficient Self-Shadowed Radiosity Normal Mapping." SIGGRAPH 2007.
- Jason Mitchell, Gary McTaggart, Chris Green. "Shading in Valve's Source Engine." SIGGRAPH 2006.
- Groal et al. "Modeling the interaction of light between diffuse surfaces." 1984.
- Kajiya. "The rendering equation." 1986.