压缩纹理格式

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

用法

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

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

由于压缩纹理需要硬件支持,因此 WebGL 不需要任何特定格式;相反,上下文可以提供不同的格式,具体取决于硬件支持。此网站显示了所用浏览器中支持的格式。

使用压缩格式首先需要使用 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;
  }
}