壓縮紋理格式

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;
  }
}