"ADAPTIVE VOXEL-BASED ORDER INDEPENDENT TRANSPARENCY MICHAL DROBOT"
- 问题是一句 alpha blend 的性质:游戏里的透明就是玻璃、VFX 网格与 VFX 卡片,按任意顺序画都不对,更糟的是每帧换顺序会闪,因为 alpha blend 与顺序相关(讲义 slide 8);参考解是对每个事件按背到前顺序渲染、逐像素解一条含透射率积分的合成方程(讲义 slide 9)。
- 既有解族各有取舍:精确解能算对但代价高(链表、depth peel、有界 A/K 缓冲,内存不够就回退近似),随机解靠抖动加超采样收敛,加权混合把方程改写成加权分量 —— 先算透射率积分,再按任意顺序合成(讲义 slide 10–19)。
- 生产现实是手工排序:排序手工指定在发射器、材质、网格三层,实际在 CPU 上排,人力密集且有时根本不奏效(讲义 slide 21、22);BO4 上过九层 A-buffer,能精确排序,代价是相对非 OIT 的 2.5 倍以上性能开销(讲义 slide 23、24)。
- 两条不变性把既有方案筛掉:MBOIT 不具深度复杂度不变性,烟里会漏出本该完全被遮挡的角色(讲义 slide 32);WBOIT 复杂度不变性更好,却不具位移不变性,相机稍动就振铃(讲义 slide 42)。于是「复杂度不变」与「位移不变」被立成设计目标(讲义 slide 44)。
- 做法是一次技术迁徙:体渲染早就用体素化空气密度沿眼射线积分透射率,产出透射率积分的三维查找表(讲义 slide 46)。VBOIT 把这套搬过来 —— 拟合深度分布曲线、清空体积消光缓冲、把事件样条进去(讲义 slide 47、48),再用 8 位打包的原子累加把这一步做便宜(讲义 slide 53–59)。
- 自适应是失效推出来的:事件落在同一片内会过度或不足遮挡,单片内退化为加权混合(讲义 slide 85);既然缓冲本就稀疏、且 VBOIT 在切片之间是移位不变的,就用一张深度扭曲查找表把空空间从深度轴上压掉,把切片花在该花的地方(讲义 slide 93、94)。
- 口径要一起搬走:p105 的性能表按「基线带宽吞吐拉满」的假定算,不是中立对照;所有读数绑定 PS5、1080p、1700 万像素 overdraw、透射率预通道 1/8 分辨率;p24 的 2.5 倍是 BO4 那一代的历史成本(讲义 slide 24、52、98、105)。
1「按顺序画才对」为什么在游戏里这么难
「按顺序画才对」为什么在游戏里这么难
讲义 slide 1 只放一个分节标题 INTRODUCTION,是全篇的分节骨架页,没有正文与插图。这一章要立起后面各章都绕着转的那个麻烦:透明面按什么顺序画,画面就对不上,而顺序每一帧都在换。
先给「游戏里的透明」划范围(讲义 slide 8)。这一页把平时叫透明的东西收成三类:玻璃(glass)、VFX 网格(VFX meshes)与 VFX 卡片(VFX cards)。玻璃是几何,VFX 网格是带透明材质的模型,卡片是朝向相机的片。它们共同的性质是同一像素上会叠不止一个半透明事件,也就是同一像素被反复写入的次数,本篇统一叫过度绘制(overdraw)。
讲者备注把这一页说得很直白:渲染透明不是小事,游戏里的透明通常出现在特效与玻璃上,把那些面按任意顺序画都不对;更糟的是每帧换一次顺序会带来闪烁与瑕疵,因为 alpha blend 与顺序相关(讲义 slide 8)。
正确画法摆在讲义 slide 9。这一页给的参考解叫画家算法(Painter's Algorithm):把 N 个事件按从背到前的顺序逐个渲染;每个像素都要解一条合成方程;用物理的话说,这是拿透射率积分(transmittance integral)去解一次合成。公式在 PDF 里抽成散乱字形,按页面标注能读出它的结构:第一个事件写成事件颜色加背景色乘 (1 − α₁);推广到第 i 个事件,事件贡献外面套一段连乘,连乘项是该事件之后所有事件的 (1 − αj),页面把这串连乘标成「第 i 个事件的透射率积分」。透射率(transmittance)在这里指光走到某处还剩多少的比例,它沿深度方向被每个事件按 (1 − α) 不断打折。
把讲义 slide 8 与 slide 9 并起来,本章的账就清楚了。顺序之所以是硬约束,在于合成方程的连乘项依赖哪些事件排在这个事件之后;画家算法要求背到前,等于要求每帧掌握全部透明事件的深度关系并严格照它画。要做到这件事,先得知道每个像素上有几个事件、分别在什么深度,而这个变量在游戏渲染里最先失控。想绕开严格次序、又让画面与顺序无关,这个目标有个名字,顺序无关透明(order-independent transparency,OIT);本篇讲的就是按这条目标重做的一层。这条要求把透明从一个材质标签改写成一次沿深度累积的运算,后面所有机制都在补这次累积。
本章可核对的结论有三条。游戏里的透明主要是玻璃、VFX 网格与 VFX 卡片三类,同一像素会被多个事件反复写入(讲义 slide 8)。alpha blend 与顺序相关,按任意顺序画都不对,每帧换顺序会闪(讲义 slide 8)。参考解是画家算法式的从背到前逐事件合成,逐像素解一条带透射率积分的合成方程(讲义 slide 9)。这套要求直接引出下一章:同一个合成方程,业界给出了哪几条路,各自的代价又在哪。
2一条方程引出的三类解法
上一章把压力落在合成方程上:连乘项绑定事件的先后关系。这一章沿同一条方程往下走,看业界给答案时分成几条路(讲义 slide 10 到 slide 19)。
先看精确解这一支(讲义 slide 10)。页面标题是 EXACT SOLUTIONS,路线有两条:在 CPU 上做背到前排序,这条只适用于不重叠的几何;要通用就得先捕获全部事件再排序,做法有链表(Linked Lists)、深度剥离(Depth Peel)、有界 A/K 缓冲(Bounded A/K buffers),内存不够时回退到近似解。这一页给的利是精确,弊是带宽高、复杂度高、内存占用高,并且需要同步原语(synchronization primitives)。
第二条是随机解(讲义 slide 11)。做法是按像素透明度做随机抖动(stochastic dither)光栅化,再做空间与时间上的超采样,随采样数收敛到解,页面注明游戏里常用。这一路的利是便宜,弊是情景依赖(situational)。
第三条是加权混合(讲义 slide 12)。页面把它写成把方程改写成加权分量、再归一化求和,结果收敛到参考解。公式同样抽得散乱,能读出的结构是:分子把各事件颜色乘一个权重后求和,分母把各事件的 α 乘同一个权重后求和(页面标为归一化因子),再加背景色乘各 (1 − αi) 的连乘;页面把权重标成到该事件为止的积分透射率,并注出它近似的是该事件之后各 (1 − αj) 的连乘。
这套改写落到管线上分两步(讲义 slide 13、slide 14)。渲染侧(讲义 slide 13)给三张渲染目标:MRT0 存颜色乘权重,MRT1 存 α 乘权重,MRT2 存 −log(1 − α),三张都是 11R11G10B Float、用 Add 混合。页面顺带说明 MRT2 为什么用 −log(1 − α):连乘换成指数里求和,从 alpha 挪到消光(extinction),好对上体渲染的记号。解析侧(讲义 slide 14)是一次全屏解析:分子项乘上 1 减去透射率,再除以 MRT1,背景色另乘透射率后相加。
讲义 slide 15 把这一族的定位说清:把 over blend 这个算子换成与顺序无关的算子,页面列了加权求和、加权平均与加权混合 OIT(Weighted Blended OIT)三支,并注出游戏里最常见的就是加权混合,后续改进见 [KIR18],权重是临场取的经验值,可以按深度或亮度构造。这一页的利是复杂度低、带宽低、内存占用低,弊写得更重:频率混杂(frequency soup)、难调、以及难以表示遮挡。
第三条路往下再分出一支,走的是透射率积分(讲义 slide 16、slide 17、slide 18)。讲义 slide 16 的构造函数一节列出用于近似沿深度的透射率的几类函数:指数、统计、DCT、分段;做法是把所有透射事件投影上去,得到函数系数,全部透明面在预通道里画一遍,这一层可以降分辨率。讲义 slide 17 给出投影与重建两侧:投影是把各事件的透射率投影累加到函数基上,系数按像素存;重建是在深度 Z 上取累加系数求值,权重记作 T(z, c0, c1, …, cn)。讲义 slide 18 把它收成两趟:一趟算透射率积分,一趟按任意顺序、用预积分的透射率画透明;页内把近似透射率积分的几条支线列全,透射率函数映射(Transmittance Function Mapping,[DEL11])、矩的顺序无关透明(Moment-Based OIT,MBOIT,[PMWK17])、小波顺序无关透明(Wavelet-Based OIT,WBOIT,[ASM21]),以及体素的顺序无关透明(Voxel-Based OIT)。
这一路线的取舍集中在讲义 slide 19,也就是本章配图这一页。利有四条:复杂度中等,带宽低到中,内存占用低到中,而且事件的渲染分辨率可以与透射率的分辨率分开。弊这一列在抽取时有截断,能读出的条目是近似、取舍各不相同,另有一条讲沿深度的平滑与正确性、一条讲遮挡处理棘手;被截断处按讲义未给该条目的完整口径处理,不做补全。
本章可核对的结论有三条。精确解靠 CPU 排序、链表、深度剥离与有界 A/K 缓冲,代价是带宽、内存、复杂度与同步(讲义 slide 10);随机解靠抖动光栅加时空超采样,便宜但情景依赖(讲义 slide 11);加权混合把合成改写成加权分量再归一化,三张 MRT 加一次全屏解析,代价含频率混杂与难调(讲义 slide 12 到 slide 15)。透射率积分这一支把权重换成一条沿深度预积分的透射率,允许事件渲染分辨率与透射率分辨率分开(讲义 slide 16 到 slide 19)。下一章离开纸面,回到引擎现状。
3引擎现状:手工排序,与 BO4 的九层 A-buffer
上一章把三条路的取舍摆开,这一章换到生产现场。Call of Duty 的这段经历由讲义 slide 20 的分节页 OIT JOURNEY IN CALL OF DUTY 起头,接下来几页讲的是现行做法、它的翻车现场,以及 Treyarch 在 Black Ops 4 上做过的一次尝试(讲义 slide 21 到 slide 24)。
先看现行技术(讲义 slide 21)。排序是手工指定的,分在发射器(emitters)、材质(materials)、网格(meshes)三层;实际排序跑在 CPU 上;发射器之间允许排序,页面把 CPU 与 GPU 两处都列了出来;此外还支持 Blend Add RGB 模式,依赖硬件双 blend(hardware dual blend)。这一页给的利是快,且没有内存开销,附带提到一个专为剔除光斑用的 8 位累积 alpha 缓冲。
这条路的账付在哪里,讲义 slide 22 用一页失败案例回答。页面只列了两条弊:人力密集(labor intensive),以及有时根本不奏效(sometimes doesn't work)。
排不动顺序时上硬件是一条出路,Treyarch 在 Black Ops 4 上的方案就是这一支(讲义 slide 23、slide 24,引 [KOH16])。讲义 slide 23 讲机制:做精确排序,用的是 9 层 A 缓冲(A-buffer,A 缓冲);网格用 UAV 光栅化,回退时并入一层;VFX 走软件光栅再在 compute 作业里解析;排序与解析都在这个 A 缓冲上做;顺带为别的媒介合成生成一层自适应透明的 OIT 结构(引 [SAL11]);页面明确列出一条限制,不支持显式的排序指定。同页还给了一张逐层结构表,两列分别是单色与 RGB,能读到的行目是 9 x 颜色、9 x 透射率、9 x 深度、1 x 同步计数器,另有每像素位数合计与 4K 下的内存两行;表格在 PDF 里抽成散块,行标签与数值的对应关系未经人工过图核对,正文只引用能够自洽对齐的部分,其中每像素位数合计一行读出 512 与 728,4K 内存一行读出约 530MB 与约 754MB,其余单元格(含带宽行)按讲义未给该行的完整口径处理。
讲义 slide 24 是这一支的利弊总账。利有两条:已发货,且在该内容下溢出并不明显(原页写作 overflows not apparent <w/ that content>)。弊这一列更长:相对非 OIT 有 2.5 倍以上的重性能开销(原页标为 current);软件光栅路径需要大量维护;更现代的 VFX 少用朝向相机的卡片,迫使 A 缓冲更频繁溢出、成本更高;对多分辨率没有简单支持;4K 与 RGB 下内存与性能都不划算。这里的 2.5 倍以上要按口径读:它是 Black Ops 4(2018)那一代的历史成本,属于既有方案的故事,不能拿去当本篇方法的对照。
本章可核对的结论有三条。现行做法把排序手工指定在发射器、材质、网格三层,实排跑在 CPU 上,支持发射器之间排序与 Blend Add RGB(讲义 slide 21)。手工与 CPU 排序的两条弊是人力密集与有时根本不奏效(讲义 slide 22)。Black Ops 4 用九层 A 缓冲做精确排序,网格走 UAV 光栅、VFX 走软件光栅再 compute 解析,代价是相对非 OIT 的 2.5 倍以上历史开销与高维护成本,且在 4K 与 RGB 下不划算(讲义 slide 23、slide 24)。下一章把这些代价换成一份从玩法与美术侧提出的诉求清单。
4玩法级的硬要求:这一层不能只求「好看」
上一章收在既有两条路都碰顶这个判断上,这一章要说清碰顶是怎么被界定的。讲义 slide 25 用一页把新方案的诉求列全,页面标出 IMPORTANT,等于把这一页定成后文所有取舍的验收标准。
页面一侧列了四条诉求。第一条是遮挡(occlusion):烟雾弹与能见度本身是一条重要的玩法特性,被烟挡住的东西就该看不见,遮挡在这里属于玩法能否成立的条件。第二条是多色透明(页面写作 polychromic transparency):Call of Duty 系列用大量彩色玻璃,透射率因此不能只当一个标量处理。第三条是远距离视图的稳健性(robustness in long distance views):远距离交战下覆盖关系仍要正确。第四条是内存与性能(memory & performance),把预算这条硬约束一并列入。页面另一侧还列了别的游戏在用什么,写着加权混合 OIT(Weight Blended OIT)、矩的顺序无关透明(Moment-Based OIT)与有界 A 缓冲(Bound A-Buffer)三项;这三种方法的机制与代价留到后文展开。两条栏目在页面上分别标成 NEW SOLUTION 与 WHAT OTHER GAMES USE,这一页因此既是诉求定义,也是一次选型提示。
四条诉求看着朴素,它们各自否掉了一批能出图的方案。遮挡这条把近似混合的短板顶到台面上:上一章提到加权混合的弊里就有难以表示遮挡,一条烟雾弹要挡住的恰恰是最容易被近似抹平的那块内容。多色透明这条否掉了只按单色透射率做的近路,它要求透射率带颜色,于是颜色要么另存一份,要么在别处补回来,第 11 章会看到这套方法在这个问题上花了额外内存。远距稳健这条把误差随深度的积累摆上桌面,越远的地方越容易把误差攒起来。内存与性能这条则限定了解法能用什么手段换精度。
这四条要求也各自指向后文的一处回答。遮挡这条要求透射率在深度上足够陡,事件挤在同一片内时的过度与不足遮挡是它的最小反例,第 10 章的自适应深度分布就是冲这件事去的(讲义 slide 85、slide 94)。多色透明这条在结果侧被回答两次,一次是彩色透射率源单独存一份、多付预通道与内存(讲义 slide 99),一次是远距离交战里彩色玻璃能否被正确解出(讲义 slide 104)。远距稳健这条对应同一张 150 米交战距离的覆盖对照(讲义 slide 104)。内存与性能这条落在性能表上,其中基线一侧按带宽吞吐拉满的平台假定来算(讲义 slide 105)。本章只把它们的话头挂上,展开留到后面。
本章可核对的结论有四条。遮挡、多色透明、远距离视图的稳健性、内存与性能是这一层的四条硬要求(讲义 slide 25)。其中遮挡被明确定义为玩法要素,烟雾弹的遮挡本身构成玩法(讲义 slide 25)。多色透明这条的依据是 Call of Duty 系列大量使用彩色玻璃(讲义 slide 25)。页面另列了别的游戏在用的加权混合、矩与有界 A 缓冲三类方案(讲义 slide 25),它们的机制与失效将在后文被逐一对照。至此问题、解族、现状、要求四块已经铺开,第 5 章进入方案筛选,看两条不变性怎样把既有方案一批批筛掉。
5两条不变性把既有方案筛掉
第 4 章把 CoD 的硬要求收成四条,遮蔽、多色透明、远距离稳健、内存与性能。这一章把既有方案拉回对照台,看它们各自在哪一条上先撑不住。
矩的方案在讲义 slide 26 上给出,moment-based OIT(MBOIT,矩的顺序无关透明),出处 [PMWK17][SHA18]。它的预通道渲染 P 个通道的 MRT,逐事件把深度 z 的幂次与权重 w 相乘再累加;采样时用这批矩重建透射率(transmittance)曲线,页内写出的重建式是 T(z) = exp(−Hamburger(b/d′, z)·d′)。隐患也列在同一页:阶跃函数难以表示,薄的不透明特征会被平滑掉,判断是它不具备深度复杂度不变性(depth complexity invariance,深度复杂度不变性)。
小波的方案在讲义 slide 27 上给出,wavelet-based OIT(WBOIT,小波顺序无关透明),出处 [ASM21]。它的预通道把 n+1 个通道写进 2n 通道的 MRT,采样侧同样重建透射率积分。隐患写在同一页:薄的不透明特征投影会引出振铃,且存在平移方差,也就是不具位移不变性(shift invariance,位移不变性)。这里要分开两个缩写,讲义 slide 15 的 weighted blended OIT [MB13] 归在近似混合一类,本篇 WBOIT 指讲义 slide 27 的小波版本。
讲者在最简场景上过一遍,讲义 slide 28 到 slide 30。三种做法都看不出毛病:NO OIT 已经露出破绽,MBOIT 解掉顺序依赖、图像稳定,WBOIT 的表现相当。
换成烟、玻璃与剪影混在一起的场景后,对照开始分化,讲义 slide 31 到 slide 33。NO OIT 是标准排序版本,一个角色剪影从烟雾弹里透出一点。切到 MBOIT 反而更差,画面里又冒出一个此前藏在烟里的角色,这次是一个合法的不透明几何角色,本应 100% 被遮住;同时能看到 MBOIT 的放大走样。WBOIT 有同样的问题,但剪影分辨率保持得明显更好,原因被归到小波在线性放大下的行为。
拆解从讲义 slide 34 的一套测试台架开始。屏幕中偏左一个洋红色十字准星指着前景最靠前那张卡片左上角旁的不透明背景;场景里三张以 0% 透射率画的透明 VFX 卡片按不透明物体的方式绘制,但走 OIT,此处本应得到 100% 遮蔽。
向右移准星,讲义 slide 35 命中第一张单独的表面,函数够陡。讲义 slide 36 命中两张透明精灵重叠的像素,此前陡峭的线开始歪斜、失去斜率。讲义 slide 37 命中三张卡片重叠的像素,歪斜已经显著。这条链落实了讲义 slide 26 的判断,MBOIT 不具深度复杂度不变性。
换到 WBOIT,讲义 slide 38 到 slide 40 给出另一条曲线。讲义 slide 38 上蓝光不再从任何卡片里透出,只是重建出的透射率图上有一些奇怪的倾斜。讲义 slide 39 继续移动,曲线没有变化。讲义 slide 40 到最后一个事件仍然如此,备注把它解释成小波在深度上的隐式分离。
转折在讲义 slide 41 到 slide 43 兑现。讲义 slide 41 把相机往后拉,重建出的透射率明显偏移,斜率变化不大。讲义 slide 42 把相机稍微内推,斜率和偏移剧烈变化,备注说这在运动中很像振铃,后果是精灵之间遮蔽关系的明显视觉振荡。讲义 slide 43 说越过那段深度区间之后一切又恢复正常。WBOIT 复杂度不变性更好,位移不变性却不成立,讲义 slide 27 的隐患栏写过一次。
两条不变性被一起立成目标,讲义 slide 44 一页写全。标题是 NEED NEW SOLUTION,两条要求分别是 Complexity invariant 与 Shift invariant,MBOIT、WBOIT、NO OIT 与讲者新提的 VBOIT 各占一格。
本章可核对的结论有三条。MBOIT 与 WBOIT 都有机制页写明隐患,前者在讲义 slide 26 被点出不具深度复杂度不变性,后者在讲义 slide 27 被点出不具位移不变性。拆解把前者坐实到三张卡片重叠的像素上(讲义 slide 34 到 slide 37),把后者坐实到相机位移后曲线的斜率与偏移上(讲义 slide 41 到 slide 43)。两条不变性由此定为设计目标,讲义 slide 44 的第四格 VBOIT 是下一章的入口。
6思路挪一次家:把体渲染的 froxel 透射率搬过来
第 5 章把两条不变性立成设计目标,这一章看讲者从哪里借来一条能同时满足它们的路。讲义 slide 45 是一页分节页,标题 VOXEL-BASED OIT,在讲到最终形态 Adaptive Voxel-Based OIT 之前,先讲基础版本,把它当作完整方案所必需的积木。
名字里的体素落到一张具体的图上,讲义 slide 46 标题是 TRANSMITTANCE IN VOLUMETRIC RENDERING。这一页把体渲染(volumetric rendering)的做法摆成一条对照:办法是把空气密度体素化成 froxel(体素化空气密度单元),再由一个 compute 作业沿眼射线积分透射率,生成一张从眼睛到所问之点的透射率积分的 3D LUT;渲染透明物体时去采样这张 LUT 拿透射率积分,采样可以是线性或更高阶。
示意图的纵轴是透射率 1.0 到 0.0,示例里沿相机 Z 逐级把透射率压到 0.75、0.375、0.281(讲义 slide 46)。这三个数只说明曲线单调下降的形状,不构成平台读数,页内另一半同型面板标的是 0.75 与 0.5。
把讲义 slide 46 的条目逐条拆开,每一步都落在 OIT 缺的东西上。沿眼射线积分给出的是从眼睛到某点的累积,这正好是第 2 章合成方程里每个事件那个到该事件为止的积分透射率;3D LUT 让这份累积以点为单位被取用,取样位置由事件自身的深度决定;线性与更高阶采样是两组插值档,讲义 slide 46 只列了这两档,具体到 OIT 侧怎么选、要留多少深度偏置,要到第 9 章才展开。采样这一步发生在透明绘制里,讲义 slide 46 把它列在渲染透明之下,和第 9 章的采样处走样是同一条线。
体积雾已用过相似的框架 [WRO14][DRO17],更早的对应物是深度阴影图(Deep Shadow Maps)[LOK00][NGU05][SIN08][BAV13]。
讲义 slide 45 的备注说得直接,基础版本只是积木,后面还有自适应版本,而自适应要用的前提之一,就是这一层体积结构在切片之间位移不变,讲义 slide 93 会回到这点。
为什么这套做法正好补上 OIT 缺的那一层,要回到第 2 章那条合成方程。方程里每个事件的权重是到该事件为止的积分透射率,也就是沿深度累积的结果;第 5 章的 MBOIT 与小波 WBOIT 都把这整条累积曲线压成少量矩或基系数,采样时再重建,重建在深度不连续处失真。体渲染的做法把累积结果本身留在缓冲里,查询是按点去缓冲取样,累积结构没有被压掉。还有一处结构上的对应,讲义 slide 18 在讲透射率积分加权 OIT 时已经把整条链拆成两个 pass,低分辨率的透射率预通道加全分辨率的透明绘制,体渲染这套是同一形状,只是把低分辨率那一层从平面缓冲换成了体积缓冲。深度被切成一片一片的格子,遮挡关系就落在这些格子里,MBOIT 与 WBOIT 把整条曲线压成的系数里没有这种按深度分好的结构。
借用有代价,讲义 slide 46 也把两处伏笔埋下。多出一层体积缓冲,它有自己的分辨率与内存账;切片带来精度问题,froxel 在相机 Z 上离散,写进去与读出来都受切片分辨率限制。前者在第 7 章连上深度分布,后者在第 8 章与第 9 章分写入侧与读出侧展开。
体渲染积分的是连续介质,OIT 面对的是无限薄的表面事件,把表面事件当成消光(extinction)逐层累加进体素缓冲,是这次挪家最要紧的一步。第 7 章骨架里的把透明事件样条进缓冲,就是这步改写的落地形式。
本章可核对的结论有三条。基础版本的名字是 VOXEL-BASED OIT,讲者明说它只是最终形态的积木(讲义 slide 45)。它借的是体渲染沿眼射线积透射率的那套框架,工具是 froxel 与透射率积分的 3D LUT,已在体积雾与深度阴影图里有先例(讲义 slide 46)。借来的代价是多一层体积缓冲与切片精度,骨架与精度分别留给下面两章。
7VBOIT 三步与可调的深度分布
第 6 章把体渲染那套搬过来了,这一章立骨架。讲义 slide 47 标题 VBOIT : BASIC STEPS,一页把整条流水线列完。为切片拟合沿深度的曲线分布;清空体积消光缓冲;把透明事件样条(splatting)进体积消光缓冲。随后是三个下游步骤,沿视线把消光累加成一张 3D 消光积分纹理;画不透明几何;最后按任意顺序渲染透明,在表面所在位置查消光积分,把表面不透明度乘上透射率积分。收尾一步用归一化后的透明累积颜色与累积消光去合成不透明背景,这个归一化回到第 2 章加权混合里那一步归一化求和。
样条发生在更低分辨率上;透明渲染本身按任意顺序,顺序依赖在写入侧的消光累加里已经被吸收。
拟合曲线决定每个切片落在相机 Z 上的哪个位置,它把一条连续的对数曲线采样成有限个深度值;清空把体积消光缓冲置空,这是每帧都要付的一次固定成本,讲义 slide 47 把它排在样条之前;样条把事件的消光写进它覆盖到的那些切片,写入时要顺带决定分辨率与位宽,这两件事分别落在第 8 章的开头与中段。透明绘制那一步的乘法要单独说一句,讲义 slide 47 写的是把表面不透明度乘上查到的透射率积分,这个权重与第 2 章合成方程里每个事件的权重是同一个量,差别只在它此时是查表结果,不再是排序后的连乘。
深度分布在讲义 slide 48,标题 VBOIT : DEPTH DISTRIBUTION,页内写 LOG CURVE 与三个可调项,远平面(Far plane)、线性化因子(Linearization factor)、切片数(Slice count),近平面是隐含定义的。froxel 缓冲的切片在深度上用一条参数化对数曲线分布,切片数越多,近平面附近的精度就能调得越高。
讲义 slide 49 把两个对照组摆在两边,128 切片与 1024 切片,并给出两条要一起调的规则:切片数与线性化因子一起调,让靠近相机处的空间切片分辨率大致保持恒定;同时保证场景里有一个最小的期望精度,用动态覆盖更长距离的方式在远处牺牲精度。
这三个旋钮就是第 4 章内存与性能那条要求落到实处的接口。切片数越多、近处越细,体积缓冲的内存与每帧的读写量都跟着涨,讲义 slide 49 用 128 与 1024 两组切片把这条交换摆开;讲义 slide 48 的远平面与线性化因子则决定这条曲线把多少分辨率留给近处、多少留给远处。讲者在讲义 slide 47 到 slide 49 没有报任何计时,这一步的读数要到第 8 章原子累加的计时表里才出现。
切片是相机空间 Z 上的离散化。讲义 slide 47 的写入与查询都发生在深度维上,讲义 slide 48 的曲线与讲义 slide 49 的切片数都只是在决定这条 Z 轴怎么分格。讲义 slide 49 的 128 与 1024 只是两组对照,讲者没有推荐其中一档,正文按可调项的口径写。分格之后的后果留到后面,第 8 章讲样条写入侧的走样,第 9 章讲采样侧的走样与自遮挡,两处的根都在这里。
本章可核对的结论有两条。VBOIT 的基础步骤是拟合深度分布曲线、清空体积消光缓冲、把事件样条进缓冲,随后积分成 3D 消光积分纹理再合成(讲义 slide 47)。深度分布用可调对数曲线,旋钮是远平面、线性化因子与切片数,近平面隐含(讲义 slide 48);128 与 1024 切片的对照说明切片数与线性化因子要一起调(讲义 slide 49)。讲义 slide 47 到 slide 49 没有给这三个旋钮的默认值。
8消光体素化:位宽、溢出与彩色打包
第 7 章定好深度分布,这一章处理每一次样条怎么写进缓冲。讲义 slide 50 与 slide 51 给出两条样条路径。光栅化路径在讲义 slide 50,思路是借样条累加透射率,[BAV13] 建议用 SV_RenderTargetArrayIndex 把四边形指派到切片;硬件支持可能要走几何着色器路径,快路径要求 VPAndRTArrayIndexFromAnyShaderFeedingRasterizer,它只对逐图元有效,因此只能体素化面向相机的四边形。页内三步是,切片清成 1.0;顶点着色器把 VFX 四边形指派到切片;像素着色器用 MUL BLEND 写入 (1.0 – alpha)。
原子路径在讲义 slide 51,出自 [DRO17.2] 的原子网格体素化。从像素着色器直接样条,争用压小就快;硬件没有 InterlockedAtomicMultiply,于是把量从透射率改成消光,在对数空间里用 InterlockedAtomicAdd 累加。页内代码就是这条换算,由 alpha 取消光的 saturate(-log(1.0 - alpha) / -log(1.0 / VBT_EXTINCTION_BIT_MASK)),由深度算切片号,再乘位掩码取整后用 InterlockedAdd 写进体素缓冲。
一次原子累加的成本在讲义 slide 52,页首口径是渲染 1700 万像素 overdraw(过度绘制)@ 1080p PS5,页内表并列 MRT MUL 0.75 ms 与 U32 0.91 ms(讲义 slide 52,页内表)。
讲义 slide 53 判断 U32 过杀,内存与性能两头都贵,于是把切片打包进 U32 里的 8 位字,随之而来两个问题,溢出,以及字与字之间的进位。页内示意图画的是一个 DWORD 里的 Word3 到 Word0,正确结果是被加的那个字变成 129,进位版则把下一个字顶到 255,动了不该动的字。打包后的计时表在讲义 slide 54,MRT MUL 0.75 ms、U32 0.91 ms、U8 0.89 ms(讲义 slide 54,页内表),8 位一栏旁标出 overflows。
溢出处理在讲义 slide 55,用 InterlockedAtomicCompareExchange。它能实现任意运算,等价于自旋锁,讲者给的判断是贵 2 到 10 倍,并称其为参考版本。页内代码是一个 pack/unpack 循环,先算打包消光与期望值,用 AtomicCmpExchange 尝试写入,期望值与当前值不等就把当前值解包、加上消光、饱和后打包重试。带自旋锁的计时在讲义 slide 56,MRT MUL 0.75 ms、U32 0.91 ms、U8 0.89 ms、U8 Spinlock Overflow 1.95 ms(讲义 slide 56,页内表),这一档比 8 位直写贵出一倍多,靠它兜溢出并不划算。
讲义 slide 57 换了一条路,先做溢出检测。把字按积分方向排好、沿射线推进,一旦溢出,之后的数据不再重要,字间进位也不必管;检测只做两件事,溢出时记下当时的深度,用 InterlockedMin 在射线上取最小深度。积分阶段读回这个溢出最小深度,饱和之后停止积分。页内示意图把这条链画成 W0 到 W3 四段,标出溢出点 Z2,积分走到 Z2 就停并饱和。讲义 slide 58 的计时表把成本摆出来,MRT MUL 0.75 ms、U32 0.91 ms、U8 0.89 ms、U8 Spinlock Overflow 1.95 ms、U8 Overflow Min 0.91 ms(讲义 slide 58,页内表),加了整套溢出最小深度检测之后,这一档回到与 8 位直写相当的位置。
彩色在讲义 slide 59,做法把 RGB 压进 32 位,排布是 8|(2)|8|(2)|8|(2),用单次原子更新完成,执行速度与打包 8 位单色相同,代价来自缓存变差。页内另列几条推论,切片共享变少,原子争用随之变少;第一版溢出法不防进位跑到下一个波长;把 8 位放进 10 位字段能留出 2 位给溢出与进位;进位只碰到下一个波长的最低位,除非所有 VFX 都有严重色偏,实际里看不到;第一版溢出对 R、G、B 各存第一个切片;用三次 InterlockedMin 再加一次针对单个 U32 的自旋锁更新反而更快。
积分作业在讲义 slide 60,生成积分 3D LUT 的做法是遍历全部切片、逐片累加消光,积分饱和或检测到溢出就停,这一步接上第 6 章那张从眼到点的透射率积分表。讲义 slide 61 是第一次尝试的对照,只给 Slice 0 与 Slice 1 两格,备注说它跑通了,但能清楚看到走样。
走样先在写入侧,讲义 slide 62 标题 VBOIT : ALIASING AT SPLAT,副题 ALIASING AT SOURCE,机制写得很短,样条时事件被离散到切片分辨率,跨样条深度发生的变化就会产生走样。
讲义 slide 63 给出线性样条,做法用切片内的小数把一次样条拆给相邻两片,单色版本把样条合并到 Z 与 Z+1 两片,并在跨越 DWORD 时多发一次。讲义 slide 64 是 RGB 的线性样条,要发两次样条,性能没有差别,原因是两次样条落在同一缓存行内、彼此独立。讲义 slide 64 的计时表把四种方式并列,单色点样条 0.75 ms、单色线性样条 0.81 ms、RGB 点样条 0.91 ms、RGB 线性样条 0.95 ms(讲义 slide 64,页内表),口径仍是渲染 1700 万像素 overdraw @ 1080p PS5。
本章可核对的结论有两条。原子累加被压到 8 位字,中间经过溢出与进位两个问题,自旋锁版本贵 2 到 10 倍(讲义 slide 55),换成溢出最小深度检测后回到 0.91 ms(讲义 slide 58,页内表)。写入侧的走样由线性样条化解,四种方式的读数在 0.75 ms 到 0.95 ms 之间,RGB 线性样条相对点样条没有性能差(讲义 slide 64,页内表)。这些读数全部绑定 PS5、1080p 与 1700 万像素 overdraw,页内表的行列对应关系未经人工核对。下一章转到采样侧,看走样在读出时如何再出现一次。
9积分、采样与两个提前退出
上一章把线性样条讲到位,源处的走样被压下一截。这一章从那些片出发,先把它们加成一条可查询的积分,再处理采样侧冒出来的第二次走样,最后收在讲者找到的两处提前退出(讲义 slide 60 与 66 至 84)。
积分由一条 compute 作业完成(讲义 slide 60)。它逐切片遍历、累加消光,一旦积分饱和就停止这条射线的推进;产出一张积分三维 LUT,眼射线上任意一点都去查它的消光积分。示意图的横轴是相机 Z 上的体素序列、纵轴是透射率,刻度为 1.0、0.75、0.375、0.281。第一版跑通后,讲义 slide 61 的两张切片图给出的评语是走样明确可见(讲者备注原话之意:第一次尝试可行,可见明显的走样)。
第二次走样出在采样一侧(讲义 slide 66)。问题在于样条点的采样值并不等于样条当时的取值,于是有了自遮挡的机会。讲义 slide 67 的玻璃板示例说得很直,玻璃板开始与自己相交、自己遮挡自己,根子是深度切片不够精确,积分缓冲按更低分辨率存放又把它放大一档。对策是在采样深度上留负偏移(讲义 slide 68、69):用硬件线性插值要偏移两个切片,线性样条上再叠线性插值不成 C1 连续,得换二阶采样,bicubic 效果好但要偏移 2.5 个切片;落到数字上,线性插值取 -2.0、bicubic 取 -2.5(讲义 slide 69)。
讲者随后把缓冲的真实样子摆出来(讲义 slide 70 至 73)。讲义 slide 70 是一批单色消光切片,页码为 1、5、9、11、12、13、44、66、88;讲义 slide 71 换成彩色事件,页码为 1、3、4、5、6、12、13、14、15,RGB 缓冲与单色缓冲分开,占用相当稀疏;讲义 slide 72 把两路积分并排,页码为 1、3、4、5、6、11、23、66、88。0 到 3 与 20 到 40 这类区间根本没有内容,空空间不影响消光积分、只让代价更高,另有一些区域在缓冲末尾之前甚至在不透明场景之前就已饱和到全消光。讲者据此问了两个问题:空切片能不能跳过,别的渲染能不能也提前退出。
第一处提前退出落在清屏与积分上(讲义 slide 74、75)。先建一张低分辨率占用位缓冲,XY 各是消光分辨率的八分之一,Z 每一位对应一个切片,整体存进 U32;一条 CS 作业把所有包围盒与四边形收拢起来,保守地光栅化或体素化进去,单色与彩色分两路。清屏与积分逐波前读它、跳过空的部分,代价随空间占用率缩放。讲义 slide 75 的页内表把它量化,同一组作业按满屏算是 0.153 与 0.2 毫秒、合计 0.353,按占用算是 0.01 与 0.04、合计 0.05(1440p 目标、RGB OIT 口径,讲义 slide 75(页内表))。
第二处提前退出更大(讲义 slide 76)。一旦某像素透射率归零,它后面的东西就不必再画。积分作业沿射线推进时记下归零的那个切片序号,写出一张零透射率深度纹理。随后是一条提前深度管线(讲义 slide 77),CS 作业按屏幕瓦片生成四边形列表,保守地读零透射率深度,为每块瓦片生成一个贴着该深度的四边形,再用 DrawIndirect 画进深度缓冲。页内表给两组读数,新管线生成四边形 0.004 毫秒、深度绘制 0.01 毫秒、合计 0.014,旧的单四边形 SV_DEPTH 路径深度绘制要 0.2 毫秒(4K 深度缓冲由 480×270 的零透射率生成、PS5 口径,讲义 slide 77(页内表))。瓦片至少要 16×16 才能吃到压缩深度 HiZ 的好处(讲义 slide 78)。讲义 slide 78 到 83 是这项优化的可视化,只能读页内文字与备注。
收尾是一张逐 pass 性能表(讲义 slide 84)。三列分别是 VBOIT、VBOIT 加零透射率与 alpha blend,透明光栅一行是 2.035、1.78、1.73 毫秒,总计一行是 1.98、1.742、1.73;实际绘制的透明像素由 21,276,176 降到 18,922,855,不透明像素由 2,759,432 降到 1,867,980(VRS 4K、RGB VBOIT 480×270、PS5 口径,讲义 slide 84(页内表))。零透射率深度对所有透明绘制都是一次明显的优化,若引擎渲染顺序允许先画透明,它还能顺手剔掉不透明绘制;同时他限定本篇口径,为这场报告给出的性能数字不使用零透射率深度去剔不透明几何。
本章可核对的结论有三条。积分由一条 compute 作业逐切片累加、饱和即停并产出三维 LUT,第一版可见明确走样(讲义 slide 60、61)。采样侧的走样来自采样值与样条时的取值不一致,玻璃板会自遮挡,对策是负偏移,线性插值 -2.0、bicubic -2.5 个切片(讲义 slide 66 至 69)。两处提前退出分别是占用位缓冲驱动的清屏与积分跳过(讲义 slide 74、75)、零透射率深度驱动的绘制剔除(讲义 slide 76 至 84);性能读数绑定 VRS 4K 与 PS5 口径,且本篇数字未用零透射率深度剔除不透明几何。下一章从另一条失效里长出自适应。
10从一条失效里长出自适应
第 9 章把两处提前退出立了起来。这一章换一个方向,讲者主动去找 VBOIT 在哪里坏掉,再把这条失效变成自适应的起点(讲义 slide 85 至 96)。
失效发生在同一条射线上的事件落进同一片时(讲义 slide 85)。讲者的判词是 VBOIT 在同一片内退化为加权混合,权重由线性样条隐式给出(讲者备注原话之意:单片内重叠时 VBOIT 退化为带线性样条隐式权重的加权混合)。示意图把点采样配 -1 偏移与点样条并排。
四种情形被讲者按序演示(讲义 slide 86 至 91)。没有 OIT 的一版单独看;深度分离足够、至少隔开一个切片时渲染没有伪影(讲义 slide 87);事件落进同一片就开始处理「频率汤」(讲义 slide 88);随后是点样条与线性样条各一版,讲义 slide 89 的判断是线性样条与采样借助空间信息改善了色彩混合。两页结论并到一起(讲义 slide 89、91):线性样条能靠加权拉开一点深度分离、让伪影没那么显眼,代价是拉长自遮挡范围;要拿到精确结果,关键仍在把深度分离做开,在需要的地方给出足够的切片。
自适应分节页(讲义 slide 92)之后,讲者先摆三条前提(讲义 slide 93):空空间可以跳过;清屏与积分的优化已留下稀疏缓冲的占用信息,空空间在哪是现成的;VBOIT 在切片之间移位不变,允许把深度压成一条曲线来打包切片。
做法落在一条一维的深度扭曲查找表上(讲义 slide 94)。它借深度切片分箱思路,在样条前先算 Z 占用率前缀和、压掉空区间,再把非空区间的起始与结束标成可过滤端点;空区间里关闭过滤,过滤吸附到端点并重算小数位置;样条与采样两端都去查它。只在深度这一维上做、不把 XY 也一起做稀疏,显著简化了构造与采样(讲者备注原话之意:只做一维、不进 XY 全稀疏)。这条方案能优雅跳过空空间,单独用起来还不能改善视觉精度。
只跳过空空间还不够,切片总数仍要能塞进物理预算(讲义 slide 95)。讲者先按虚拟切片分辨率算出深度方向的一维覆盖率,把占用的切片数加起来。做法是先指定可见深度范围内要求的最小切片厚度,把切片数放到足以满足该厚度的大值并生成占用缓冲,这一步通常造成切片数超订;装不下就把切片数减半、重新参数化、重跑打包,覆盖率数据按保守方式改写进更低分辨率,重复到所有切片装进内存(讲者备注原话之意)。
收尾是一页对照(讲义 slide 96)。深度查找表在两端的代价都接近零;代价转到积分这一侧,它随切片占用率缩放,可调的旋钮是一池物理内存,往性能、精度、内存占用三个方向一起拨。
本章可核对的结论有三条。单片内事件重叠时 VBOIT 退化为带线性样条隐式权重的加权混合,表现为过度或不足遮挡,这是方法的已知失效(讲义 slide 85、89、91)。自适应的三条前提是空空间可跳过、稀疏缓冲已留下覆盖率信息、VBOIT 在切片之间移位不变(讲义 slide 93)。它落成一条只做深度一维的深度扭曲查找表(depth warp LUT,深度扭曲查找表),样条与采样两端按前缀和跳过空空间,构造与采样几乎零代价,积分代价随切片占用率缩放(讲义 slide 94 至 96)。
11结果:图像、150 米远距,与三张性能表
上一章把自适应收在深度扭曲查找表上,这一章交出结果(讲义 slide 97 至 109)。
先立测试设置(讲义 slide 98)。所有方法共用同一个 resolve 与透明度渲染 pass,透射率预通道跑在八分之一分辨率,深度范围也一致。预通道输出按方法不同,MBOIT 是 rank 2 的 5 份 FP16、共三张,WBOIT 是 rank 2 的 8 份 FP16、共三张,AVBOIT 是 8 位乘 128 切片、另加 32 位乘 128;深度扭曲 LUT 取 8k;透明输出走 RGB,累加颜色为 11R11G10B 浮点,累加消光与归一化分母都用 16F。同页还给一张透射率函数开销对照表,MBOIT 每像素写 10 位、读 10 位、两次二维采样,八分之一分辨率 4K 占 1.3 兆字节;WBOIT 每像素写 8 位、读 8 位、三次二维采样,占 2 兆字节,两者在存储上都属稠密(讲义 slide 98(页内表))。
彩色这一路单独算一笔账(讲义 slide 99)。AVBOIT 把彩色透射率源拆成单独一份,只为 RGB 源多付预通道成本,到积分那一步再合并;MBOIT 与 WBOIT 没有明显的拆法,也没有明显的合并采样办法。页内表按 pass 给出 RGB 相对单色的额外开销:清屏三者都是 3 倍;预通道 MBOIT 1.9 倍、WBOIT 1.7 倍、AVBOIT 1.04 倍;积分只有 AVBOIT 有,为 3 倍;绘制 MBOIT 1.4 倍、WBOIT 1.3 倍、AVBOIT 1.05 倍;平均下来 MBOIT 高于 1.5 倍、WBOIT 高于 1.3 倍、AVBOIT 约 1.05 倍(讲义 slide 99(页内表))。RGB 消光缓冲单独存要额外内存,换到的是清屏、样条与积分只作用在真正被 RGB 表面用到的切片上。CoD 的内容里样条事件更可能来自粒子、偏单色;换到 VFX 大量用 RGB 透射率的项目,留一份 RGB 表示反而更省。
三张画面按方法排开(讲义 slide 100 至 103)。讲义 slide 100 是没有 OIT 的一版,讲义 slide 101 与 102 分别是 MBOIT 与 WBOIT,透明会透出来。讲义 slide 103 是 AVBOIT 的结果,备注特别交代画面中景那团烟在原始资产里就有,AVBOIT 因深度分离得到改善,让它更突出。
远距离那一层放在直线距离 150 米的一次交战上(讲义 slide 104),一页四联对照 NO OIT、MBOIT、WBOIT 与 AVBOIT。NO OIT 正确遮住了背景里的车,却没能解出右侧建筑的玻璃;MBOIT 与 WBOIT 在一定程度上解出了玻璃与烟,却漏掉背景玻璃的遮挡;AVBOIT 把两类麻烦事件都解对(讲义 slide 104)。这一页解释了为什么把「远距离视图的稳健性」列进第 4 章那张诉求清单。
第三层是性能总表(讲义 slide 105)。表中列了 MBOIT、WBOIT、AVBOIT、AVBOIT 加剔除与 NO OIT 五列,行按 clear、prepass、cull、integration、draws、resolve 与总计铺开;总计一行的读数是 MBOIT 5.705、WBOIT 5.908、AVBOIT 5.667、AVBOIT 加剔除 4.967、NO OIT 4.4 毫秒(4K、PS5 口径,讲义 slide 105(页内表))。这一页的表必须连它的假定一起读,讲者明说为了对照,MBOIT 与 WBOIT 被假定跑在「带宽吞吐拉满」的平台上,即加速清屏、加速 zero 渲染目标输出;他补充清屏在各平台与 PC 上都应是硬件加速的,zero 输出则可能因平台而异。AVBOIT 的定位也被说成对既有 OIT 方法一个有吸引力的替代,逼近没有 OIT 的地带(讲义 slide 105)。表中 AVBOIT 绘制一行 5.2 毫秒、加剔除降到 4.5 毫秒,剔除那一行本身是 0.006 毫秒。
最后四个阶段是 RGB 实用性能(讲义 slide 106 至 109),每翻一页多出一列,读数从 2.8 毫秒起步,依次出现 2.95、3.02 与 3.11 毫秒(4K、PS5 口径,讲义 slide 106 至 109(页内表))。这四档的行列对应未经人工核对,讲义未给该行的完整口径,此处只按页内出现的顺序记下这四个读数,不把它们与列名一一归位。
本章可核对的结论有三条。所有方法共用一个口径,共用 resolve 与透明度渲染 pass、透射率预通道八分之一分辨率、深度范围一致,预通道输出按方法各是 5 份 FP16、8 份 FP16 与 8 位乘 128 切片(讲义 slide 98)。远距 150 米一页上,NO OIT 遮住背景车却解不出玻璃,MBOIT 与 WBOIT 部分解出玻璃与烟却漏遮背景玻璃,AVBOIT 两类事件都对(讲义 slide 104)。性能总表总计为 MBOIT 5.705、WBOIT 5.908、AVBOIT 5.667、AVBOIT 加剔除 4.967、NO OIT 4.4 毫秒,且 MBOIT 与 WBOIT 的读数按「带宽吞吐拉满」的平台假定给出,并非中立对照(讲义 slide 105)。
12边界与反例:它在哪里失效、在哪里不划算
上一章交出结果与三张性能表,这一章把讲者自己列的边界摆齐(讲义 slide 110 至 122,另加 bonus 段的 126 至 135),把「结果好」与「到处都能用」分开。
先说生产侧的账(讲义 slide 110)。环境美术这一侧判为没有负面影响、也没有新 bug,不再需要手工排序与自定义排序材质。VFX 一侧相反,很多问题被修掉,同时冒出一条反复出现的「bug」,发射器不按手工排序来了,UI 也排不对;备注解释是环境通常守规矩、不会滥用物理排序逻辑,VFX 的效果常靠烟雾与障眼手段凑出来(讲者备注原话之意)。
VFX 这一处的冲突需要单独看(讲义 slide 111 至 114)。讲者承认部分发射器故意用手工排序夸大某些元素,讲义 slide 111 的例子是火球透过烟显得很强;换成 OIT 之后(讲义 slide 112),画面变成物理正确的结果,讲者直接写下这并不符合美术本意。完全复原在观感上做不到,但可用 camera offset 把效果沿相机射线在深度上摆开,甚至预设一组偏置供分层。反过来,手工排序本身也不干净(讲义 slide 113),爆炸帧里烟缕会出现不该有的问题,OIT 会顺手修掉(讲义 slide 114)。
第二处冲突是 3D UI(讲义 slide 115)。讲者给三条绕法,拨切片用于分层、手工改这些绘制的顶点着色器深度,或把 UI 先离屏合成为二维图再当纹理用(讲义 slide 115)。
结果之外还有平台(讲义 slide 116)。Gen8 与 Gen9 缩放趋势相近,PC 低配也一样,讲者点名 AMD RX470 与 NVIDIA GTX 1060 两张卡。页内表按 PS4 1080p 给出透明度与 VFX 两行及总计,总计为 MBOIT 6.65、WBOIT 6.16、AVBOIT 5.03、NO OIT 4.5 毫秒;另一段 GTX 1060 的电影化测试在 1080p 下给出 AVBOIT RGB 透射率 12.2 与 NO OIT 11.2(讲义 slide 116(页内表))。讲者备注说 AVBOIT 在各平台都给出可用的性能替代。
结论页把这一篇收在「够好」上(讲义 slide 118),靠提前剔除与多分辨率渲染做到比没有 OIT 更快、稳定,RGB 透射率 OIT 变得可用,并打开 OIT 折射与散射、景深与运动模糊三道门。扩展页把更多量按透射率积分加权,点名运动矢量、景深视觉深度与折射散射(讲义 slide 119、120);未来工作页只展开一项稀疏体素纹理,于是按目标分辨率占用数据申请虚拟缓冲的块,内存不够就下调分辨率重来(讲义 slide 121)。讲义 slide 122 只有文献清单。bonus 段(讲义 slide 126 至 135)把单色与彩色近似的失败与自校正又演一遍,只在透明绘制里累加彩色消光会让不透明像素正确、透明处缺色;双面玻璃背靠背、深度差 0.125 英寸这类硬例子会因重叠切片混入色偏,可用检测重叠、去掉色偏的保守做法解决。
边界 1:性能读数全部绑定平台与设置。 读数出自 PS5、1080p、1700 万像素 overdraw(过度绘制)、透射率预通道 1/8 分辨率、全部方法同一 resolve 与透明度渲染 pass、同深度范围(讲义 slide 52/84/98/105);4K 读数(讲义 slide 106–109)另注分辨率。
边界 2:讲义 slide 105 的对照按「基线带宽吞吐拉满」的平台假定来算,并非中立对照(加速清屏、加速 zero 渲染目标输出);该页总计读数只在此假定下成立,不能读成 AVBOIT 对 MBOIT/WBOIT 的中立比较。
边界 3:讲义 slide 24 的「2.5 倍以上」是 BO4(2018)那一代的历史成本,属既有方案的故事,不作 AVBOIT 的对照。
边界 4:单片内事件重叠时 VBOIT 退化为带线性样条隐式权重的加权混合(讲义 slide 85、89、91)。这是方法的已知失效,并非实现缺陷;缓解是线性样条与在需要处增加切片。
边界 5:讲义 slide 111–115 是「物理正确与美术意图」的冲突。 手工排序有时是美术故意用来夸大效果的,OIT 给出物理正确结果而该结果并非美术本意;3D UI 的叠加逻辑与 OIT 天生不合。属内容侧问题。
边界 6:不与任何商用方案横比。 对照对象只有讲者自列的 NO OIT/MBOIT/WBOIT,AVBOIT 深度绑定 CoD 的透明渲染管线与 PS5/Gen8 平台。
边界 7:幻灯区表格的行列对应关系未经人工核对。 页内表格在 PDF 里是散块文本,正文只引用能自洽对齐的部分,不确定处写「讲义未给该行的完整口径」;不得凭推断补全。
边界 8:讲者未给代码与数据。 讲义 slide 122 只有文献清单,全篇无仓库与开源链接;讲义 slide 121 的稀疏体素纹理、讲义 slide 119–120 的畸变扩展按未来工作引用,不得写成已落地。
本章可核对的结论有两条。生产影响与「更少工作、更少 bug」并存于两处内容侧冲突之中,一处是 VFX 用手工排序故意夸大效果、OIT 给出的物理正确结果并非美术本意,另一处是 3D UI 的叠加逻辑与 OIT 天生不合,二者都属内容侧问题(讲义 slide 110 至 115)。性能与扩展各带口径,讲义 slide 105 的对照按「带宽吞吐拉满」的平台假定、4K 读数另注分辨率(讲义 slide 106 至 109),扩展与未来工作按方向引用(讲义 slide 119 至 121)。
13贡献块
三条可搬走的做法与站内互读
一场生产向的讲座能留下什么,取决于它把哪些东西讲到了别人抄得走的程度。AVBOIT 留下的三样都绑在明确的依赖前提上:一次从体渲染借来的结构迁移、一套把原子累加压到 8 位的工程收口,以及一层把切片精度按需分配的自适应结构。它还有一条贯穿全篇的口径纪律,历史成本、同设置的性能表与图像结果分列,正文凡出场即带限定,因此这三样贡献都只报「怎么做的」,不替读者把收益外推。
贡献 1:把体渲染的 froxel 透射率积分搬到透明渲染上。 OIT 与体渲染解的是同一条沿视线的透射率积分,只差在一侧的事件是体积散射、另一侧是不透明表面。讲者把体渲染那套结构整块借来重用:切片化的消光缓冲、沿眼射线的积分作业、以及一份可被眼射线查询的三维查找表(第 6、7 章,讲义 slide 46/47/48)。想在自己管线里试这条路的读者,可搬的是这套结构与三步骨架,前提是自己已经有一层 compute 作业调度与切片化的体积缓冲。
贡献 2:一次原子累加做成 8 位打包的工程收口。 消光累加最初用 32 位原子,讲者判断这是「过杀」,于是把切片打包进 32 位字里的若干 8 位段,随之而来的溢出与字间进位分别用溢出检测加最小深度饱和、以及等价于自旋锁的比较交换来收口;彩色事件则压成 8|(2)|8|(2)|8|(2),单次原子更新、速度与打包 8 位单色持平(第 8 章,讲义 slide 52–59)。这一段可搬的是「先量再压、压完把失败模式一个个堵上」的做法,不是那些具体的毫秒数 —— 它们全部绑定 PS5、1080p 与 1700 万像素 overdraw。
贡献 3:把切片精度集中到有内容的地方。 VBOIT 的失效只有一种:事件落在同一片内时退化为加权混合(讲义 slide 85)。既然后续优化早就知道了缓冲的稀疏分布,且这个表示在切片之间是移位不变的,那么把深度在若干区间上做一次非线性映射、用前缀和把空空间压掉,就能在同样的切片预算下把精度放到真正有事件的地方;讲者强调只在深度一维上做,因此结构的构建与采样都没有被复杂化(第 10 章,讲义 slide 93/94/95/96)。可搬的是这条「用已有的稀疏信息换精度」的推理链。
站内可以接着读的几篇:篇目 11(DDGI)与篇目 27(ORCA)都在处理体积或探针表示的取舍 —— 前者给辐照度场补可见性、后者每帧重建多尺度体素缓存,与本篇「用稀疏结构换精度」是同一类动作;同批的篇目 29(Smolder)讲的是把体积效果做成引擎里的通用系统,与本篇「把体渲染的机制搬到另一个渲染阶段」是同一种迁徙思路;篇目 30(Adaptive Tessellation)与篇目 31(SLIM)都在按预算分配分辨率,与本篇把切片花在该花的地方互相呼应。本篇讲义全篇没有给出代码仓库或开源链接,唯一的文献线索是讲义 slide 122 的参考文献清单(其中 [KOH16] 就是讲者自己讲过的 BO4 A-buffer)。
14原文出处块
原文出处与引用口径
出处:SIGGRAPH 2025 · Advances in Real-Time Rendering in Games(Part I,2025-08-12)· 讲者 Michał Drobot(Technology Fellow, Activision Central Technology)· 官方讲义《Adaptive Voxel-Based Order-Independent Transparency》,136 页,540×720 pt(竖版),来源 PDF 2026-siggraph-advances-avboit.pdf(元数据 author=claire@cubicleninjas.com,为外部讲义设计供应商账号,非讲者;讲者身份取自标题页与讲义 slide 2)
材料:官方讲义 136 页,其中 66 页带讲者备注(合计约 1.38 万字符);幻灯区有文本层,页内标题、项目符号、公式与表格可直接引用,正文不另标图像识别来源;但页内表格在 PDF 里是散块,行列对应关系须人工过图核;本篇事实、读数与页码取自幻灯文本与讲者备注;页码为 PDF 页序(从 0 起),引用写作「讲义 slide N」
许可:幻灯区逐页页脚为 © 2025 ACTIVISION PUBLISHING, INC,末段推广页为 © 2025 SIGGRAPH. ALL RIGHTS RESERVED;全文检索无 Creative Commons / CC BY / public domain 任何 CC 声明,亦无代码许可(无 MIT / open source / GitHub)。故 23 件图按分区非 CC 口径逐件署名(源 slide 号 + 出处 + 版权行 + 「未修改引用」),并在构建记录标注残留风险,不得写成 CC 或可自由转载
引用口径:所有性能读数绑定平台与设置(PS5、1080p、1700 万像素 overdraw、透射率预通道 1/8 分辨率、全部方法同一 resolve 与透明度渲染 pass、同深度范围;4K 读数另注分辨率);讲义 slide 105 的对照按讲者原话建立在「基线带宽吞吐拉满」的平台假定上,不是中立对照;讲义 slide 24 的 2.5 倍以上开销属 BO4 那一代的历史成本,不可当作 AVBOIT 的对照;讲义 slide 111–115 是「物理正确与美术意图」的冲突,按内容侧问题引用;全篇不与任何商用方案横比