大场景渲染与虚拟纹理
Large Scenes & Virtual Texturing
当场景数据远大于内存(如主机只有 8 GB,而游戏世界有数百 GB)时,需要按需把数据流送进内存。本页讲三类技术:虚拟纹理(把巨大的 mipmap 链切成瓦片,只让可见瓦片驻留在显存,通过页表/间接纹理寻址)、纹理转码(磁盘上用高压缩比的可变码率格式,加载时转成 GPU 块压缩格式),以及按平面瓦片组织资产的通用流送。这些方法几乎总是与剔除和 LOD 配合使用;地形部分见 地形渲染。
虚拟纹理与流送(19.10.1 节)
《RAGE》中部分虚拟纹理分辨率达 128k × 128k,全部放进显存需要 64 GB。类比操作系统的虚拟内存,稀疏纹理 (sparse texture) 允许分配一张巨大的虚拟纹理(又称 megatexture),也叫虚拟纹理或部分驻留纹理;应用决定每级 mipmap 的哪些瓦片驻留在显存中。瓦片通常 64 kB,对应的纹素分辨率取决于格式。
核心观察:使用 mipmap 时,所需纹素数理想上只与最终图像分辨率成正比,而与纹理本身分辨率无关。因此只需让可见纹素驻留在物理显存中。
flowchart LR
A["几何体的全局虚拟 uv"] --> B["页表或间接纹理"]
B --> C{"瓦片已驻留?"}
C -- "是" --> D["换算为物理纹理坐标并采样"]
C -- "否" --> E["退回更高层 mip 瓦片, 记录请求"]
E --> F["流送加载并映射瓦片, 更新间接表"]如上图:整条 mipmap 链在虚拟和物理内存中都被切成瓦片(书中示例为 128×128 像素),这种结构也叫虚拟 mipmap 或 clipmap(指从大 mipmap 中裁出一小部分使用)。像素着色器使用 uv 之前,要经 GPU 支持的页表或软件实现的间接纹理换算成物理纹理坐标。远处几何只需少量高层 mip 瓦片,近处几何只需少量低层 mip 瓦片,因此小物理纹理就够用。任天堂 GameCube 的 GPU 已支持虚拟纹理,PS4、Xbox One 及许多 GPU 支持硬件虚拟纹理。虚拟纹理不仅用于从磁盘流送巨型纹理,也可用于稀疏阴影贴图。
决定哪些瓦片驻留:
- 反馈渲染(Sugden 与 Iwanicki;van Waveren 与 Hart):先渲染一遍,输出每个片元将访问哪个瓦片,读回 CPU 分析,加载映射缺失瓦片、解除映射不需要的瓦片。可单独一遍(如只用 80×60 分辨率近似以节省时间)或合并进 z-prepass。对阴影、反射、透明无效,但透明可用纱门技术凑合。
- Hollemeersch 等人用计算着色器代替 CPU 读回分析,在 GPU 上生成紧凑的瓦片 ID 列表再交给 CPU 映射。
- 硬件虚拟纹理下,驱动负责创建销毁资源、映射与解除映射瓦片,稀疏纹理采样除过滤值外还返回瓦片是否驻留的代码;软件虚拟纹理则全部由开发者负责。
适配内存与过渡:
- van Waveren 调整全局纹理 LOD 偏移,直到工作集装得进物理内存。
- 所需低层 mip 瓦片还没到时,先放大使用已有的高层瓦片,新瓦片到达后随时间混合进来,避免突变。
- Barb(《DOOM》2016)总是加载所有不超过 64 kB 的纹理,保证始终有低质量纹理可用;离线反馈渲染预计算在各位置每种材质每级 mip 覆盖玩家周围多少立体角,运行时根据纹理与屏幕分辨率调整,得到每纹理每 mip 的重要性,再除以该级纹素数——这样即使纹理被切成多张相同映射的小纹理,度量也不变。
- 流送还可与程序化纹理生成结合(Widmark,Chen 将其扩展到大一个数量级的纹理)。
纹理转码(19.10.2 节)
转码:从磁盘读取以可变码率格式(典型如 JPEG)压缩的图像,解码后再编码为 GPU 支持的块压缩格式。van Waveren 与 Hart 的流送系统流程:
flowchart LR A["反馈分析所需瓦片"] --> B["经存储层次获取: 光盘/硬盘 → 可选磁盘缓存 → 软件内存缓存"] B --> C["为新瓦片分配, 解除不需要瓦片的映射"] C --> D["转码为 GPU 块压缩格式"] D --> E["映射为新的驻留瓦片"]
- 优点:磁盘上压缩比更高,采样时又是 GPU 原生格式。要求可变码率格式能快速解压、GPU 格式能快速压缩;GPU 上已有 BC1/BC4、BC6H/BC7、PVRTC 的快速压缩方法。
- 对已压缩纹理再压缩:解压后直接就是 GPU 可用的压缩格式。开源的 crunch 库可达每纹素 1~2 位(书中示例:原图 24 bpp,ETC 4 bpp,crunch 后的 ETC 1.21 bpp);其后继 basis 是专有格式,对块做可变位压缩,可快速转码到各种块压缩格式。Khronos 当时正在制定通用压缩纹理文件格式标准。
- Sugden 与 Iwanicki 用 Malvar 压缩的变体作为磁盘可变码率格式:法线压缩比 40:1,反照率借助 YCoCg 变换达 60:1。
- Olano 等人让纹理在磁盘和显存中都保持可变码率压缩,用到时由 GPU 自己的算法解压,之后以未压缩形式使用,兼顾高质量与短加载时间。
通用流送(19.10.3 节)
几何、脚本、粒子、AI 等也需要流送。用正多边形平铺平面——三角形、正方形或六边形——每个格子关联其中所有资产。正方形和六边形最常用,可能因为直接邻居比三角形少(三角形和正方形有共边和仅共顶点两类邻居)。流送系统保证观察者所在格子的直接邻居都已加载,以便周围几何可渲染、走进相邻格子时数据已就绪。
| 案例 | 做法 |
|---|---|
| Ruskin | 六边形,每格一低一高两级 LOD;全世界的低分辨率 LOD 常驻,只流送高分辨率 LOD 和纹理 |
| Bentley | 每格 100 m × 100 m 的正方形,高分辨率 mip 单独流送;近中距离 1~3 级 LOD,远处用烘焙替身 |
| Tector(赛车) | 随赛车前进沿赛道加载;磁盘上 zip 压缩,装入压缩的软件缓存,按需解压后交给 CPU/GPU 内存层次 |
需要三维平铺时,立方体是唯一能铺满三维空间的正多面体,是自然选择。
取舍
- 虚拟纹理让所需显存只与屏幕分辨率相关、与纹理分辨率解耦;代价是地址换算、反馈分析与流送的复杂度,以及瓦片未就绪时先用低分辨率 mip 再渐入。
- 软件虚拟纹理的资源管理、映射与间接表维护全部由开发者负责;硬件支持把这些交给驱动,但应用仍要决定驻留哪些瓦片。
- 转码用 CPU/GPU 时间换磁盘体积和加载带宽。
GEA 的视角:MegaTexture、纹理流送与分块资源(卷 II 11.3.14.8)
- 问题:通常整张纹理连同全部 mip 级都驻留显存,纹理越大越吃内存,GPU 还有最大尺寸限制(DirectX 特性级别 9_3 为 4,096²,10_1 为 8,192²)。
- MegaTexture:id Software 的 Rage(id Tech 5)让美术制作约 128k × 128k 的超大纹理,切成小瓦片按需流送进显存,目标是让开放世界铺满永不重复的独特纹理。GEA 说这项技术本身没有流行起来,但催生了一系列相关技术。
- 纹理流送:需要时把纹理(MegaTexture 的块或普通纹理)流入显存,不再绘制时卸载。顽皮狗引擎等许多引擎都这样做;包括顽皮狗在内的一些方案能按 mip 级分别加载,最低分辨率的几级常驻、随时可画,更高分辨率的级按需流入。
- 虚拟纹理:每张纹理切成较小瓦片(通常 128×128),由 GPU 和图形 API 管理各瓦片在显存中的驻留,只让相关部分占内存。GEA 提到虚幻引擎区分运行时虚拟纹理(通常程序化生成)和流送虚拟纹理(通常离线制作、从磁盘流入流出)。
- 过滤接缝问题与分块资源:过滤需要相邻纹素和相邻 mip 级。如果瓦片完全由应用管理(id Tech 5 就是这样),GPU 不知道哪些瓦片在大纹理中相邻,瓦片接缝处的过滤会出错。DirectX 特性级别 11_0 起支持分块资源 (tiled resources),也叫部分驻留纹理,把邻接信息告诉 GPU 以便跨瓦片正确过滤;此时 GPU 可访问的最大纹理尺寸为 16,384²。
补充与订正(11.3.14.8):GEA 说虚拟纹理"由 GPU 和图形 API 管理各瓦片的驻留",这只适用于硬件的分块资源/稀疏纹理。虚幻引擎的流送虚拟纹理和运行时虚拟纹理都是软件虚拟纹理:引擎自己维护页表纹理和物理瓦片缓存,着色器先查页表再采样(Epic "Streaming Virtual Texturing" / "Runtime Virtual Texturing" 文档)。软件方案也不必然出现过滤接缝:常规做法是给每个瓦片加几纹素宽的边框(如 128 + 2×4),双线性和有限的各向异性就不会越界(Sean Barrett,"Sparse Virtual Textures",GDC 2008;id Tech 5 亦如此),三线性则靠分别采样两级 mip 后自行混合。
与本页 RTR4 内容相比,GEA 的介绍偏概览,没有涉及纹理转码和通用流送。几何上的同类思路见 Nanite 虚拟化几何体。
出处
- realtime_rendering_4ed.pdf 第 19 章 Acceleration Algorithms
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.3.14.8 节