Android-WebGL 支持哪些纹理压缩格式?

What texture compression formats are available on Android-WebGL?

我正在处理一些大型纹理的 WebGL,并且已经到了必须使用纹理压缩来缓解 VRAM 和上传时间问题的地步。

我的应用程序需要在过去两三年的 iOS 和 Android 手机上 运行。这一次,桌面支持并不重要。

我知道 Chrome 和 iOS 中的 Safari 将允许我以 PVRTC 格式传递纹理,因为所有 iOS 设备都使用 PowerVR GPU 芯片组。所以 iOS 是一个已解决的问题。

我还了解到几乎所有 Android 手机都正式支持爱立信纹理压缩(ETC、ETC1)——这实际上是 OpenGL 2 规范强制要求的。但是,我读过一些报道,某些 Android 实例上的某些浏览器实际上以未压缩的方式传递 ETC1 纹理。

WebGLStats 非常明确地警告我不要使用 WEBGL_compressed_texture_etc1 扩展名:

Warning DO NOT USE. Often implemented in browsers by decompressing on the CPU and uploading full size to GPU with severe performance, vram and quality impacts. Fixed in Chrome 57 and Firefox ??.

我知道的另一种常见格式是 S3TC。这在台式机上得到很好的支持,但 Android 可操作性似乎仅限于使用 NVIDIA 芯片组的设备。我相信这些已经过时了(仅限 Tegra?)。

要选择适用于现代 Android 手机的纹理压缩格式,我的最佳选择是什么?

What texture compression formats are available on Android-WebGL?

这取决于设备上的GPU/driver/browser

您可以使用

检查特定设备
 gl.getSupportedExtensions();

截至 2017 年 7 月 15 日检查 webglstats.com 它声称

  • 无android设备支持s3tc
  • 2% 的设备支持 pvrtc
  • 97% 的设备支持 etc1
  • 97% 的设备支持 etc
  • 48% 的设备支持 atc
  • 46% 的设备支持 astc

我 99% 确定它不完全准确,因为我很确定 NVidia Shield 支持 s3tc,但也许没有人使用 NVidia Shield 曾经访问过使用 webglstats.com 或可能是数字的网站用户数量太少,四舍五入为 0%

What is my best option for choosing a texture compression format that will work on modern Android phones?

你应该做的是支持所有的 etc1,etc,atc,astc。将您的资产存储在文件夹中或使用扩展名等

assets/etc1/image1
assets/etc1/image2
assets/astc/image1
assets/astc/image2
...

assets/image1.etc1
assets/image2.etc1
assets/image1.astc
assets/image2.astc
...

然后在启动时查询用户设备支持的格式并选择最佳格式(对于 最佳 的某些定义,例如最小尺寸)

示例

// in order of best compression to worst
const compressions = [
   { ext: "astc", name: "WEBGL_compressed_texture_astc" },
   { ext: "etc1", name: "WEBGL_compressed_texture_etc1" },
   ...
];
let imageExtension = ""; // pick a default?
for (let i = 0; i < compressions.length; ++i) {
  const info = compressions[i];
  const ext = gl.getExtension(info.name);
  if (ext) {
    imageExtension = info.ext;
    break;
  }
}

function loadImage(baseUrl) {
   ...
   img.src = baseUrl + imageExtension;
   ...
}

或者上述的其他变体,您可以在其中找出用户设备需要什么,然后使用它。