"Hello everyone, Today I'll be talking about the global illumination solution developed for idTech8.. This work has been used in 2 big projects running realttime at 60hz or higher on all platforms, and lays some of the foundations for next idTech iterations."
- 四笔约束同时收紧:性能压倒一切(全平台稳定 ≥60 Hz)、为所有人加快工作流(做法是简化、减少步骤、少出错)、尽量减少预处理、关卡更大且数量差不多翻倍(讲义 slide 2)。规模落到数字上,DOOM The Dark Ages 全部关卡可行走面积合计约 5000 平方公里,是 DOOM Eternal 的 4–10 倍,单人基础关卡 22 张对 13 张(讲义 slide 3);备注另给一条口径:低配指 Xbox Series S 与同类支持光追的硬件。
- 老办法的账单是按面积和改动次数累加的:idTech7 用路径追踪 lightmap(唯一 UV、BVH、lightmap LOD 等多道预处理,自建云烘最多 64 台机器,2 波段球谐编码,网络存两套编码以免重烘),任何改动都要重烘(讲义 slide 4–5);限制是漏光/接缝/条带与块压缩伪影,大图烘焙要 40 小时,最后只能把分辨率砍到 1/2;DOOM Eternal 的统计是最终质量烘焙 ≥4 到 10 小时、全图约 4 天周转、单关约 500 MB(压缩)、网络存储约 1.4 TB(讲义 slide 6)。
- 照搬的代价是一笔明确的推算:按 4–10 倍关卡估,单关预处理 16–100 小时、单关 2–5 GB,再加上关卡数约 1.7 倍,磁盘 44–110 GB、网络存储 9.5–24 TB、周期 27–68 天(讲义 slide 9,页内标为 rough estimate)。
- 新方案一帧七步:更新光网格 → 采样世界可见性 → 写世界辐射缓存 → 用上一帧结果更新辐照度体积 → 末级收集(只索引缓存、不做着色)→ 去噪 → 上采样;半透明另有 froxel 辐照度体积,用意是不必为半透明再做一遍查表(讲义 slide 11)。
- 把分箱搬到世界空间:视锥绑定的 tile/cluster 分箱在 RT 世界里不可用,于是做成级联光网格 —— 世界空间 AABB 单元、16×16×16 × 8 级联、首级 32 米、每单元最多 64 个 id(灯 16 位/反射探针 8 位/贴花 16 位)、约 30 MB,点亮一次 async dispatch、约 0.2 毫秒(控制台)(讲义 slide 12–13)。
- 每帧只更新一小块,而且这一遍只追可见性:每帧只更新 1 个级联加 1 个体积,每个探针每帧追 64/32/16 条可见性射线,命中记录压进 128 位(SBT 索引、primitiveID、instance 索引、重心坐标与命中距离)(讲义 slide 15–16)。
- 缓存与重建:世界辐射缓存用空间哈希(一维数组 + 多维哈希函数、25 立方厘米量化带单元 LOD、约 14 MB,讲义 slide 17);辐照度体积按 [Greger1998] 算并累加上一帧,存进八面体映射的探针图集(64 MB/低配 30 MB,讲义 slide 20);末级收集每像素一条射线,依次查屏幕空间、世界辐射缓存、最后回落到辐照度体积(讲义 slide 21)。
- 读数与未竟都写在明面上:p31 的热点表里 async 在 Series X 与 PS5 上省约 0.5 毫秒、Series S 约 0.4 毫秒,团队认为没有 async 就达不到性能目标;讲者自陈 CEDEC 2025 那次的画面对照没比同一组级联/体积、性能会有波动,SIGGRAPH 版已修正并补了平台;而间接镜面的光追这一支在控制台上因性能最终被关掉(约 2 毫秒,没时间继续优化),收益一页写的是量级上的节省与 0 磁盘占用(讲义 slide 27、31、32)。
1「性能压倒一切」:新项目的要求
「性能压倒一切」:新项目的要求
讲者开场先报身份与题目,他来自 id Software,任渲染技术总监,讲的是 idTech8 的全局光照(global illumination / GI)。他给这套方案的位置交代得很清楚:它是为 idTech8 开发的 GI 解法,已经在两个全平台跑到 60 Hz 或更高的项目里落地,同时为 idTech 后续版本铺一部分底。两个项目用的是不同迭代,Indiana Jones and The Great Circle 用的是早期版本,DOOM The Dark Ages 用的是最新一版。他顺带说到团队规模,id 与 MG 两家工作室都不到 200 人,技术团队尤其精简,能共用就共用(讲义 slide 1)。
交代完背景,他先把新项目压在 GI 头上的要求逐条摆开(讲义 slide 2)。第一条是性能压倒一切,标准是全平台稳定不低于 60 Hz。第二条是为所有人加快工作流,做法是简化,减少必须的步骤,步骤少了出错的机会也少,同时让迭代更快。第三条是尽量减少预处理。第四条是关卡更大,而且关卡数量差不多翻一倍。
第四件要求下面挂着几问(讲义 slide 2)。磁盘怎么装得下?lightmap(光照贴图)与探针这类预处理会不会更久?动态物体与次级动画会不会更多,他举的例子是物理、布料、植被与复杂过场?屏上的几何与角色也更多?这几问是同一处压力的四种问法,它们共同决定了旧方案那笔账还撑不撑得住。
他给「低配」划了一条线(讲义 slide 2 备注):低配指 Xbox Series S 以及同类硬件,也就是支持光追的那一档。这条口径在后面凡出现平台差异时都要带上。
这四条并列在一起,彼此是拉扯的关系。性能先摆第一位,其余三条都要在它的边框里兑现:关卡大一倍,屏上内容多一倍,预处理却要更少,迭代还要更快。讲者在这一页用问句把矛盾摊开,第四条里的「关卡数量差不多翻一倍」后面带一个问号,说明它在讲义里是一处待解的算术,还不算已经定下的结论。
还有一条口径要从这页的备注里取。页内正文列出的要求都出自幻灯文本,备注只补了低配的所指,也就是 Xbox Series S 一类支持光追的硬件。它同时说明了这套方案要覆盖的硬件下限在哪里,与「全平台稳定不低于 60 Hz」这条标准是配套的。
规模数字落在下一页(讲义 slide 3)。DOOM The Dark Ages 全部关卡可行走面积合计约 5000 平方公里,这个数只算可行走表面。与 DOOM Eternal 相比,关卡大 4 到 10 倍;单人基础关卡 22 张,上一代是 13 张。备注在同一页补了一句「单关示例」,说明这页另配了一张单关的图,本篇不引用那张图。
本章可核对的结论有三条。这套 GI 已在两个 60 Hz 或更高的项目里落地,DOOM The Dark Ages 用的是最新一版,Indiana Jones and The Great Circle 用的是早期版本(讲义 slide 1)。新项目对 GI 的要求是性能压倒一切(全平台稳定不低于 60 Hz)、简化以加快工作流、尽量减少预处理、关卡更大且数量近乎翻倍(讲义 slide 2)。可核对的规模是全部关卡可行走面积合计约 5000 平方公里、比上一代大 4 到 10 倍、单人基础关卡 22 张(对 13 张),而「低配」在讲义里指 Xbox Series S 一类支持光追的硬件(讲义 slide 2、3)。下一章看被这些要求指到的那套旧系统长什么样。
2老办法:路径追踪 lightmap 的全流程与它的账单
上一章的要求指向一套已经在用的系统,这一章看它在上一代长什么样(讲义 slide 4)。老办法的核心是路径追踪 lightmap(path tracing / 路径追踪)。它有明确的适用面:静态、不透明的几何。动态物体与半透明不归它管,那两条腿留到下一章。
它前面排着多道预处理:唯一 UV 展开、BVH 生成、lightmap LOD,页内以「等」收尾,清单未穷举。
烘焙放在自建云上完成(讲义 slide 4)。每台机器处理 N 个实例的 lightmap,并派发 N 个 tile 线程;每个 tile 的每个 texel 要做几件事,光栅化三角形、路径追踪、更新辐照度缓存 [Ward1988];HDR 结果用 2 波段球谐(spherical harmonics / SH)编码 [Ramamoorthi2001]。云烘的机器数上限,讲义给到 64 台(讲义 slide 4 备注)。
这段流程里有两处以「提前算好」换运行时的做法。第一处是 2 波段球谐,它的用途是之后重建有向光照结果,讲者的评价是便宜且够用,团队在很多地方都在用(讲义 slide 4 备注)。第二处是网络上存两个版本:一份是 BC6H L0 加 3×BC1 L1 [O'Donnell18],再走 Oodle Kraken;另一份是 RGBE L0 加 3×32 位 L1,同样走 Oodle Kraken。存两份的理由讲义写得很直白,不同平台各有各的编码方式,存两份是为了不必重烘。备注另给了两条口径:Switch 最后用的是 ASTC 加 Kraken;所有 tile 在收尾时会聚合成最终的实例 lightmap。
只要任何改动发生,就要重烘(讲义 slide 4)。改动包括光照、几何、设置等。触发条件在下一页列开(讲义 slide 5):光照改动;画质设置改动,他举了最终烘焙所用的 SSAA 这一项;几何改动;可行走区域改动导致 LOD 需要重新调整。这一页没有配图,讲义只给了文字。
限制与账单另占一页(讲义 slide 6)。老办法常见的毛病是漏光、接缝、条带、分辨率,以及块压缩伪影。绕过它们的办法是自定义 UV、厚墙、贴花、抖动等。
这一串绕过办法的形态相差很大,各自针对一种病灶。自定义 UV 与厚墙属于建模与资产层面的约定,要在制作期就排布好;贴花与抖动是在渲染阶段补上去的,用来遮住压缩与采样留下的痕迹。它们是逐处打的补丁,靠美术与工程在具体场景上手工处理。
优化做了不少,仍不够(讲义 slide 6)。大图要烘 40 小时,最终把分辨率砍到 1/2。默认密度是每平方米 2×2 texel,关键区域美术可以调高。这一刀省下的是烘焙时间、磁盘、网络与内存各约 4 倍,代价是画质,用双三次过滤缓解。讲者备注把话说全:他们花了不少时间优化,即使如此最后仍得降到 1/2 分辨率,换取更能接受的烘焙时间与内存、磁盘、网络占用。这里的「大图 40 小时」与「最后砍到 1/2 分辨率」属于上一代产品线上的实测读数。
DOOM Eternal 的统计也在这页(讲义 slide 6):最终质量烘焙 ≥4 到 10 小时,全图周转约 4 天,单关磁盘约 500 MB(压缩后)/约 5 GB(未压缩),网络存储约 1.4 TB。这几个数同样是上一代产品的实测口径。页内这张统计表是幻灯文本,行列未经人工核对,本章只引幻灯文本与备注明确给出的量。
本章可核对的结论有四条。老办法是路径追踪 lightmap,只管静态不透明几何,前面排着唯一 UV 展开、BVH 生成、lightmap LOD 等多道预处理,并用自建云烘完成,机器上限 64 台;每个 tile texel 走光栅化、路径追踪与辐照度缓存更新,HDR 结果用 2 波段 SH 编码(讲义 slide 4)。网络上存两套编码(BC6H L0 加 3×BC1 L1,以及 RGBE L0 加 3×32 位 L1,各自再接 Oodle Kraken),用意是不同平台各用各的编码而不必重烘(讲义 slide 4)。任何改动都要重烘,触发条件含光照、画质设置(如最终烘焙的 SSAA)、几何与可行走区域改动导致的 LOD 调整(讲义 slide 4、5)。账单方面,优化后大图仍需 40 小时、最终砍到 1/2 分辨率,DOOM Eternal 的最终质量烘焙为 ≥4 到 10 小时、全图约 4 天、单关约 500 MB(压缩)/约 5 GB(未压缩)、网络约 1.4 TB,这些属上一代实测(讲义 slide 6)。下一章看这条主路之外的两条腿,以及把老办法照搬到新规模时的推算。
3另外两条腿、依赖链,以及照搬老办法的代价
上一章的 lightmap 只管静态不透明几何。动态物体与半透明另走两条路(讲义 slide 7),本章先看这两条腿各自的出身与用法,再看它们与主路之间怎么相互牵动,最后看照搬旧办法的推算。
第一条腿是辐照度体积(irradiance volume),负责间接漫反射,出处是 [Greger1998]。它的生成方式有两种,从可行走玩家区域自动生成,或由人手工摆放。它在 lightmap 烘完之后才做路径追踪,顺序不能颠倒。结果同样按 HDR 加 2 波段球谐编码。运行时是逐顶点查表,取最近的 8 个探针做线性混合。它内部叫 ambient probes。讲义给的口径是它比 lightmap 快得多,但通常单机单关仍要约 10 分钟烘焙时间(讲义 slide 7 备注)。
第二条腿是反射探针(reflection probe),负责间接镜面,出处是 [Mittring2009]。它用盒投影立方体贴图环境映射 [Czuba2010],样本由美术手工摆放,同样在 lightmap 烘完之后生成,存成 BC6H 立方体贴图数组,运行时按 cluster/tile 分箱 [Olson2012][Sousa2016][Geffroy2020] 应用。它内部叫 environment probes(讲义 slide 7 备注)。重烘触发条件与 lightmap 类似,这两条腿同样绑在重烘这件事上。
这两条腿与主路有一个共同点,它们都排在上游烘完之后才轮到。辐照度体积与反射探针的生成时机都写着在 lightmap 烘焙之后,说明主路上的任何一次改动都会顺延到它们身上。讲义在本页最后一行把这层依赖收紧:两条腿的重烘触发条件与 lightmap 类似。
依赖链在下一页(讲义 slide 8)。这些系统彼此依赖,能在多处断掉,失败可以归成两类。一类出在结果层面,lightmap 的实例或探针看起来错位、坏掉,可能的来路是网格变了、关卡布局变了、lightmap LOD 变了、光照变了,也可能是代码 bug 或 NaN。另一类出在烘焙作业本身,云机上的活没跑完,可能是崩溃、Windows 更新、杀毒软件或磁盘满。两类的共同点是一处出问题会牵动多个系统。这一页讲义没有配图,只给文字。
真正的压力测试在下一页(讲义 slide 9)。讲者换了个问法,如果 DOOM The Dark Ages 照搬同一套老技术会怎样。页内把这一页的结论标成 Rough estimate,它属于假设照搬老办法的推算,读的时候不能当成实测。
推算按两档规模给出(讲义 slide 9)。按 4 倍关卡,单关预处理约 16 到 40 小时,压缩体量约 2 GB;按 10 倍关卡,约 40 到 100 小时,约 5 GB。关卡数约 1.7 倍之后,磁盘需求最少约 44 GB、最多约 110 GB;网络存储最少约 9.5 TB、最多约 24 TB;周转时间最少约 27 天、最多约 68 天。页内这几行同样是幻灯文本,行列未经人工核对,本章只引页内明确写出的数值。
备注把结论说得更重(讲义 slide 9 备注)。就算云端机器数量翻倍、每台核数也翻倍,还是慢,而且解决不了其他几笔账。他还补了一句,如果关卡只按最低的 4 倍增长,也会相当程度地限制美术与关卡设计,而且这处痛点在项目末期最要命,因为那时最需要快速迭代。他把问题收成一句:继续在老技术上投入,还是往前走?
本章可核对的结论有三条。动态物体与半透明靠两条腿处理,辐照度体积管间接漫反射、出自 [Greger1998],从可行走区域生成或手工摆放、在 lightmap 之后路径追踪、HDR 加 2 波段 SH 编码、逐顶点线性混合最近 8 个探针,单机单关仍要约 10 分钟;反射探针管间接镜面、出自 [Mittring2009],用盒投影立方体贴图 [Czuba2010]、手工摆放、在 lightmap 之后生成、存 BC6H 立方体贴图数组、按 cluster/tile 分箱 [Olson2012][Sousa2016][Geffroy2020] 应用,重烘触发条件与 lightmap 类似(讲义 slide 7)。这些系统彼此依赖,失败可分两类,一类是实例或探针错位(网格、关卡布局、lightmap LOD、光照改动、代码 bug 或 NaN),一类是烘焙没跑完(崩溃、Windows 更新、杀毒、磁盘满)(讲义 slide 8)。照搬旧办法的推算标着 Rough estimate,按 4 倍关卡给出单关约 16 到 40 小时与约 2 GB,按 10 倍给出约 40 到 100 小时与约 5 GB,叠加约 1.7 倍关卡数后是磁盘约 44 到 110 GB、网络约 9.5 到 24 TB、周转约 27 到 68 天,这些是假设推算而非实测(讲义 slide 9)。下一章看团队手上那块新硬件的定位。
4出发点:把硬件光追当可见性工具
上一章把老办法的账算到了十倍规模上,结论是照搬撑不住。这一章回到团队手里已有的那块新硬件,看他们给它安排的定位(讲义 slide 10)。
起点是 2021 年 6 月 DOOM Eternal 的 idTech7 光追更新。硬件光追到那时已有近十年历史,新一代主机都支持。团队对它的定位是把它当作一个可见性工具,并且强调与计算着色器一样可以有创意地用。这一定位决定了后面整套方案的样子,光追在这里主要用来问「能不能被看见」,不承担完整的光线传输。
在 idTech8 里,光追还被用在玩法等其他用途上(讲义 slide 10):材质查询(声音、贴花这一类)、粒子碰撞、流送、网格生成、工具。讲义对这些用途只点名,不展开各自的实现。
方向上要做的事是统一并简化既有系统。这里有一条前提被讲者反复强调:追不了很多射线,低端硬件可能比快硬件慢几个数量级(讲义 slide 10 备注)。由此引出两问,怎么把工作量压下去,以及能不能接近路径追踪的结果。同期他们持续跟进一批实用研究:DDGI [Majercik2019]、Surfels [Halen2021]、屏幕空间辐射缓存 [Wright2021]、ReSTIR GI [Ouyang2021] 等。备注补了这条前提的来路,2021 年做 DOOM Eternal 光追支持时就已看清新一代平台的能力边界。
方案总览收在一页上(讲义 slide 11)。一帧的次序是:更新光网格(light grid)、采样世界可见性、写世界辐射缓存(world radiance cache)、用上一帧结果更新辐照度体积、末级收集(final gather)、去噪(denoise)、上采样(upscale)。除这七步之外,半透明另有 froxel(视锥单元体)辐照度体积这一路。
备注对这七步逐条做了说明(讲义 slide 11 备注):先更新光照与着色需要的结构;再采样世界可见性并把采样结果缓存起来;然后把上一步的样本着色,存进世界辐射缓存;接着用上一帧的结果更新辐照度体积;末级收集这一步只索引各级缓存,不做着色;随后去噪;最后上采样。半透明那一路的用意他也交代了,不必为半透明再做一遍查表工作。
有一处限定要说清,这七步并不表示一帧里每一样都从头重算。备注在解释时给了两处关键约束,辐照度体积那一步消费的是上一帧的结果,末级收集只索引各级缓存、它的输入同样来自已经算好的缓存。这一帧真正新算的是可见性采样与随之而来的缓存更新,其余几步都在消费前面留下的结果。
备注还交代了这批研究的用法。2021 年动手时,这些工作看上去能在多个平台上用起来,团队把它们留作长期对照的坐标。
本章可核对的结论有三条。硬件光追在 idTech8 里被当作可见性工具使用,起点是 2021 年 6 月 DOOM Eternal 的 idTech7 光追更新;除 GI 之外它还用于材质查询、粒子碰撞、流送、网格生成与工具,讲义对这些只点名不展开(讲义 slide 10)。整篇的前提是追不了很多射线,低端硬件可能慢几个数量级,方向上要统一并简化既有系统(讲义 slide 10)。一帧的七步次序是更新光网格、采样世界可见性、写世界辐射缓存、更新辐照度体积、末级收集、去噪、上采样,半透明另走 froxel 辐照度体积,用意是不必为它再做一遍查表(讲义 slide 11)。
5用世界空间的级联光网格点亮 RT 世界
上一章把这一代的出发点定为把硬件光追当可见性工具,并给出一帧七步的总览,头一步是更新光网格(讲义 slide 11)。这一步要回答的是,进入 RT 世界的灯、探针与贴花怎么在帧内找到各自该照亮的单元。讲者的起手式是一套级联光网格(cascaded light grid),它在 DOOM Eternal 的光追更新里就已经引入(讲义 slide 12)。
这套结构与分箱(clustered binning)[Olson2012] 在精神上接近,落点却不同,分箱用的是绑在视锥上的划分,这里用的是世界空间的单元(cell),每个单元是一个 AABB。备注把改动的理由说得直接,tile 与 cluster 分箱都绑在视锥上,RT 世界里用不了;换成世界空间的单元之后,这套网格与相机摆在哪里无关。
网格按分层的办法铺开,16×16×16 的体积重复 8 级,级联之间按指数分布,于是近处密、远处疏。首级的边界是 32 米,每单元 2 立方米。每个单元最多装 64 个 id,id 分三类:灯用 16 位,反射探针(reflection probe)用 8 位,贴花用 16 位。id 本身并不存放数据,它是一张索引,拿到之后要到对应的数组里查出真正的索引。
网格的用途比灯更宽。它也被用在粒子与玻璃上,备注给的理由是,粒子按顶点着色时若用 cluster 分箱,顶点落在视锥外会带出伪影,世界空间的单元不吃这条约束,所以这一类按顶点分派的物品也归它管。这套结构在显存里约占 30 MB,备注交代了这笔占用的构成,大部分来自相机附近数量夸张的贴花(限 3 万)以及输入数组必须双缓冲这两件事。
点亮过程本身只有一次异步计算(async compute)dispatch(讲义 slide 13)。派发的 X、Y、Z 取网格分辨率除以 4,线程组大小是 4×4×4。整段走的是分层收集,先用 CPU 以位掩码标出 AABB 完全落在某个级联之内的物品,没有落进去的不进后面的处理。第一级是粗剔除,每个线程对应级联里的一个世界单元,单元尺寸取边界除以线程组尺寸,把与该单元重叠的灯、贴花与探针收进来,相叠的判定做在物品的 OBB 上,把单元的 AABB 变换到物品 OBB 的局部空间再与单位 AABB 比较。收集的结果写进 group shared memory 里的扁平位数组桶 [Drobot2017],每一种物品类型占一个桶,位数组保持有序,这一点对贴花与反射探针的预排序结果很重要。第二级是细剔除,单元尺寸改成边界除以网格分辨率,遍历扁平位数组再做一次 OBB 对 AABB,写出最终缓冲。
这一步的开销在页内给出,控制台上约 0.2 毫秒,PC 上约 0.1 毫秒;处理量还带着零售与开发两组上限,灯是 4k(零售)/8k(开发),贴花是 30k(零售)/54k(开发)(讲义 slide 13)。讲者在这一页的备注里自陈,就它处理的数据量而言这一步算快,但仍有改进空间,当时还有更大的硬仗要打。
这套结构有一套与分箱一样的局限(讲义 slide 14)。级联越远,体积越大,远处的 overdraw 随之增加。缓解的一条路是把级联分辨率提高,单元变细,浪费就少。团队实际测下来,16×16×16 的体积在内存与性能之间是个甜点,这是他们按自己的内容调出来的口径,未必通用。备注还补了一条容易被忽略的处理,光栅侧的角色用的是 light rig,那是美术与设计上为了让角色始终可见而做的安排,这类角色在 RT 世界里被跳过。
本章可核对的结论有三条。级联光网格用世界空间的单元(AABB)代替绑在视锥上的分箱,尺寸是 16×16×16 体积乘 8 级指数分布的级联,首级边界 32 米、每单元 2 立方米、每单元最多 64 个 id;三类 id 是灯 16 位、反射探针 8 位、贴花 16 位(讲义 slide 12)。这套网格也用于粒子与玻璃,因为按顶点着色的粒子在视锥外会出伪影;显存约占 30 MB,大部分来自相机附近限 3 万的贴花与输入数组的双缓冲(讲义 slide 12)。点亮由一次异步计算 dispatch 完成,含粗剔除与细剔除两级,控制台约 0.2 毫秒、PC 约 0.1 毫秒,灯的上限是 4k/8k、贴花是 30k/54k 两组零售与开发口径(讲义 slide 13)。局限是远处 overdraw 增加,可提高级联分辨率缓解,团队把 16×16×16 认作甜点,光栅侧用 light rig 的角色在 RT 世界被跳过(讲义 slide 14)。下一章看这些单元里的探针怎么被采样。
6采样世界:探针只追可见性
上一章把世界切成单元,并装好了灯、贴花与反射探针。七步里的第二步落在这套网格之上,采样的对象换成了辐照度体积(irradiance volume)里的探针(probe)(讲义 slide 11、15)。
被采样的体积分成两类。一类是级联辐照度体积,尺寸记作 16×16×16×6,也就是每层 16×16×16 的探针阵列铺 6 级级联,这一处与光网格的 8 级是两个不同的数字,读的时候不要串行。另一类是手工摆放的局部辐照度体积,尺寸 10×10×10,用于需要单独照顾的局部区域。级联体积的探针与光网格的单元同处世界空间,光网格负责把灯与探针分派到需要它们的单元,采样这一步在这些单元的探针上发射线。低配上级联会降到 12×12×12。采样的位置取单元中心,页内给出的射线定义也照这个起点写,射线起点等于探针位置即单元中心,终点是起点加上射线方向乘最大距离,这条最大距离划出一次查询要覆盖的范围。
更新是交错的,每帧只更新 1 个级联加 1 个体积(讲义 slide 15)。这类体积数量多,一次全刷不划算,交错把开销摊到多帧上,代价是任意一帧里只有一部分体积是新的。这一遍先只追可见性,每个探针每帧追 N 条可见性射线,N 取 64/32/16,按平台与设置来定。选这三档数字与前面的交错是配套的,每帧要刷的体积本就不多,探针上的射线数再按平台分档,整条采样路的帧预算才压得住。射线长度由最大距离封顶,查询开销因此可控。命中点在这里只交身份与位置,颜色留到后面去算,这一步的产出量只与射线数成正比。
命中记录是这一遍的产物(讲义 slide 16)。每次命中压进 128 位,分成四段,packedVbuffer0 里放 23 位的 SBT(着色器绑定表,Shader Binding Table)索引与 9 位的 primitiveID,packedVbuffer1 里放 24 位的 instance 索引与 8 位的 primitiveID,两段里的 primitiveID 合起来是 17 位;此外还有 barycentrics 与一个 float 的 hitDistance。四段各管一段信息:SBT 索引定位到要用的着色器与命中组,instance 索引定位到具体实例,primitiveID 定位到实例里的那个三角形,重心坐标给出落点在三角形内的位置,命中距离则给出这条射线走了多远,后面缓存做量化时要靠它定位。整份记录只描述打到了哪个三角形、在多远处,不含任何颜色。四段合起来是 128 位,正好装进两个 uint 加一个 uint 与一个 float,取用时按位段把各字段解出来即可。
每次命中还会触发世界辐射缓存(world radiance cache)的更新,这一步把产出的任务交给下一章那条流水线(讲义 slide 16)。把可见性与着色拆到两遍,是这一章最要紧的一处安排,采样这一遍只管射线的落点,成本因此压在射线查询本身;一次没打中的情况在这里不处理,交给后面去补一个替代值。
本章可核对的结论有三条。被采样的体积是级联辐照度体积与手工摆放的局部辐照度体积,前者记作 16×16×16×6、后者 10×10×10,低配级联降到 12×12×12,采样位置取单元中心(讲义 slide 15)。更新是交错的,每帧只更新 1 个级联加 1 个体积,这一遍只追可见性,每个探针每帧追 64/32/16 条射线,按平台与设置来定(讲义 slide 15)。每次命中把 128 位数据压成两个 uint 加一个重心坐标与一个命中距离,其中 SBT 索引 23 位、instance 索引 24 位,两段里的 primitiveID 合起来 17 位,并触发世界辐射缓存更新(讲义 slide 16)。下一章看这些命中在世界辐射缓存里怎么被登记与着色。
7世界辐射缓存:空间哈希与它的更新
上一章那 128 位的命中记录,落到世界辐射缓存里才变成可用的样本。这一章看这份缓存怎么存、怎么被点亮(讲义 slide 17)。
缓存用的是空间哈希(spatial hashing)[Gautron2020],结构是一条一维数组配一个多维哈希函数,用算出的哈希值去索引数组。位置上先做量化,粒度是 25 立方厘米的单元,并给单元配上 LOD,远处的单元可以更粗。这套缓存约占 14 MB。备注交代了选它的理由,简单,并且能把体数据紧凑地存进一条一维数组里。哈希函数可以对多个分量做,量化后的位置、到相机的距离(用来做 LOD)、时间、法线都行,用他的话说自己挑。哈希冲突会发生,处理办法是线性探查,往后面找 N 个元素来兜;他的原话带着一句半开玩笑的补充,但愿装得下,装不下就得丢结果。这条让步要跟着 14 MB 一起记,容量是有上限的,装超出容量的那部分样本只能被舍弃。
写入流程在下一页(讲义 slide 18)。每个命中先原子自增本帧活跃单元的计数,每个 dispatch 索引配一份计数与一份列表,而 dispatch 索引就是着色器索引,从 SBT 取。计数与列表按 dispatch 索引分开,是因为同一个 dispatch 里可能有多类着色器在写缓存,各自记各自的活跃名单才不会混。随后把活跃单元的哈希索引写在列表的最后一项,并在哈希索引处存下 rayID 与 probeID,供后面的步骤取回命中数据。页内给出的代码把这段写成几行,先按到相机的距离除以 LOD 距离常数取出 LOD,用它决定单元大小;再把位置量化成整数格点;然后逐级做哈希,得到哈希值后对缓存容量的上限取模,拿到哈希索引;最后用一次原子加把计数与列表写出去,并把打包好的射线数据写进该哈希索引处。备注给这一页的定位是示例代码,要深挖空间哈希与冲突处理,看 Gautron 2020 那篇。
缓存条目点亮在再下一页(讲义 slide 19)。活跃帧的计数被用来配置间接派发,每个着色器类型一次异步间接派发,着色器总数不到 10 个。取输入时用 rayID 加 probeID 再加命中数据,从 probeID 与 rayID 可以推出全局 rayID,再拿它去取打包的命中数据,命中数据里的 SBT 索引指向三角形数据,配合重心坐标就能取到所需的值;着色循环要访问光网格与无绑定资源,用的就是这些从命中包算出来的输入。光照与着色循环大体沿用光栅侧同一套代码,并可以借上一帧的辐照度体积做出多次弹射。规模上,每帧约 2 万个缓存条目被更新,这些结果可以复用 N 帧;缓存把结果留在原地跨帧使用,不必每帧把所有单元重新着色一遍。
本章可核对的结论有三条。世界辐射缓存用空间哈希存进一维数组,位置按 25 立方厘米量化并带单元 LOD,约 14 MB,选它的理由是简单与紧凑,哈希函数可对量化位置、相机距离、时间、法线等分量做(讲义 slide 17)。冲突靠线性探查往后找 N 个元素兜住,装不下就得丢结果(讲义 slide 17)。写入时每个命中原子自增本帧活跃单元计数,dispatch 索引即从 SBT 取的着色器索引,活跃单元的哈希索引写在列表末尾,rayID 与 probeID 存在哈希索引处;着色时用活跃计数配间接派发,每个着色器类型一次异步间接派发、着色器不到 10 个,光照循环大体与光栅侧同源,借上一帧辐照度体积做多次弹射,每帧约 2 万个条目更新、结果可复用 N 帧(讲义 slide 18、19)。下一章看这些条目怎么被辐照度体积取回,并一路走到每像素的末级收集。
8辐照度体积与末级收集
上一章把约 2 万个缓存条目点亮,这一章是它们被消费的地方,体积更新与末级收集(final gather)两步都在这一页组里(讲义 slide 20、21)。
体积更新是一次 compute dispatch,只处理本帧那些体积(讲义 slide 20)。线程组是 8×8,这一组正好对应最多 64 条 rayID,一个线程处理一条射线的结果。取结果时按 probeID 与 rayID 从世界辐射缓存里查,查不到就取天空的颜色当作命中值,先放进 group shared memory。随后按 [Greger1998] 的办法算出每个 texel 的辐照度,并把上一帧的结果累加进来,体积因此带一点时序上的延续,不必每帧从零重建。备注把查表的路线也交代了,从 probeID 与 rayID 能推出全局 rayID,交点等于探针中心加射线方向乘命中距离,用这个位置算出哈希再去查缓存。
存下来的形态是探针图集(讲义 slide 20)。投影用八面体映射(octahedral mapping)[Dachsbacher2008],把整个方向球摊进一张平面图块,存储方式与 DDGI [Majercik2019] 类似,颜色用 RGB9E5、可见性用 RG16F。图集的尺寸是 2560×1585,覆盖 6 个级联加最多 100 个局部体积,每个探针占一个 8×8 的 tile,带边界时是 10×10。这套图集占 64 MB,低配上 30 MB,更新一次的开销约 0.08 毫秒。备注解释了为什么挑八面体映射,它刚好能把一个探针铺进一个图块,查表简单,也省内存;探针图集把成千上万个探针收进一张贴图,取用时按 probeID 折算到图块坐标即可。
末级收集是每像素一条射线(讲义 slide 21)。方向按像素法线的半球做余弦加权,并用蓝噪声来做方向的抖动,避免同屏射线方向扎堆。分辨率跟着画质设置走,取 1/2 或 1/4。查表按三级依次回落,第一级是屏幕空间,看命中点是否落在视锥内且未被遮挡;第二级是世界辐射缓存,看这条射线的命中处有没有有效的缓存;前两级都不成,就回落到辐照度体积。三级回落的次序照顾的是可用性与成本,屏幕空间的信息最贴合当前画面,世界辐射缓存覆盖面更广,辐照度体积则随时在线,前两级都落空时它托底。这一步不做着色,只用缓存里的值,因此它的成本主要在查表与射线本身。
结果存成 2 波段球谐(spherical harmonics,SH)(讲义 slide 21)。写法是 3 张 RGBA16F,R 分量装 L0,GBA 三个分量装 L1;L0 给出与方向无关的底色,L1 补上一层方向感。这么存的用意很明确,他想像 lightmap 那样尽量保住法线贴图的细节,让光照的方向感在贴图细节上还能留下痕迹。落到语义上,每个像素在球谐空间里就是一个辐照度探针,末级收集因此把逐像素的间接光照变成了成千上万个探针的一次查询。
本章可核对的结论有三条。体积更新是一次 compute dispatch,只处理本帧体积,8×8 线程组对应最多 64 条 rayID,按 probeID 与 rayID 取缓存结果、查不到取天空,按 Greger 1998 算每个 texel 的辐照度并累加上一帧(讲义 slide 20)。结果存进八面体映射的探针图集,尺寸 2560×1585、覆盖 6 个级联加最多 100 个局部体积、每探针 8×8 tile(带边界 10×10),占 64 MB、低配 30 MB,更新约 0.08 毫秒(讲义 slide 20)。末级收集每像素一条射线,方向按像素法线半球余弦加权并用蓝噪声抖动,分辨率取 1/2 或 1/4,依次查屏幕空间、世界辐射缓存、最后回落到辐照度体积,不做着色,结果存成 2 波段 SH,每个像素在球谐空间里就是一个辐照度探针(讲义 slide 21)。下一章接上去噪与上采样,看这一条射线的结果怎么被补成一幅可看的画面。
9去噪、上采样与格式取舍
上一章收在末级收集(final gather)那一页上:每像素只发一条射线,结果存成 2 波段球谐(spherical harmonics / SH,球谐),于是每个像素在球谐空间里就是一个辐照度探针(讲义 slide 21)。一条射线的结果噪点很重,这一章看它怎么靠邻居、时针与上采样补出来,以及中间结果在 32 位上怎么选(讲义 slide 22 至 slide 25)。
去噪(denoise)与上采样(upscale)这一页把两件事的次序排得很清楚(讲义 slide 22)。空间去噪就在末级收集的那一档分辨率上做,用的形式是可分离的双边高斯(separable bilateral gaussian)。为了性能,数据先预载进 group shared memory,精度取 FP16。加权的依据有两路,一路是法线与深度的差 [Sloan2007][Yang2008],另一路是命中距离的差。前一路把落在同一表面上的邻居聚到一起,后一路照顾到射线打到远近不同物体的情况,两路合起来才决定一个邻居算多重。
讲者在这页备注里把「去噪」这个说法的底子挑明,它做的事是把邻居相似的采样结果摊开来,用来弥补采样数量的不足。他还补一句,这个双边高斯其实不可分离,采用可分离的形式只是为了性能;预载进 group shared memory 也是同一目的,邻居的读写都落在片上,省下反复访问显存的开销。这页的次序是去噪在前、上采样在后,两条都跑在末级收集的低分辨率结果上。
上采样这一步用 4 个泊松采样点(讲义 slide 22),权重同样按法线与深度来定。接在双边上采样之后的是时序滤波(temporal filter)[Mattausch2010],它维护一个有效帧计数,把像素的历史结果与当前结果按时钟加权。页内给出两行式子,加权后的结果写作 N^{t+1}_p = ( n_t^p · P_prev^p + Curr^{t+1}(p) ) / ( n_t^p + 1 ),计数本身按 n_{t+1}^p = min( n_t^p + 1, n_max ) 递推,计数封顶在 n_max,历史积累到上限之后,新结果与历史在加权里的分量就固定下来。讲者顺带交代一处容易被忽略的事,TAA 等在帧末还会再充当一层时序滤波,时序这一环在整帧里出现两次以上。
存储格式是本章的一处硬取舍(讲义 slide 22)。结果优先用 RGB9E5,前提是平台完整支持这个格式;不支持就退回 RGBA16F。R11G11B10F 被明确避开,讲义给的原因是这个格式会带色偏与条带,画面里也没有纯白。三档格式里被选中的两档都是 32 位,取舍点落在色彩还原这一头,与位宽无关。
画质分档在这页给出观感上的差别(讲义 slide 24)。高低两档并排看,结果相当接近,低画质那一侧略微软一点,丢掉了一部分有向光照的细节,原因是分辨率更低。这条判断挂在讲者自己这组画面上,属主观观感,本篇按他的原话记,不外推为通用结论。
格式对照另占一页(讲义 slide 25)。同一个画面上,RGB9E5 与 R11G11B10F 的差别落在三处,后者颜色往绿黄方向偏,画面里没有纯白,并带条带。讲者在备注里说条带可以用抖动掩盖一部分。他在这里停了一下,请求硬件厂今后都完整支持 RGB9E5,理由是想要精简的 32 位格式,而内存这些年涨得并不多。
本章可核对的结论有四条。去噪与上采样的次序是空间去噪在末级收集的分辨率上做、用可分离双边高斯并预载 FP16、权重按法线/深度差 [Sloan2007][Yang2008] 与命中距离差;上采样用 4 个泊松采样点、权重按法线/深度;时序滤波 [Mattausch2010] 带有效帧计数,计数按 n_{t+1}^p = min( n_t^p + 1, n_max ) 递推(讲义 slide 22)。存储优先 RGB9E5、不支持时退回 RGBA16F,R11G11B10F 因色偏与条带、没有纯白被避开(讲义 slide 22、25)。讲者自陈三处口径,去噪是把邻居相似结果摊开来弥补采样不足、双边高斯其实不可分离只为性能、TAA 在帧末还会再充当一层时序滤波(讲义 slide 22)。分步对照见讲义 slide 23,高低画质观感相当接近、低画质略软并丢掉部分有向光照细节(讲义 slide 24)。下一章转到间接镜面与半透明这两条支路。
10间接镜面与半透明:两条支路
上一章把单射线结果的补法讲完,去噪、上采样与时序滤波合起来把一条射线的结果撑到能看的画质(讲义 slide 22 至 slide 25)。这一章转到间接光里的另外两条支路,间接镜面与半透明(讲义 slide 26 至 slide 28)。
间接镜面这一路以反射探针(reflection probe)为底(讲义 slide 26)。这页第一句就把它与老办法的差别点出来,不必等 lightmap(光照贴图)烘焙,直接做就行。运行时的应用方式沿用了过去十来年的做法:BC6H 立方体贴图数组,不透明表面按 tile 分箱,半透明走 cluster 分箱或光网格(备注)。第 3 章那套辐照度体积与反射探针的老流程在这里被接了过来,次序上少掉等待烘焙这一环,探针数据因此能和光照改动一起跟上,不必等一整轮重烘。
探针的烘焙是他们自己写的。讲者说他们弃用了 AMD 的 Cubemap Gen,为烘焙性能重新实现了一遍,做法有两点,GGX 过滤,以及按 tile 的多线程。这段替换换来的是烘焙时间上的余地,具体数值讲义未给该口径。
探针结果还要按 [Lazarov2013][Hobson2019] 重拟合到环境(讲义 slide 26)。页内给出的关系式是 反射 =(反射/探针辐照度)× 帧辐照度,备注补一句,他们这里把帧辐照度当作探针辐照度的替代项。重拟合换来的好处是局部细节更好,角落不再发光,也能拾取反弹颜色。讲义只给到这条关系式,推导未给,本篇也不补。
这一路与 idTech7 几乎相同(讲义 slide 27)。顺序是能用屏幕空间反射(SSR)就先用它,然后才走光追,再按光滑度回落到探针。光追那一支有自己的时序上采样,上采样分辨率随画质设置分为 1/2 与 1/4 两档。这一段的形状与前一页的探针配套,探针在最外层兜底,屏幕空间与光追是更靠前的两级。
让步在这页写得最直白,这一支最终在控制台上因性能关掉了。讲义给的口径一并记下,它通常还挺快,约 2 毫秒;团队没时间继续优化;另外按最小光滑度做了阈值,只在很光滑的表面上跑;也没时间做更复杂的 BRDF。备注再补一句,屏幕空间加探针本来就是后备计划,光追这一支属于在这之上去争取的可选项,关掉它并不动摇前面那一整套。
半透明走的是另一条路,用 froxel(视锥单元体)辐照度体积(讲义 slide 28)。体积雾 [Wronski2014] 本来就要用辐照度体积,于是把这份现成的工作分享给所有半透明,不必再为半透明重做一遍查表。这份体积在光散射的 froxel dispatch 时写入,用 2 波段 SH 编码,占 50 MB,低配 25 MB,用于粒子、玻璃等。重拟合时,他们把这个 froxel 辐照度体积当作探针辐照度的替代项(备注)。半透明这一路因此不再新增一套查表结构,它搭在体积雾已经算过的那份结果上。
本章可核对的结论有四条。间接镜面以反射探针为底,不必等 lightmap 烘焙,存成 BC6H 立方体贴图数组,不透明按 tile 分箱、半透明走 cluster 或光网格;团队弃用 AMD 的 Cubemap Gen 后为烘焙性能重写(GGX 过滤、按 tile 多线程),并按 [Lazarov2013][Hobson2019] 重拟合到环境,页内关系式为 反射 =(反射/探针辐照度)× 帧辐照度(讲义 slide 26)。镜面这一支与 idTech7 几乎相同,顺序是屏幕空间优先、再走光追、按光滑度回落到探针,最终在控制台上因性能关掉,撑住它的口径是约 2 毫秒、没时间继续优化、按最小光滑度做阈值、也没时间做更复杂的 BRDF(讲义 slide 27)。半透明用 froxel 辐照度体积,沿用体积雾 [Wronski2014] 的辐照度体积并分享给所有半透明,在光散射 dispatch 时写入、2 波段 SH 编码、50 MB(低配 25 MB)(讲义 slide 28)。下一章看高频细节怎么补回来,以及整条管线在一个指定场景里的账。
11合成、热点性能与那处自陈
上一章把间接镜面与半透明两条支路交代完,光照的各个部分到这一章只剩合成这一步把高频细节补回来(讲义 slide 29)。随后讲者把整条管线在一个指定场景里的账摊开,也在这页留下了一处对自己的更正(讲义 slide 31)。
合成靠的是方向遮蔽(directional occlusion)[Landis2002][Ritschel2009],用它把高频细节补回画面(讲义 slide 29)。需要它,是因为 BLAS(底层加速结构)里并没有装下全部几何,上层 LOD 的细节也不在其中。具体做法用 POM(视差遮蔽贴图)[Tatarchuk2005] 给每个光源做接触阴影,另外做镜面遮蔽,做法是沿半球做 ray-march,存下平均未被遮挡的方向。补完这一层再去噪,加时序滤波 [Mattausch2010]。备注把这页的作用说得直接,这块把 BLAS 里缺失几何造成的高频细节补回来,方向遮蔽在这一步承担的是拾遗的角色。
合成开与关的对照另占一页(讲义 slide 30)。对照落在做了视差遮蔽贴图的表面上,备注只有一句,指明比的就是这块表面。讲义该页没有对应插图取出,本篇只记它给出的是一组开与关的并排,不虚构画面。
热点性能表是这一章最重的一页(讲义 slide 31)。场景是游戏里一个常见热点,mission 4 的大远景,敌人、植被、粒子都多;表里的数值是他们发货时的那一套。表按五个平台排开,分别是 Xbox Series S(900p)、Xbox Series X(1440p)、PS5(1440p)、PS5 Pro(1800p)与一台 PC(4k),每个平台分成六个阶段,依次是采样世界、辐射缓存、辐照度体积、末级收集、去噪、上采样。
两行合计是最先该看的。串行合计落在约 1.7 到 2.11 毫秒之间,改成异步计算(async compute)之后落到约 1.4 到 1.82 毫秒之间;异步那一行在 PC 上标的是 NA。按平台分读,Series S 的串行合计约 2.11 毫秒、异步之后约 1.71 毫秒;Series X 约 1.9 与约 1.4 毫秒;PS5 约 2.05 与约 1.55 毫秒;PS5 Pro 约 1.923 与约 1.82 毫秒;PC 的串行合计约 1.7 毫秒。六个阶段的逐项值讲义都列在表里,本篇按幻灯文本与备注原值记,不做换算,也不把这两行之外的口径补全。这六个阶段与第 4 章那页总览里的步骤对得上,更新光网格那一步不在表内,它另有约 0.2 毫秒(控制台)、约 0.1 毫秒(PC)的读数(讲义 slide 11、slide 13)。
备注给出的可比对结论有几条。控制台之间相当接近;Series X 略快,原因是它多 20% 的 TFLOPS,约 12 对约 10;这台 PC 上装的是 4080,算力大约是控制台的 4 倍。异步在 Series X 与 PS5 上省了约 0.5 毫秒,Series S 上约 0.4 毫秒;PS5 Pro 上省得少,因为它那几个异步 dispatch 本身就跑得快。团队把异步的活塞得很满,尽量让 GPU 保持忙碌,按他们的判断,没有异步就达不到性能目标。
这页还有一处讲者主动交代的更正,必须一并记下(讲义 slide 31)。他说几周前在 CEDEC 2025 讲同一份材料时,画面对照做错了一处,没有比较同一组正在更新的级联与体积,性能因此会有波动;SIGGRAPH 这一版把这一点修正了,也为了完整补上了更多平台。这句自陈限定的是画面对照的可比性,与表里那两行合计是两件事,读的时候要分开。
本章可核对的结论有四条。合成用方向遮蔽 [Landis2002][Ritschel2009] 补高频细节,起因是 BLAS 里没有全部几何与上层 LOD 细节;做法用 POM [Tatarchuk2005] 做每个光源的接触阴影与镜面遮蔽,沿半球 ray-march 后存平均未被遮挡方向,再做去噪加时序滤波(讲义 slide 29)。合成开与关的对照落在视差遮蔽贴图表面上(讲义 slide 30)。热点性能表的场景是 mission 4 大远景、多敌人植被粒子,五档平台各标了分辨率,六阶段逐项列出,串行合计约 1.7 到 2.11 毫秒、异步之后约 1.4 到 1.82 毫秒,异步在 Series X 与 PS5 上省约 0.5 毫秒、Series S 约 0.4 毫秒、PS5 Pro 上省得少,Series X 略快因多 20% 的 TFLOPS,PC 那台 4080 约控制台 4 倍,团队认为没有异步达不到性能目标(讲义 slide 31)。同一页记下讲者的自陈更正,CEDEC 2025 那次的画面对照没有比较同一组正在更新的级联与体积、性能会有波动,SIGGRAPH 版已修正并补了平台(讲义 slide 31)。下一章收结果与未竟。
12结果与未竟
上一章把整条管线在指定场景里的账摊开,也把讲者那处更正写在明面上(讲义 slide 31)。收尾这一段讲结果,再把这套方案的未竟项与前提一并交代(讲义 slide 32 至 slide 37)。
结果这一页给的是收益清单(讲义 slide 32)。第一笔是量级上的节省,讲者的说法是从小时降到毫秒。第二笔是 0 磁盘占用,老办法那套按关卡体积累加的磁盘与网络账随之消失。第三笔是美术拿到即时反馈,关卡尺寸上因此更自由、限制更少。第四笔是光照结果更一致,静态、动态与半透明各类表面都算在内。第五笔是代码路径更统一、更少。
后面几页是收束与出处(讲义 slide 33 至 slide 35)。致谢页列了 id Software 的同事与美术团队、Natalya Tatarchuk,以及玩家,本篇只记出处。再往后是讲者的联系方式与提问页,同样只记页码与用途。
最后两页是参考文献(讲义 slide 36、slide 37)。它们列的是学术出处,构成这场的引用底子。与 GI 直接相关的包括 [Majercik2019] 的 DDGI、[Halen2021] 的 Surfels、[Wright2021] 的辐射缓存、[Ouyang2021] 的 ReSTIR GI,配套的还有 [Gautron2020] 的空间哈希、[Geffroy2020] 的 DOOM Eternal、[O'Donnell2018] 的 Frostbite 预计算 GI、[Drobot2017] 的分箱剔除、[Sousa2016] 的 idTech 细节、[Wronski2014] 的刺客信条 4、[Lazarov2013] 的黑色行动 2、[Olson2012] 的 cluster 着色、[Mattausch2010] 的时序相干 SSAO,以及 [Vahl2025] 的 60 Hz 与夺宝奇兵。另一页收了探针与环境映射一端的老出处,包括 [Czuba2010]、[Mittring2009]、[Ritschel2009]、[Dachsbacher2008]、[Sloan2007]、[Tatarchuk2005]、[Landis2002]、[Ramamoorthi2001]、[Greger1998]、[Ward1988],外加 SBT 与 Oodle Kraken 两条链接。这些论文各自写了什么,本篇不展开,只把它们记作出处。
本章可核对的结论有两条。结果页给出的五笔收益是量级上的节省(从小时降到毫秒)、0 磁盘占用、美术即时反馈、各类表面光照更一致、代码路径更统一更少(讲义 slide 32)。收尾的几页分别是致谢、联系方式与提问页(讲义 slide 33 至 slide 35),以及两页只作出处的参考文献(讲义 slide 36、slide 37)。这场的读数与口径边界,按顺序收在下面八条里。
边界 1:三类读数不可混。 讲义 slide 6 的 DOOM Eternal 统计与「大图 40 小时」是上一代产品的实测;讲义 slide 9 明标 Rough estimate,问的是「如果照搬老办法」,属假设推算;讲义 slide 31 的热点表是本代在指定场景与平台上的实测、发货值。引讲义 slide 9 时不得写成实测。
边界 2:p31 的口径与那处自陈。 该页场景为 mission 4 大远景(多敌人/植被/粒子),各平台跑在 boost 时钟上;讲者自陈几周前在 CEDEC 2025 讲同一份材料时,画面对照没有比较同一组正在更新的级联与体积、性能会有波动,SIGGRAPH 版已修正并补了平台。
边界 3:内存读数逐项带条件。 级联光网格约 30 MB(大部分来自相机附近限 3 万的贴花与输入数组双缓冲,讲义 slide 12)、空间哈希缓存约 14 MB(讲义 slide 17)、探针图集 64 MB/低配 30 MB(讲义 slide 20)、froxel 体积 50 MB/低配 25 MB(讲义 slide 28);低配口径不逐项相同,不可互相套用。
边界 4:未竟项与前提。 间接镜面的光追这一支在控制台上因性能被关掉(约 2 毫秒、没时间继续优化、也没时间做更复杂 BRDF,讲义 slide 27);整篇前提是追不了很多射线(低端硬件可能慢几个数量级,讲义 slide 10);哈希冲突靠线性探查、装不下就得丢结果(讲义 slide 17 备注)。
边界 5:与篇目 10(MegaLights)不可直接横比。 两篇是同一问题的两家竞争方案,厂商、硬件、场景与帧预算都不同,只能逐项对齐条件之后对读。
边界 6:页内表格行列未经人工核对。 讲义 slide 31(五平台 × 六阶段 + 两行合计)、讲义 slide 9(估算表)、讲义 slide 6(DOOM Eternal 统计)都是页内文本,正文只引幻灯文本与备注明确给出的数值,不确定处写「讲义未给该行的完整口径」。
边界 7:讲者自陈的经验值。 16×16×16 是团队在内存与性能上的甜点(讲义 slide 14 备注)、光栅侧角色用 light rig 而在 RT 世界被跳过(讲义 slide 14 备注)、「双边上采样其实不可分离、只为性能」与「TAA 会再充当一层时序滤波」(讲义 slide 22 备注),都是按他们自己的内容调出的口径,属经验值,不能当通用最优套用。
边界 8:边界之外。 讲义 slide 36 与 slide 37 两页参考文献只作出处、本篇不展开其内容;本篇未给数学推导(重拟合只给页内关系式);讲义未给代码仓库或开源链接。
13贡献块
三条可搬走的做法与站内互读
一场讲「为了让 GI 撑住更大的世界而把整套预计算换掉」的讲座,能留下的东西集中在三处:把分箱从视锥搬到世界空间、把更新摊到帧内并用哈希缓存兜住、以及把「一致性」本身当成设计目标。三处都没有新数学,用的是把已有零件重新排布到能满足四笔约束的位置上这件事本身;本篇因此更适合当作一份从离线预计算转向帧内计算的工程路线记录来读。
贡献 1:把分箱从视锥搬到世界空间。 tile/cluster 分箱绑在视锥上,在 RT 世界里用不了(讲义 slide 12 备注),于是做成级联光网格:世界空间 AABB 单元、16×16×16 × 8 级联按指数分布、每单元最多 64 个 id,而 id 分三类(灯 16 位、反射探针 8 位、贴花 16 位,讲义 slide 12)。它的构造是这样的:先用 CPU 位掩码标出哪些物品完全落在某个级联内,GPU 那一步就跳过不在本级的物品,再分粗/细两级把重叠关系收进 group shared memory 的扁平位数组桶 [Drobot2017],最后写出缓冲(讲义 slide 13)。这套结构同时服务灯、反射探针、贴花,以及粒子与玻璃(用 cluster 分箱处理粒子会因视锥外顶点出伪影),代价约 30 MB、点亮约 0.2 毫秒(控制台)。
贡献 2:把更新摊到帧内,再用哈希缓存兜住。 老办法靠离线烘焙把结果算好;这一代把它拆成「每帧只更新一小块」的时序账:采样环节每帧只更新 1 个级联加 1 个体积、每个探针只追 64/32/16 条可见性射线,而且这一遍只追可见性(讲义 slide 15);命中记录压进 128 位(讲义 slide 16),写进用空间哈希组织的一维缓存(25 立方厘米量化带单元 LOD、约 14 MB,讲义 slide 17),并按活跃列表在下一遍着色(每帧约 2 万条、结果可复用 N 帧,讲义 slide 19);末级收集再按屏幕空间、世界辐射缓存、辐照度体积三级依次回落(讲义 slide 21)。可搬的是这套「先只追可见性、把着色与重建放到后面几步」的分工,它让预处理从小时级压到帧内。
贡献 3:把一致性当成设计目标。 收益一页写的五条里,有三条讲的是统一:各类表面(静态/动态/半透明)光照结果更一致、代码路径更统一也更少、以及0 磁盘占用与美术即时反馈(讲义 slide 32)。半透明那一路最能说明这层意思 —— 体积雾 [Wronski2014] 本来就有辐照度体积,于是把它分享给所有半透明,在光散射 dispatch 时顺手写入(50 MB/低配 25 MB,讲义 slide 28),这就省掉了「为半透明再做一遍查表」的重复工作。
站内可以接着读的几篇:篇目 11(DDGI)是本篇的直系先声 —— 讲义 slide 20 明说辐照度体积的存储方式与 DDGI 类似(八面体探针图集 + 可见性),而 slide 10 也把 DDGI 列为团队长期跟进的第一项研究,两篇连起来看正好是「探针场怎么做」到「探针场怎么在帧内更新」的一段。篇目 10(MegaLights)与本篇是同一问题的两家竞争方案(大规模随机直接光/GI),但厂商、硬件与场景都不同,两篇的读数不可直接横比,只能逐项对齐条件后对读。篇目 34(Neural Light Grid)与本篇恰是辐照度体积的两条换代路线 —— 前者把预计算里最贵的那一层现代化(用一组学出来的权重函数替掉固定三线性核),本篇索性把预计算整套搬到帧内、用空间哈希缓存与交错更新撑住。本篇讲义 p36/p37 两页列了完整参考文献([Greger1998]、[Ward1988]、[Majercik2019]、[Gautron2020]、[Drobot2017]、[Ouyang2021]、[Halen2021]、[Wright2021] 等),是学术出处,全篇未给代码仓库或开源链接。
14原文出处块
原文出处与引用口径
出处:SIGGRAPH 2025 · Advances in Real-Time Rendering in Games(Part II)· 2025-08-12 · 讲者 Tiago Sousa(Rendering Technical Director, id Software)· 官方讲义《Fast as Hell: idTech8 Global Illumination》,38 页,576×756 pt(竖版),来源 PDF 2026-siggraph-advances-idtech8-gi.pdf
材料:官方讲义 38 页,其中 29 页带讲者备注(合计约 0.92 万字符);幻灯区有实时文本层(37/38 页的要点、伪代码与数值表都可选),本篇事实同时取自幻灯文本与讲者备注;页码为 PDF 页序(从 0 起),引用写作「讲义 slide N」
许可:幻灯区有文本层,逐页检索未检到 © / Copyright / Creative Commons / CC BY / MIT / License 任何声明(页脚位置为课程名 Advances in Real-Time Rendering in Games course),亦未检到代码仓库或开源链接。故 22 件图按分区非 CC 口径逐件署名(图号 + slide 号 + 出处 + 「未修改引用」),并在构建记录标注残留风险(讲义未授权转载,条款以官方发布为准),不得写成 CC 或可自由转载;讲义 slide 36/37 的参考文献为学术出处,不是代码许可
引用口径:三类读数不可混 —— ①上一代实测:DOOM Eternal 的最终质量烘焙 ≥4 到 10 小时、全图约 4 天周转、单关约 500 MB(压缩,未压缩约 5 GB)、网络存储约 1.4 TB,且「大图烘焙 40 小时、最后砍到 1/2 分辨率」出自 idTech7 的实测(讲义 slide 6);②假设推算:讲义 slide 9 明标 Rough estimate,问的是「如果 DOOM The Dark Ages 照搬老办法」,给出单关预处理 16–100 小时、单关 2–5 GB、磁盘 44–110 GB、网络存储 9.5–24 TB、周期 27–68 天 —— 这是推算,不得写成实测;③本代实测:讲义 slide 31 的热点表是发货值,场景为 mission 4 的大远景(多敌人、植被与粒子),覆盖 Xbox Series S 900p、Series X 1440p、PS5 1440p、PS5 Pro 1800p、PC 4k 五档,六阶段之和在串行约 1.7–2.11 毫秒、async 后约 1.4–1.82 毫秒,其中 async 在 Series X 与 PS5 上省约 0.5 毫秒、Series S 约 0.4 毫秒,PC 那台是 4080(约控制台 4 倍 TFLOPS)。讲者自陈的一处更正一并保留:CEDEC 2025 讲同一份材料时,画面对照没有比较同一组正在更新的级联与体积,性能会有波动,SIGGRAPH 版修正了这点并补了平台。内存读数逐项带条件:级联光网格约 30 MB(其中大部分来自相机附近限 3 万的贴花与输入数组双缓冲,讲义 slide 12)、空间哈希缓存约 14 MB(讲义 slide 17)、探针图集 64 MB/低配 30 MB(讲义 slide 20)、froxel 体积 50 MB/低配 25 MB(讲义 slide 28)。未竟与让步同样保留:间接镜面的光追这一支在控制台上因性能被关掉(约 2 毫秒,没时间继续优化,也没时间做更复杂的 BRDF,讲义 slide 27);整篇的前提是追不了很多射线(低端硬件可能慢几个数量级,讲义 slide 10);哈希冲突靠线性探查兜住,装不下就得丢结果(讲义 slide 17 备注)。不与任何商用方案横比:本篇与篇目 10(MegaLights,Epic)是同一问题的两家竞争方案,两篇读数不可直接横比。篇幅说明:本篇为本批文字量最厚的一篇(幻灯区有文本层且 29 页带备注),正文按 15,000–20,000 汉字写,事实全部来自幻灯文本与备注。