MAKE · WRITE · SHARE

Base-纹理格式与GPU压缩

一张 PNG 只有几百 KB,进入引擎后却占用几 MB,并不一定是资源导入出了问题。磁盘上的图像压缩与 GPU 上可随机采样的纹理格式,优化的是不同访问方式。

判断纹理成本,要把磁盘文件、上传数据、GPU 存储、Mipmap 和运行时采样分开。只比较源文件大小,容易得到错误的显存预算。

源图文件、GPU 块压缩和 Mipmap 驻留是不同层次的成本

1. 图像文件与纹理资源

PNG、JPEG、TGA 描述资产存储,GPU 资源则有尺寸、通道、格式、层级与用途。源文件通常会在导入或构建阶段转换;运行时也可以解码和转码,但要承担相应时间与临时内存。

未压缩的 RGBA8 每个纹素 4 字节。2048×2048 的第 0 级为 16 MiB;加上完整二维 Mipmap 链约为 21.33 MiB。这里不包含布局对齐和其他资源副本。

2. 为什么 GPU 偏爱块压缩

块压缩将固定区域编码为固定或受控大小的数据,使硬件能够在采样时局部解码,而不必先解开整张图片。它在压缩率、局部可寻址和解码成本之间权衡。

对于每块 b 字节、块宽高 bx/by 的格式,某一 Mip 的近似数据量是:

1
ceil(width/bx) * ceil(height/by) * b

最小 Mip 也可能占一个完整压缩块,因此不能始终用“宽×高×每像素位数”精确计算所有小层级。

3. 格式家族与数据类型

BC 家族包含适合颜色、单/双通道和 HDR 数据的不同格式。BC1 的典型块为 4×4、8 字节,BC7 的典型块为 4×4、16 字节;因此 2048 方图第 0 级分别约为 2 MiB 与 4 MiB。

ASTC 使用不同块尺寸调节码率;较大的块通常降低存储,也提高细节损失风险。ETC/EAC 与 PVRTC 也有不同通道和能力组合,不能把一整个家族当成单一 RGB/Alpha 规则。

格式支持取决于设备、API、扩展和引擎后端。旧笔记按系统版本或“安卓/iOS”直接划分支持情况过于粗略,应查询实际能力,并检查不支持时的解压回退成本。

原笔记截取的旧版 Unity 平台默认格式表,仅作历史导入策略示例

原笔记配图:原笔记截取的旧版 Unity 平台默认格式表,仅作历史导入策略示例;图中默认格式不代表当前版本或所有设备。

4. 通道语义比文件扩展名重要

Base Color 需要保持颜色外观,法线需要保持方向,高度和 Mask 需要保持数值关系。某种格式在彩色照片上很好看,不代表适合精细法线或平滑梯度。

有无 Alpha、Alpha 是否需要连续值、是否有 HDR 范围,也会改变选择。把几个 Mask 打包到 RGBA 可以减少资源数量,但如果它们采样频率、精度或压缩需求不同,打包未必最省。

颜色纹理可能需要 sRGB 解释,法线和粗糙度一般需要线性数据解释。压缩格式与颜色解释是两个维度,不能用“压缩过”判断是否需要 Gamma 转换。

5. 压缩率不等于质量

块边界、渐变色带、法线方向偏差与 Alpha 轮廓,都是典型观察点。检查应包含放大图、实际镜头距离、运动与 Mipmap,而不只看源图静态截图。

纹理分辨率、块尺寸和导入设置可以组合优化。先降低无贡献的高频或过高分辨率,再选择压缩,往往比对所有贴图使用最高质量格式合理。

6. 存储和带宽预算分别算

压缩可能减少显存占用与纹理传输量,但采样成本仍受缓存、过滤、坐标访问模式与工作集影响。各向异性过滤不会固定把纹理存储变成三倍,也不能靠 PNG 大小推断带宽。

Streaming 和虚拟纹理控制哪些层级或页面常驻;它们与块压缩可以同时使用,解决的是驻留管理与每块数据大小两个层面。

总结

纹理预算从目标 GPU 资源格式开始计算,而不是从源文件开始猜。先明确通道语义与设备支持,再计算完整层级、观察压缩误差,并在实际画面中验证采样成本。

参考资料