Signatur
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
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");
}
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");
// 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()aufnullund sieh einen Fallback vor, etwa mit Basis Universal/KTX2. - Größe der Daten: Die Länge des übergebenen
ArrayBufferViewmuss genau zur Blockgröße passen:ceil(w/4) * ceil(h/4) * 8bei DXT1 bzw.* 16bei DXT3/DXT5. Stimmt sie nicht, bricht der Aufruf mitINVALID_VALUEab. - Abmessungen: Für
compressedTexSubImage2Dmü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_s3tcund muss separat aktiviert werden.