壓縮紋理格式
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]D 或 compressedTexSubImage[23]D 代替 texImage2D 呼叫。
請注意,WebGL 不提供壓縮或解壓縮紋理的功能:紋理必須已經是壓縮格式,然後才能直接上傳到視訊記憶體。
所有格式都支援 2D 紋理。下表列出了支援 TEXTURE_2D_ARRAY 和 TEXTURE_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 的倍數。 | ? | 否 |
示例
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;
}
}