Start · Sprachen · JavaScript · Referenz · EXT_texture_compression_bptc extension

EXT_texture_compression_bptc extension

Schnittstelle

WebGL-Erweiterung, die vier BPTC-komprimierte Texturformate (BC6H für HDR, BC7 für hochwertige RGBA-Daten) für <code>compressedTexImage2D</code> bereitstellt.

seit JavaScript WebGL 1 und WebGL 2; hauptsächlich auf Desktop-GPU Kategorie: webapi

Signatur

interface EXT_texture_compression_bptc

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');
}
BPTC verfügbar 8e8c

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));
65536

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)}`);
Lade Texturen im Format: bc7