Start · Sprachen · JavaScript · Referenz · WEBGL_compressed_texture_astc extension

WEBGL_compressed_texture_astc extension

Schnittstelle

WebGL-Erweiterung, die ASTC-komprimierte Texturformate (Blockgrößen 4×4 bis 12×12, linear und sRGB) für <code>compressedTexImage2D()</code> bereitstellt.

seit JavaScript WebGL 1 / WebGL 2 – verfügbar je nach GPU (v. a. M Kategorie: webapi

Signatur

interface WEBGL_compressed_texture_astc

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

Typ
WEBGL_compressed_texture_astc | null
Beschreibung
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-Profile: ["ldr"] 4x4-Format: 93b0

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));
Textur geladen

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)}`);
Lade Texturen im Format: astc (z. B. auf iPhone/Android)

// 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, meldet compressedTexImage2D() 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 linearen RGBA-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-extensions liegen, abhängig von Version und Treiber.