压缩纹理格式
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]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;
}
}