上一篇讲完了光追跑进实时的三个条件。现在看一个更具体的问题:打开游戏的光追开关,画面里到底有多少像素是光追算出来的?
答案比想象中少。以《控制》这类游戏的实际帧结构为例,真正交给光追的是反射、阴影、环境光遮蔽和间接光;而“每个像素看到的是什么形状、什么贴图”,仍然由光栅化决定 1。这不是偷懒,而是分工。
两种工具,回答的是两类不同的问题
光栅化回答的问题是:“从相机看出去,每个像素上是什么。”它把三角形投影到屏幕上,覆盖到哪些像素,就给哪些像素上色。相机只有一个,屏幕上的像素排成整齐的格网——光栅化天生就为这种成批、只看相机方向的问题设计。
光线追踪回答的是另一个问题:“从这里、往这个方向看,第一个挡住视线的是什么。”出发点不必在相机上,方向也不必排成格网 1。第 1 篇里光栅化做不了的阴影、反射、折射,全都属于这一类:阴影是从表面往灯的方向看有没有被挡住;反射是沿镜面方向看能看到什么;环境光遮蔽是看头顶那片天空中多大一片被挡住;间接光(全局光照)是看弹出去的光落在了哪里、带回了什么颜色。
在光追之前,这些效果靠什么“凑”
没有实时光追的年代,这些效果靠屏幕空间近似来凑:屏幕空间反射(SSR)把已经渲染好的画面当成一个场景,沿屏幕内的像素搜索反射内容;屏幕空间环境光遮蔽(SSAO)用深度图估计遮挡 2。它们的共同前提是,只看得见屏幕里出现过的东西,屏幕外的一切对它来说都不存在。后果很具体:镜头一转,一直待在画面外的物体就不会出现在反射里;水面和玻璃的反射在画面边缘会忽然变干净;物体贴地的那道接触阴影也可能消失。光追的收益就是解除了这个限制,它查询的是真实的三维场景 2。
最“便宜”的那项,为什么反而留给光栅化
光栅化最擅长的那件事,恰恰是光追最不划算的那件事。
第一是光线预算。 1080p 大约 200 万像素。主可见性每个像素至少要一条光线,一帧 200 万条,一条都省不掉,而且必须自己算,不能靠相邻像素猜。效果类查询却可以少采样:EA 的实时演示 PICA PICA 里,反射只做半分辨率、每像素 1/4 条光线,再靠时空滤波重建回全屏,整个演示平均每像素约 2.25 条光线 34。对比离线路径追踪每像素成百上千条,实时混合渲染的全部预算只有“像素数 × 2”这个量级。总数越紧,就越要把光线留给“少发了就明显出错”的效果,而把最贵、最不可省又最规整的主可见性交给光栅化。
第二是纹理清晰度。 光栅化时,GPU 的像素着色器以 2×2 像素为一组(quad)执行,于是能算出纹理坐标在屏幕上的变化率,据此给每个像素挑合适的 mipmap 层级,远处用低分辨率贴图、近处用高分辨率贴图。光追里每条光线各自独立发起,命中点之间没有这种天然邻居关系,也就没有现成的屏幕空间导数,只能靠 ray differentials、ray cones 这类办法估算采样足迹,估不准就会糊或者闪 3。这不是能力差距,而是顺不顺手。
第三是连贯性。 相机光线方向接近、命中的也是邻近的三角形,显存访问成批成片,缓存利用率高;反射光线四面开花,缓存被反复冲掉 3。同样数量的光线,主可见性那些要便宜得多。EA 的结论也很直白:主可见的不透明几何,光栅化仍然占优 3。
交给光追的几件事,收益各不相同
阴影:取代阴影贴图。阴影贴图是从光源方向渲染的一张深度图,分辨率有限、覆盖范围还要分段,结果是边缘锯齿、细小物体漏光、接触处缺少随距离变硬的暗影。光追阴影从每个着色点往灯的方向发光线问“挡没挡”,接触阴影自然正确,半透明遮挡也能一起处理 2。
反射:取代屏幕空间反射,多出来的是屏幕外的内容、随粗糙度正确变化的模糊,以及不再随镜头转动而忽然出现或消失。
环境光遮蔽:取代屏幕空间环境光遮蔽,收益集中在近处——两个物体贴近的凹缝里,暗影不再受“屏幕里有什么”限制。
全局光照:取代静态烘焙。烘焙出来的间接光天色一变、物体一动就不对了,光追能实时更新。
半透明(玻璃、水):光栅化按三角形顺序画,透明物体必须排序,前后弄错就画错;光追本来就沿一条路径穿过去,可以边前进边累积吸收和折射 2。
这几项里只有全局光照和透明、半透明非光追不可,阴影、环境光遮蔽、反射都能用别的办法做,光追只是做得更好 2。这也解释了为什么光追设置可以分项开关,而且不同场景下收益差别很大。
代价在哪里
光线数量只是账本的第一页。
1/4 条光线当然有噪声,要靠降噪补,而降噪要借用前几帧的信息,于是画面上会出现拖影、闪烁,镜头快速转动时慢半拍;降噪本身也是一遍全屏处理,要花 GPU 时间 2。
光追还要维护场景的加速结构(BVH),动态物体和大量独立实例会带来每帧更新成本。Epic 的文档写明:实例数超过 10 万时,硬件光追的场景更新代价显著 5。Digital Foundry 实测 UE5 时也观察到这笔开销:在 1080p 加时间超分到 4K 的 RTX 2060 Super 上,硬件光追版 Lumen 比软件版慢约 7% 6。
而且“光追”从来不是一个固定档位。同一个效果可以调精度:UE5 的 Lumen 默认查 Surface Cache 里预先缓存的近似光照,快;切成 Hit Lighting,就在命中点真算材质、再发阴影光线,准得多也贵得多 5。它还能把光追换成软件版本——用网格距离场(把物体形状存成一张记录“到最近表面距离”的贴图,光线在其中步进)代替逐三角形求交,不支持光追硬件的显卡也能跑,只是精度低一档 57。
一帧里的实际分工
一个典型的光追帧就是这个顺序:光栅化先画出主可见性,同时把每个像素的位置、法线、粗糙度、材质存进 G-buffer;所有光追效果都从这些点出发发射光线,而不是从相机出发 12。也就是说,光追在一帧里根本不管“你看到的是什么”,只负责回答“这些表面上的光是怎么来的”。同一个效果内部也常常混着来:UE5 的 Lumen 做反射时先做屏幕空间追踪,屏幕里已有的信息又便宜又准,只有追踪失败或指向屏幕外的部分,才真正发出世界空间的光线 57。
怎么判断开不开光追
按这条分工,光追收益最大的场合就是屏幕空间近似失效的地方:夜晚和室内(屏幕外看不到的光源在影响画面)、玻璃水面抛光地面(反射必须正确)、物体密集贴合(接触阴影)。收益最小的场合是明亮的开阔地、大面积粗糙材质、屏幕内容基本齐备,这时屏幕空间反射加烘焙就能交出差不多的画面,开光追主要是为少数边缘像素付全屏的代价。
小结
混合渲染不是“硬件还不够快,先凑合一下”。两类查询的成本结构本来就不同:主可见性必须密集、连贯、每像素至少一次,是光栅化的主场;效果类查询可以稀疏、可以挑位置采样、再靠降噪重建,是光追的主场。所以即使光追全开,真正经过光线追踪的也只是阴影、反射、环境光遮蔽、间接光和半透明这些“从场景内部往外看”的部分;你想看清的形状、贴图、边缘,仍然由光栅化负责。