虚拟纹理

1.2k words

来源

大地形的一种简化RVT - jackie 偶尔不帅的文章 - 知乎

简介

为了渲染一个巨大的地形,可能需要使用一个超大分辨率的纹理。大到装不进GPU的显存。128K*128K的纹理将消耗大概64GB的GPU显存。当GPU上的内存空间有限时,操作系统会使用虚拟内存来进行内存管理,根据需要将数据从驱动程序交换到CPU内存中。虚拟纹理提供相似的功能。

地形的采样除了抖动混合其他都需要非常多次的采样albedo和normal然后混合。这已经成为多数项目在GPU方面的最大开销所以有必要缓存他。其次,地形的mesh结构单一性,材质统一性,贴图共用性都导致仅对地形实现RVT是比较方便的.

应用程序会决定每个mipmap层级中的哪些区域(瓦片tile)应当驻留在GPU显存中。一个tile通常为64kb,其分辨率取决于具体的纹理格式。在理想情况下,所需要的纹素数量应当与正在渲染的最终图像的分辨率成比例,并且与纹理本身分辨率无关。只要求可见的纹素位于物理GPU的显存中即可,其中整个mipmap链会在虚拟内存中被划分为若干个块(虚拟mipmap或者clipmap)。由于物理内存的大小比虚拟内存小得多,因此只有一小部分虚拟纹理块可以被装进屋里内存中。

效果对比



将不帅佬的rvt移植到urp下

对RT的压缩

直接将数据存储为 RGBA32的 RT对于内存而言占用很大,通过将RT 压缩为平台对应的压缩纹理,能够更好的优化内存

1
2
3
4
5
6
7
8
9
10
SourceRT = new RenderTexture(albedoSmooth.width / 4, albedoSmooth.height / 4, 0)
{
format = RenderTextureFormat.ARGBFloat,
enableRandomWrite = true,
useMipMap = false,
autoGenerateMips = false
};
TargetTexture = new Texture2D(VirtualCapture.virtualTextArraySize, VirtualCapture.virtualTextArraySize, TextureFormat.DXT5,
0);
Graphics.CopyTexture(SourceRT, 0, 0,0,0, SourceRT.width, SourceRT.height , TargetTexture, 0, 0,0,0);

RT 的数据,通过 ComputeShader 的方式,去将数据压缩后拷贝到 SourceRT,将 VirtualCapture.virtualTextArraySize * VirtualCapture.virtualTextArraySize 大小的 sRGB格式的图片压缩为 VirtualCapture.virtualTextArraySize/4 * VirtualCapture.virtualTextArraySize/4 ARGBFloat 格式