Signatur
Beschreibung
Die Erweiterung WEBGL_compressed_texture_astc gehört zur WebGL-API und macht die Adaptive Scalable Texture Compression (ASTC) in WebGL nutzbar. ASTC ist ein blockbasiertes, verlustbehaftetes Kompressionsformat. Es arbeitet mit einer festen Blockgröße von 128 Bit, die je nach Blockabmessung (von 4×4 bis 12×12 Texel) zwischen 8 und 0,89 Bit pro Texel ergibt. So lässt sich Qualität gegen Speicherbedarf sehr fein abwägen.
Die Erweiterung erhältst du über gl.getExtension("WEBGL_compressed_texture_astc"). Das zurückgegebene Objekt enthält 28 Konstanten: je 14 Blockgrößen für lineare RGBA-Daten (COMPRESSED_RGBA_ASTC_4x4_KHR … COMPRESSED_RGBA_ASTC_12x12_KHR) und für sRGB-Daten (COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR … _12x12_KHR). Diese Konstanten übergibst du als internalformat an gl.compressedTexImage2D(), in WebGL 2 zusätzlich an compressedTexSubImage2D() und texStorage2D().
Außerdem gibt es die Methode getSupportedProfiles(). Sie liefert ein Array mit den unterstützten ASTC-Profilen, also "ldr" (Low Dynamic Range) und gegebenenfalls "hdr" (High Dynamic Range). Weil ASTC nur auf bestimmter Hardware läuft (die meisten modernen Mobil-GPUs, Apple-GPUs, einige Intel-GPUs, aber selten Desktop-GPUs von NVIDIA/AMD), solltest du immer ein Ersatzformat bereithalten, etwa S3TC/BPTC, ETC2 oder unkomprimierte Texturen.
Rückgabewert
gl.getExtension() gibt das Erweiterungsobjekt mit den ASTC-Konstanten und der Methode getSupportedProfiles() zurück. Unterstützt die Plattform ASTC nicht, ist der Rückgabewert null.Beispiele
Erweiterung abfragen und Profile prüfen
const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl2") ?? canvas.getContext("webgl");
const astc = gl.getExtension("WEBGL_compressed_texture_astc");
if (astc) {
console.log("ASTC-Profile:", astc.getSupportedProfiles());
console.log("4x4-Format:", astc.COMPRESSED_RGBA_ASTC_4x4_KHR.toString(16));
} else {
console.log("ASTC wird nicht unterstützt – Ersatzformat verwenden.");
}
ASTC-Datei (.astc) laden und als Textur hochladen
// .astc-Header: 16 Byte (Magic, Blockmaße, Bildmaße als 24-Bit-Werte)
const loadAstcTexture = async (gl, url) => {
const ext = gl.getExtension("WEBGL_compressed_texture_astc");
if (!ext) throw new Error("ASTC nicht verfügbar");
const buffer = await (await fetch(url)).arrayBuffer();
const header = new Uint8Array(buffer, 0, 16);
const magic = new DataView(buffer).getUint32(0, true);
if (magic !== 0x5ca1ab13) throw new Error("Keine gültige .astc-Datei");
const blockX = header[4];
const blockY = header[5];
const width = header[7] | (header[8] << 8) | (header[9] << 16);
const height = header[10] | (header[11] << 8) | (header[12] << 16);
// Passende Format-Konstante über den Namen ermitteln
const format = ext[`COMPRESSED_RGBA_ASTC_${blockX}x${blockY}_KHR`];
if (format === undefined) throw new Error(`Blockgröße ${blockX}x${blockY} unbekannt`);
const data = new Uint8Array(buffer, 16);
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, 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 texture;
};
const gl = document.querySelector("canvas").getContext("webgl2");
loadAstcTexture(gl, "/textures/stein_6x6.astc")
.then(() => console.log("Textur geladen"))
.catch((err) => console.warn(err.message));
Bestes Kompressionsformat mit Ersatzlösung wählen
const pickTextureFormat = (gl) => {
const candidates = [
["astc", "WEBGL_compressed_texture_astc"],
["bptc", "EXT_texture_compression_bptc"],
["s3tc", "WEBGL_compressed_texture_s3tc"],
["etc", "WEBGL_compressed_texture_etc"],
];
for (const [name, extName] of candidates) {
if (gl.getExtension(extName)) return name;
}
return "png"; // unkomprimiert
};
const gl = document.createElement("canvas").getContext("webgl2");
console.log(`Lade Texturen im Format: ${pickTextureFormat(gl)}`);
// Wichtig · Fallstricke
- Hardwareabhängig: Auf den meisten Desktop-GPUs von NVIDIA und AMD liefert
getExtension()null. Auf iOS, Android und Apple-Silicon-Macs ist ASTC dagegen weit verbreitet. Prüfe die Unterstützung immer zur Laufzeit. - Datengröße muss exakt stimmen: Die Bytelänge ergibt sich aus
ceil(width / blockX) * ceil(height / blockY) * 16. Passt sie nicht, meldetcompressedTexImage2D()INVALID_VALUE. - HDR-Profil: HDR-Daten funktionieren nur, wenn
getSupportedProfiles()den Wert"hdr"enthält. Andernfalls werden HDR-Blöcke als Fehlerfarbe (Magenta) dekodiert. - sRGB: Für Farbtexturen solltest du die
COMPRESSED_SRGB8_ALPHA8_ASTC_*-Formate nutzen, damit die Gammakorrektur stimmt. Für Normal- und Datenkarten sind die linearenRGBA-Formate richtig. - Mipmaps lassen sich für komprimierte Texturen nicht mit
generateMipmap()erzeugen. Jede Ebene muss vorkomprimiert mitgeliefert werden. - Nur 2D-Texturen und Cubemaps (sowie 2D-Arrays in WebGL 2) werden unterstützt. 3D-ASTC ist nicht Teil dieser Erweiterung.
- In Firefox kann die Erweiterung hinter
webgl.enable-draft-extensionsliegen, abhängig von Version und Treiber.