Start · Sprachen · JavaScript · Referenz · WEBGL_compressed_texture_s3tc_srgb extension

WEBGL_compressed_texture_s3tc_srgb extension

Schnittstelle

WebGL-Erweiterung, die vier S3TC-komprimierte Texturformate (DXT1, DXT1a, DXT3, DXT5) im sRGB-Farbraum bereitstellt.

seit JavaScript WebGL 1 / WebGL 2 (Erweiterung); überwiegend Deskt Kategorie: webapi

Signatur

interface WEBGL_compressed_texture_s3tc_srgb

Beschreibung

Die Erweiterung WEBGL_compressed_texture_s3tc_srgb gehört zur WebGL-API. Sie erlaubt es, S3TC-komprimierte Texturen (auch als DXT oder BC1–BC3 bekannt) direkt als sRGB-kodierte Daten an die GPU zu übergeben. Beim Abtasten im Shader wandelt die Hardware die Farbwerte automatisch vom sRGB-Farbraum in linearen Farbraum um. Die Beleuchtung wird dadurch korrekt berechnet, ohne dass man im Shader selbst eine Gammakorrektur schreiben muss.

Man bekommt die Erweiterung über gl.getExtension("WEBGL_compressed_texture_s3tc_srgb"). Das zurückgegebene Objekt hat keine Methoden, sondern nur vier Konstanten. Diese übergibt man als internalformat an compressedTexImage2D(), compressedTexSubImage2D() oder (in WebGL 2) an texStorage2D():

  • COMPRESSED_SRGB_S3TC_DXT1_EXT (0x8C4C): RGB, 8 Byte pro 4×4-Block.
  • COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT (0x8C4D): RGBA mit 1-Bit-Alpha, 8 Byte pro Block.
  • COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT (0x8C4E): RGBA mit explizitem 4-Bit-Alpha, 16 Byte pro Block.
  • COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT (0x8C4F): RGBA mit interpoliertem Alpha, 16 Byte pro Block.

Sinnvoll ist die Erweiterung für Farb- und Albedo-Texturen (Diffuse-Maps, UI-Grafiken, Fotos), die in sRGB erstellt wurden. Normal-Maps, Roughness-Maps und andere Datentexturen sollte man dagegen nicht als sRGB hochladen. Für sie nimmt man die linearen Formate aus WEBGL_compressed_texture_s3tc.

Parameter

Name Typ Default Beschreibung
$COMPRESSED_SRGB_S3TC_DXT1_EXT GLenum (0x8C4C) Konstante: sRGB-Farbdaten im DXT1-Format ohne Alpha, 8 Byte pro 4×4-Block.
$COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT GLenum (0x8C4D) Konstante: sRGB-Farbdaten im DXT1-Format mit 1-Bit-Alpha (voll transparent oder voll deckend).
$COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT GLenum (0x8C4E) Konstante: sRGB-Farbdaten im DXT3-Format mit explizitem 4-Bit-Alpha, 16 Byte pro Block. Eignet sich für harte Alpha-Übergänge.
$COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT GLenum (0x8C4F) Konstante: sRGB-Farbdaten im DXT5-Format mit interpoliertem Alpha, 16 Byte pro Block. Eignet sich für weiche Alpha-Verläufe.

Rückgabewert

Typ
WEBGL_compressed_texture_s3tc_srgb | null
Beschreibung
gl.getExtension() gibt das Erweiterungsobjekt mit den vier Konstanten zurück. Wird die Erweiterung nicht unterstützt, ist der Rückgabewert null.

Beispiele

Erweiterung abfragen und Formate auflisten

const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl2") ?? canvas.getContext("webgl");

const ext = gl.getExtension("WEBGL_compressed_texture_s3tc_srgb");

if (ext) {
  console.log("DXT1 sRGB:", ext.COMPRESSED_SRGB_S3TC_DXT1_EXT.toString(16));
  console.log("DXT5 sRGB:", ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT.toString(16));
} else {
  console.log("S3TC-sRGB wird nicht unterstützt");
}
DXT1 sRGB: 8c4c DXT5 sRGB: 8c4f

DXT5-sRGB-Textur aus DDS-Daten hochladen

const loadSrgbDxt5 = async (gl, url, width, height) => {
  const ext = gl.getExtension("WEBGL_compressed_texture_s3tc_srgb");
  if (!ext) throw new Error("S3TC-sRGB nicht verfügbar");

  const buffer = await (await fetch(url)).arrayBuffer();
  // DDS-Header ist 128 Byte groß (ohne DX10-Erweiterung)
  const blocks = Math.ceil(width / 4) * Math.ceil(height / 4);
  const data = new Uint8Array(buffer, 128, blocks * 16);

  const tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  gl.compressedTexImage2D(
    gl.TEXTURE_2D, 0,
    ext.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_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;
};

const gl = document.querySelector("canvas").getContext("webgl2");
const albedo = await loadSrgbDxt5(gl, "/textures/albedo.dds", 512, 512);

Format mit Fallback auswählen (WebGL 2 texStorage2D)

const pickAlbedoFormat = (gl) => {
  const srgb = gl.getExtension("WEBGL_compressed_texture_s3tc_srgb");
  if (srgb) return { format: srgb.COMPRESSED_SRGB_S3TC_DXT1_EXT, compressed: true };
  // Fallback: unkomprimiertes sRGB8 (nur WebGL 2)
  return { format: gl.SRGB8_ALPHA8, compressed: false };
};

const gl = document.createElement("canvas").getContext("webgl2");
const { format, compressed } = pickAlbedoFormat(gl);

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// Unveränderlichen Speicher für 256×256 inkl. 9 Mip-Stufen reservieren
gl.texStorage2D(gl.TEXTURE_2D, 9, format, 256, 256);
console.log(compressed ? "S3TC-sRGB aktiv" : "Fallback SRGB8_ALPHA8");
S3TC-sRGB aktiv

// Wichtig · Fallstricke

  • Browser-Unterstützung: S3TC ist ein Desktop-Format. Auf Windows, macOS und Linux gibt es die Erweiterung meist, auf Mobilgeräten (Android/iOS) oft nicht. Dort sind ETC2, ASTC oder PVRTC üblich. Prüfe deshalb immer den Rückgabewert von getExtension() auf null und sieh einen Fallback vor, etwa mit Basis Universal/KTX2.
  • Größe der Daten: Die Länge des übergebenen ArrayBufferView muss genau zur Blockgröße passen: ceil(w/4) * ceil(h/4) * 8 bei DXT1 bzw. * 16 bei DXT3/DXT5. Stimmt sie nicht, bricht der Aufruf mit INVALID_VALUE ab.
  • Abmessungen: Für compressedTexSubImage2D müssen Offsets und Größen Vielfache von 4 sein. Ausnahme sind die kleinsten Mip-Stufen am Rand.
  • Mipmaps: gl.generateMipmap() funktioniert mit komprimierten Formaten nicht. Jede Mip-Stufe muss man vorab erzeugen und einzeln hochladen.
  • Richtiger Farbraum: Lade nur echte Farbdaten als sRGB hoch. Normal- und Datentexturen werden sonst durch die automatische Umwandlung verfälscht.
  • Die Erweiterung ist unabhängig von WEBGL_compressed_texture_s3tc und muss separat aktiviert werden.