差不多该动手实现ProjectS中地形的RVT了,所以整理一波学习资料,依旧是以FarCry为主体

注意本文中同样的词汇在不同上下文中有不同的意思,以RVT为例,在Procedural Virtual Textures部分,RVT代表Procedural Virtual Textures,但在Adaptive Virtual Textures部分,RVT则代表Adaptive Virtual Textures,基于历史发展,简单排列下术语

  • VT:Virtual Texture,包含SVT(Mega-Texture),RVT(Procedural Virtual Textures,经典RVT),AVT(Adaptive Virtual Textures,Far Cry4提出的改良版RVT)
  • Page:VT的其中一部分,其实叫Tile会更加合理一些
  • Indirection Texture:VT和真实RT映射表,也叫Page Table
  • Physical Texture Cache:最终用于渲染的的RenderTexture

大纲

  1. 概述虚拟纹理技术
  2. Far Cry4的地形
  3. Adaptive Virtual Textures - AVT(一般我们常说的RVT就是这个Adaptive Virtual Textures)
  4. VT渲染挑战
  5. 结果,性能,总结

Virtual Texturing

对于一个大世界项目来说,地形纹理将会非常巨大,并不适合一次性全部载入内存中,所以我们将其分tile,比如256x256,或128x128一个Tile(也可以叫Page,不过我觉得Tile更加贴切一些),我们用一个较小的真实的纹理内存来缓存这些tile。

我们还会使用一个Indirection Texture来记录整个游戏地形纹理Tile真实纹理Tile的索引信息和UV信息

Virtual Texturing示意图

VT在游戏中一般有两种应用方式,Mega-Texture和程序化虚拟纹理

Mega-Texture

也叫SVT(Stream Virtual Texture)

游戏中整个地形的纹理都被烘焙成一个巨大的VT(即分Tile),运行时根据相机位置流式加载,指定Tile被加载到Tile Cache,然后Page Table更新信息(感觉这个顺序有问题?应该是先更新Page Table的信息,再加载相应Tile,否则很难保证状态的干净)

image-20250130153027336

Procedural Virtual Textures

之所以叫程序化VT是因为他不进行离线烘焙VT,而是通过运行时渲染到RenderTexture上,即RVT(Runtime Virtual Texture)

不再需要从硬盘读取VT,对于需要的Tile,实时渲染

利用每帧画面的连续性来减少渲染开销,因为连续意味着可以复用已经渲染到Cached Texture上的结果,减少渲染开销,这一点在地形渲染上尤为有效

PVT

Far Cry 4的地形

Far Cry 4地形概述

远景使用预烘焙的几何和纹理,近景则复杂一些:

  1. 首先从height-map进行地形mesh渲染
  2. 基于一个Mask texture进行4层Material的混合
  3. 有道路和贴花,大量贴花对性能影响很大,可以通过将贴花直接烘焙到VT上来减少开销
  4. 目标分辨率:10纹素/厘米
  5. 基于RVT

Procedural Virtual textures in Far Cry4

下面是Far Cry 4中的早期RVT示例:

RVT

整个游戏世界的VT大小为512K x 512K,Indirection Texture为2K x 2K,最终的真实RT为9K x 9K,对于VT和Indirection Texture来说,做了11级Mip来优化性能,平衡表现

Indriection Texture格式

Indirection Texture的作用是记录VT真正的Tile索引和对应的UV信息,每个整数坐标代表一个VT的Tile,公式为

坐标 = Page 坐标(VT的Tile坐标) / Page 大小(单个Tile的大小),对结果向下取整,例如,假设Tile大小为512,那么对于世界空间5120处的某个Tile,公式就是5120 / 512 = 10

每个纹素内容为32 bit整数

  1. 8位PageOffsetX
  2. 8位PageOffsetY
  3. 8位Mip等级
  4. 8位Debug

那么这种实现方式有什么问题?以目前的规格来看,10km x 10km的世界用了512k x 512k的Virtual Texture,纹素密度是0.5texel/cm,如果我们想要10texel/cm的纹素密度,就需要512k x 20 = 10 million x 10 million的VT,虽然只是个结构体,但亿级别数据也很大了,再加上他会顺带把Indirection Texture给撑大(在这里会达到40k x 40k的分辨率),这是完全无法接受的

原始RVT的问题

Adaptive Virtual Textures

AVT概述

引用

https://zhuanlan.zhihu.com/p/138484024

https://www.youtube.com/watch?v=SVPMhGteeuE&t=827s

https://github.com/lifangjie/HDRPVirtualTexture

https://zhuanlan.zhihu.com/p/300731406