Signatur
Beschreibung
EXT_texture_compression_bptc ist eine WebGL-Erweiterung. Sie macht die BPTC-Kompressionsformate nutzbar, die in DirectX als BC6H und BC7 bekannt sind. BC7 (*_BPTC_UNORM) speichert 8-Bit-RGBA-Daten in hoher Qualität. BC6H (*_BPTC_*_FLOAT) speichert HDR-RGB-Daten als Gleitkommazahlen und eignet sich z. B. für Environment-Maps oder Lightmaps.
Du bekommst die Erweiterung über gl.getExtension("EXT_texture_compression_bptc"). Ist sie verfügbar, erhältst du ein Objekt mit vier Konstanten. Diese übergibst du als internalformat an compressedTexImage2D(), compressedTexSubImage2D() oder, in WebGL 2, an texStorage2D(). Das Objekt hat keine eigenen Methoden.
COMPRESSED_RGBA_BPTC_UNORM_EXT(0x8E8C): RGBA, linear (BC7)COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT(0x8E8D): RGBA im sRGB-Farbraum (BC7)COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT(0x8E8E): HDR-RGB, vorzeichenbehaftet (BC6H)COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT(0x8E8F): HDR-RGB, ohne Vorzeichen (BC6H)
Alle Formate komprimieren Blöcke aus 4×4 Pixeln auf jeweils 16 Byte, also 1 Byte pro Pixel. Die komprimierten Daten musst du vorab erzeugen, z. B. mit Werkzeugen wie compressonator, texconv oder über KTX2/Basis Universal. WebGL komprimiert die Daten nicht selbst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $COMPRESSED_RGBA_BPTC_UNORM_EXT | GLenum (0x8E8C) | Konstante: BC7-Format für lineare RGBA-Daten mit 8 Bit pro Kanal. | |
| $COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT | GLenum (0x8E8D) | Konstante: BC7-Format, Farbwerte im sRGB-Farbraum. Die GPU wandelt sie beim Sampeln automatisch in linearen Raum um. | |
| $COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT | GLenum (0x8E8E) | Konstante: BC6H-Format für HDR-RGB mit vorzeichenbehafteten Gleitkommawerten, ohne Alphakanal. | |
| $COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT | GLenum (0x8E8F) | Konstante: BC6H-Format für HDR-RGB mit nicht-negativen Gleitkommawerten, ohne Alphakanal. |
Beispiele
Verfügbarkeit prüfen und Formate auflisten
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2') ?? canvas.getContext('webgl');
const bptc = gl.getExtension('EXT_texture_compression_bptc');
if (bptc) {
console.log('BPTC verfügbar');
console.log(bptc.COMPRESSED_RGBA_BPTC_UNORM_EXT.toString(16));
} else {
console.log('BPTC nicht verfügbar – Ersatzformat nötig');
}
BC7-Textur hochladen (WebGL 1 und 2)
// Größe der BPTC-Daten berechnen: 16 Byte je 4×4-Block
const bptcByteSize = (w, h) => Math.ceil(w / 4) * Math.ceil(h / 4) * 16;
const uploadBC7 = async (gl, url, width, height) => {
const ext = gl.getExtension('EXT_texture_compression_bptc');
if (!ext) throw new Error('BPTC wird nicht unterstützt');
// Rohe BC7-Blockdaten laden (ohne Header, z. B. aus einer KTX-Datei extrahiert)
const buffer = await (await fetch(url)).arrayBuffer();
const data = new Uint8Array(buffer, 0, bptcByteSize(width, height));
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.compressedTexImage2D(
gl.TEXTURE_2D, 0,
ext.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
width, height, 0, data
);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
return tex;
};
console.log(bptcByteSize(256, 256));
HDR-Environment-Map mit BC6H und texStorage2D (WebGL 2)
const uploadHDR = (gl, levels) => {
// levels: [{ width, height, data: Uint8Array }, ...] – Mip-Kette in BC6H
const ext = gl.getExtension('EXT_texture_compression_bptc');
if (!ext) return null;
const fmt = ext.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texStorage2D(gl.TEXTURE_2D, levels.length, fmt, levels[0].width, levels[0].height);
levels.forEach(({ width, height, data }, i) => {
gl.compressedTexSubImage2D(gl.TEXTURE_2D, i, 0, 0, width, height, fmt, data);
});
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
return tex;
};
Passendes Kompressionsformat auswählen
const pickCompressedFormat = (gl) => {
const candidates = [
['EXT_texture_compression_bptc', 'bc7'],
['WEBGL_compressed_texture_astc', 'astc'],
['WEBGL_compressed_texture_etc', 'etc2'],
['WEBGL_compressed_texture_s3tc', 'dxt']
];
for (const [name, label] of candidates) {
if (gl.getExtension(name)) return label;
}
return 'png'; // unkomprimierter Ersatz
};
const gl = document.createElement('canvas').getContext('webgl2');
console.log(`Lade Texturen im Format: ${pickCompressedFormat(gl)}`);