Signatur
Beschreibung
Die Erweiterung WEBGL_compressed_texture_etc1 gehört zur WebGL API. Mit ihr kann man Texturen im Format ETC1 (Ericsson Texture Compression) direkt an die GPU übergeben. ETC1 speichert RGB-Daten mit 4 Bit pro Pixel in 4×4-Blöcken und ist auf fast allen OpenGL-ES-2.0-Geräten vorhanden, vor allem auf Android. Die GPU liest die Daten im komprimierten Zustand. Das spart Grafikspeicher und Bandbreite und verkürzt die Ladezeiten.
Das Erweiterungsobjekt bekommt man über gl.getExtension('WEBGL_compressed_texture_etc1'). Es hat keine Methoden, sondern nur eine Konstante:
ext.COMPRESSED_RGB_ETC1_WEBGL(0x8D64): RGB, ohne Alphakanal.
Die Konstante wird als internalformat-Argument an gl.compressedTexImage2D() übergeben. compressedTexSubImage2D() ist für ETC1 nicht erlaubt. Die Texturdaten müssen vorab mit Werkzeugen wie etcpak, PVRTexTool oder im KTX-Container erzeugt werden.
ETC1 bietet sich an, wenn man opake Texturen wie Gelände, Fotos oder Hintergründe für Mobilgeräte optimieren will. Für Texturen mit Transparenz und für WebGL 2 ist WEBGL_compressed_texture_etc (ETC2/EAC) die bessere Wahl. Plattformübergreifend lohnt sich ein Fallback auf S3TC, ASTC oder unkomprimierte Texturen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Erweiterungsname für gl.getExtension(): genau 'WEBGL_compressed_texture_etc1'. |
Rückgabewert
gl.getExtension() gibt das Erweiterungsobjekt mit der Konstante COMPRESSED_RGB_ETC1_WEBGL zurück. Wenn Browser oder GPU ETC1 nicht unterstützen, ist der Rückgabewert null.Beispiele
Erweiterung abfragen und Unterstützung prüfen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const ext = gl.getExtension('WEBGL_compressed_texture_etc1');
if (ext) {
console.log('ETC1 unterstützt, Format:', ext.COMPRESSED_RGB_ETC1_WEBGL.toString(16));
} else {
console.log('ETC1 nicht verfügbar');
}
// Alle komprimierten Formate des Kontexts auflisten
console.log(gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS));
ETC1-Textur aus Rohdaten hochladen
const loadEtc1Texture = async (gl, url, width, height) => {
const ext = gl.getExtension('WEBGL_compressed_texture_etc1');
if (!ext) throw new Error('ETC1 wird nicht unterstützt');
// Rohe ETC1-Blockdaten ohne Header: 8 Byte pro 4×4-Block
const buffer = await (await fetch(url)).arrayBuffer();
const expected = Math.ceil(width / 4) * Math.ceil(height / 4) * 8;
const data = new Uint8Array(buffer, 0, expected);
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.compressedTexImage2D(
gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_ETC1_WEBGL,
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('webgl');
const tex = await loadEtc1Texture(gl, 'textures/ground.etc1', 512, 512);
console.log(gl.getError() === gl.NO_ERROR ? 'Textur geladen' : 'Fehler');
Formatauswahl mit Fallback
const pickTextureFormat = (gl) => {
const astc = gl.getExtension('WEBGL_compressed_texture_astc');
if (astc) return { type: 'astc', ext: astc };
const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc');
if (s3tc) return { type: 's3tc', ext: s3tc };
const etc1 = gl.getExtension('WEBGL_compressed_texture_etc1');
if (etc1) return { type: 'etc1', ext: etc1 };
return { type: 'png', ext: null }; // unkomprimiert
};
const gl = document.createElement('canvas').getContext('webgl');
console.log('Lade Texturen im Format:', pickTextureFormat(gl).type);
// Wichtig · Fallstricke
- Kein Alphakanal: ETC1 speichert nur RGB. Für Transparenz braucht man eine zweite Textur als Alpha-Maske oder ETC2 (
WEBGL_compressed_texture_etc). - Kein
compressedTexSubImage2D(): Ein Aufruf mit ETC1 erzeugtINVALID_OPERATION. Teilbereiche lassen sich nicht aktualisieren. - Datengröße: Die Länge des
ArrayBufferViewmuss genauceil(w/4) * ceil(h/4) * 8Byte betragen. Sonst entstehtINVALID_VALUE. Header von KTX- oder PKM-Dateien muss man vorher abschneiden. - Mipmaps:
gl.generateMipmap()funktioniert bei komprimierten Texturen nicht. Jede Mip-Stufe muss einzeln hochgeladen werden. In WebGL 1 ist Mipmapping außerdem nur bei Seitenlängen mit Zweierpotenz möglich. - Kompatibilität: Die Unterstützung ist vor allem auf Android/mobilen GPUs verbreitet. Auf Desktop-GPUs und in Safari/iOS fehlt die Erweiterung oft. Deshalb immer auf
nullprüfen und einen Fallback vorsehen. Eine Alternative ist Basis Universal/KTX2, das zur Laufzeit in das passende Format umwandelt. - Rufen Sie
getExtension()auf, bevor Sie die Konstante verwenden. Erst dieser Aufruf aktiviert das Format im Kontext.