压缩纹理格式

WebGL API 提供了使用压缩纹理格式的方法。这些格式在增加纹理细节的同时,可以限制所需的额外显存。默认情况下,没有可用的压缩格式:必须先启用相应的压缩纹理格式扩展。

用法

除非另有说明,本文适用于 WebGL 1 和 2 上下文。

如果支持,纹理可以以压缩格式存储在显存中。这允许增加细节,同时限制所需的额外显存。在着色器访问纹理时,纹理会被即时解压缩。请注意,这种优势并不能转化为网络带宽:虽然这些格式比未压缩数据更好,但它们通常比 PNG 和 JPG 等标准图像格式差得多。

由于压缩纹理需要硬件支持,因此 WebGL 没有强制要求特定的格式;相反,根据硬件支持,上下文可以提供不同的格式。WebGL Texture Tester 网站显示了所用浏览器支持的格式。

使用压缩格式首先需要通过 WebGLRenderingContext.getExtension() 激活相应的扩展。如果支持,它将返回一个包含新增格式常量的扩展对象,并且可以通过调用 gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS) 来获取这些格式。(例如,对于 WEBGL_compressed_texture_s3tc 扩展,可以使用 ext.COMPRESSED_RGBA_S3TC_DXT1_EXT。)然后,可以使用 compressedTexImage[23]DcompressedTexSubImage[23]D 代替 texImage2D 调用。

请注意,WebGL 不提供压缩或解压缩纹理的功能:纹理必须已经是压缩格式,然后才能直接上传到显存。

所有格式都支持 2D 纹理。下表列出了支持 TEXTURE_2D_ARRAYTEXTURE_3D 目标(与 compressedTexImage3D 结合使用)的格式。

扩展名 注意 TEXTURE_2D_ARRAY TEXTURE_3D
WEBGL_compressed_texture_astc
WEBGL_compressed_texture_etc
WEBGL_compressed_texture_etc1* 不能与 compressedTexSubImage2D/copyTexSubImage2D 一起使用。
WEBGL_compressed_texture_pvrtc 宽度和高度必须是 2 的幂。
WEBGL_compressed_texture_s3tc 宽度和高度必须是 4 的倍数。
WEBGL_compressed_texture_s3tc_srgb 宽度和高度必须是 4 的倍数。 ?

示例

js
async function getCompressedTextureIfAvailable(gl) {
  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture); // create texture object on GPU
  const ext = gl.getExtension("WEBGL_compressed_texture_s3tc"); // will be null if not supported
  if (ext) {
    // the file is already in the correct compressed format
    const dataArrayBuffer = await fetch(
      "/textures/foobar512x512.RGBA_S3TC_DXT1",
    ).then((response) => response.arrayBuffer());
    gl.compressedTexImage2D(
      gl.TEXTURE_2D,
      0, // set the base image level
      ext.COMPRESSED_RGBA_S3TC_DXT1_EXT, // the compressed format we are using
      512,
      512, // width, height of the image
      0, // border, always 0
      new DataView(dataArrayBuffer),
    );
    gl.generateMipMap(gl.TEXTURE_2D); // create mipmap levels, like we would for a standard image
    return texture;
  }
}