全局光照演进史:从离线渲染到实时Lumen的算法脉络 1. 全局光照从离线到实时的技术革命第一次在游戏里看到阳光透过树叶在地面投下斑驳光影时我被震撼得说不出话。这种真实的光影效果就是全局光照Global Illumination简称GI技术的魔力。简单来说GI模拟了光线在场景中的多次反弹让虚拟世界的光影如同现实般自然流动。传统渲染只计算直接光照时场景会显得非常平。就像用手电筒直射墙壁你只能看到一个明亮的光斑。而现实中这个光斑会照亮周围区域光线还会在房间内不断反弹。GI技术正是要模拟这种复杂的光学现象让红色墙壁把红光反射到邻近物体上让阳光透过窗户后能照亮整个室内空间。在电影行业艺术家们早就用蒙特卡洛光线追踪这类离线渲染技术实现了惊人的GI效果。但这类算法需要超级计算机渲染数小时甚至数天根本无法满足游戏需要的实时性每秒60帧以上。游戏开发者不得不用各种作弊手段来模拟GI比如预计算光照贴图、使用简化的环境光遮蔽等。直到最近几年随着硬件性能提升和算法突破实时GI技术终于迎来爆发。从早期的反射阴影贴图RSM到光线传播体LPV再到最新的Lumen技术实时GI的画质和效率都在飞速进化。现在我们终于能在游戏中体验到接近电影级的动态光影效果。2. 离线渲染的基石蒙特卡洛方法2.1 渲染方程与积分难题所有光照问题的核心都可以归结为一个数学公式——渲染方程。这个看似简单的积分方程描述了光线如何在场景中传播和交互。但要在计算机中求解它却面临着巨大的计算挑战。想象你要计算一个像素的最终颜色。需要收集来自半球空间所有方向的光线考虑物体表面的反射特性还要计算光线在场景中的多次反弹。这就像要统计一个体育馆内所有人的体温但每个人体温都在实时变化而且会互相影响。蒙特卡洛积分是解决这类高维积分问题的利器。它的核心思想很直观与其精确计算整个积分不如随机采样一些点来估算。就像要估算一个池塘里鱼的数量不需要把水抽干随机撒几网统计就能得到不错的结果。2.2 光线追踪的艺术基于蒙特卡洛的光线追踪是离线渲染的黄金标准。算法从相机出发发射光线光线在场景中反弹时每次碰撞都会产生新的光线分支。就像台球桌上的母球撞击其他球后会产生复杂的运动轨迹。但这种方法有个致命问题噪点。由于采样是随机的相邻像素可能得到完全不同的结果。要获得平滑图像需要发射海量光线。在《玩具总动员》这样的电影中每个像素可能需要数千次采样渲染一帧就要数小时。我曾在项目中尝试用光线追踪实现简单GI。一个仅包含几个立方体的场景在1080p分辨率下要达到可接受的画质需要每像素256次采样渲染一帧就要5分钟。这还只是单次反弹Single Bounce要实现真实的多重反弹Multi Bounce效果计算量会呈指数级增长。2.3 重要性采样的智慧聪明的图形学家发现均匀随机采样效率太低。就像在黑暗房间里找电灯开关盲目乱摸不如沿着墙系统搜索。重要性采样Importance Sampling技术就是让采样点更多集中在可能对结果有重要贡献的区域。对于漫反射表面采用余弦权重采样Cosine Lobe Sampling效果显著。这种采样方式更倾向于沿着表面法线方向发射光线因为这是光线贡献最大的区域。实测表明同样的采样次数下采用余弦采样的噪点能减少60%以上。而对于光滑的金属表面则需要更尖锐的采样分布如GGX分布。这就像用手电筒照射时会根据表面粗糙度调整光束的聚焦程度。合适的采样策略能让算法事半功倍这是所有蒙特卡洛渲染器的核心技术。3. 实时GI的早期探索3.1 反射阴影贴图RSM的突破2005年提出的RSM是实时GI领域的里程碑。它的核心思想很巧妙既然计算所有光线反弹太困难不如先把直接光照注入场景再模拟一次反弹。具体实现时RSM会从光源视角渲染一张特殊贴图记录下所有被直接照亮的表面位置、法线和光照强度。这些点就成为虚拟的次级光源。在正式渲染时每个着色点会从这些虚拟光源收集间接光照。我在一个地下城场景中实现过RSM。当角色举起火把时周围的墙壁会被间接照亮效果相当惊艳。但RSM有两个明显局限一是只能计算单次反弹二是随着虚拟光源数量增加性能下降很快。通常需要将512x512的RSM降采样到64x64使用这会导致明显的漏光问题。3.2 光线传播体LPV的创新Crytek在CryEngine 3中提出的LPV技术将场景划分为体素Voxel网格让光线能在三维空间中传播。这就像把房间划分成无数小格子记录每个格子里的光照情况。LPV使用球谐函数Spherical Harmonics紧凑地存储每个体素内的光照分布。球谐函数的神奇之处在于它能用几个系数就表示复杂的光照分布。实测中二阶球谐9个系数已经能很好表现漫反射光照。但LPV有个物理不准确的问题光线传播速度取决于迭代次数就像石子投入水中产生的波纹需要时间扩散。这导致动态光源下会出现光线延迟的视觉效果。尽管如此LPV的空间划分和球谐表示思想对后续技术影响深远。4. 体素化GI的进化4.1 稀疏体素八叉树SVOGISVOGI改进了LPV的均匀体素划分采用八叉树结构自适应细分空间。就像城市规划人口密集区需要更细的管理单元而旷野区域可以用大区块表示。SVOGI最酷的创新是圆锥追踪Cone Tracing技术。不同于传统的光线追踪发射细射线圆锥追踪发射的是逐渐扩大的锥形。远处的物体用低精度体素表示正好匹配圆锥的扩大特性。这种多分辨率采样思想显著提升了算法效率。遗憾的是SVOGI的八叉树结构在GPU上实现复杂性能开销大。我在UE4的一个早期分支中尝试过SVOGI在复杂场景中帧率会骤降到20fps以下。这促使人们寻找更GPU友好的方案。4.2 基于视口的体素GIVXGIVXGI采用了一种更聪明的空间划分策略——clipmap。它以摄像机为中心近处用密集体素远处用稀疏体素。就像人眼视觉近处看得清楚远处只需大致轮廓。VXGI还引入了透明度体素的概念。传统体素只记录表面是否被占据VXGI则记录每个方向的透光率。这能更准确地模拟光线穿过半透明物体如树叶、毛玻璃的效果。我在一个森林场景中对比过VXGI和SVOGI。VXGI在表现阳光透过树叶的效果上明显更优且帧率稳定在45fps左右。但VXGI仍存在漏光问题特别是对薄壁物体光线会泄漏到不该照亮的地方。5. 屏幕空间GI的崛起5.1 屏幕空间全局光照SSGI寒霜引擎提出的SSGI技术完全摒弃了3D体素转而利用屏幕空间已有信息。简单来说就是把当前帧渲染的像素当作次级光源。这就像看着镜子里反射的场景利用这些信息估算间接光照。SSGI的核心加速技术是Hi-Z缓冲。它像金字塔一样组织深度信息顶层是最粗略的深度图底层是原始深度。进行光线步进时先在粗粒度层级快速跳跃发现可能相交后再到精细层级精确定位。这种分层搜索策略使光线步进次数从线性降为对数级。我在一个镜面大厅场景中测试SSGI反射细节令人惊艳。但SSGI有个致命限制只能看到屏幕内的信息。当角色背对窗户时就无法获得窗外的光照信息导致间接光突然消失。这促使开发者思考混合方案。5.2 距离场辅助的SSGI为解决SSGI的视野限制后来技术开始结合全局距离场Distance Field。距离场记录了场景中每个点到最近表面的距离即使物体不在视野内。这相当于给SSGI装上了记忆知道墙后有什么。距离场还能加速光线相交测试。传统方法需要逐步测试而距离场能直接给出安全步长——在这个距离内保证不会碰到任何物体。这就像在黑暗中前进时知道下一步能安全迈出多远。实测表明加入距离场后SSGI的稳定性显著提升。在快速旋转镜头的压力测试中GI闪烁减少了70%。但距离场需要预计算对完全动态场景仍有局限。6. Lumen实时GI的集大成者6.1 硬件加速的光线追踪Lumen革命性地结合了硬件光线追踪和软件优化。新一代显卡的RT Core能并行处理数百万条光线使实时追踪成为可能。但纯硬件方案仍不够高效Lumen的智慧在于选择性使用硬件加速。对于首帧渲染Lumen主要依靠屏幕空间追踪利用Hi-Z实现高效步进。当发现屏幕空间信息不足时才触发硬件追踪查询全局信息。这种混合策略在画质和性能间取得了完美平衡。我在RTX 3080上测试Lumen4K分辨率下能稳定保持60fps。与传统软件方案相比硬件加速使光线查询速度提升了8倍同时画质更稳定。6.2 参数化表面缓存Lumen创新地使用参数化表面缓存Parameterized Surface Cache表示场景。不同于体素的三维划分它将场景表面参数化为二维图集就像把三维模型展开成UV贴图。这种表示特别适合GPU处理能高效支持各向异性过滤和mipmap。在渲染时Lumen会根据表面粗糙度自动选择合适的mip层级粗糙表面用低分辨率采样光滑表面则用高分辨率。实测表明表面缓存的内存效率是传统体素的3倍以上。在一个城市场景中体素方案需要2GB显存而Lumen仅用600MB就达到了更好效果。6.3 动态全局光照的艺术Lumen最惊艳的是对完全动态场景的支持。传统GI技术需要预计算或有限动态性而Lumen能实时响应所有变化移动的光源、变形的物体、甚至程序化生成的场景。这得益于其创新的时空重投影Temporal Reprojection技术。Lumen会复用前一帧的光照信息通过运动矢量将其重投影到当前帧。只有当变化超过阈值时才触发重新计算。这种惰性更新策略大幅降低了计算开销。在一个动态天气demo中我测试了从日出到日落的过渡。Lumen能无缝处理太阳位置和强度的变化云层投影在地面的动态变化也自然流畅。传统技术在这种极端动态场景下要么性能骤降要么出现明显闪烁。