Signatur
Beschreibung
Die Eigenschaft unpackColorSpace eines WebGL-Kontexts (WebGLRenderingContext und WebGL2RenderingContext) bestimmt den Ziel-Farbraum für Texturdaten. Lädst du ein HTMLImageElement, ImageBitmap, HTMLVideoElement, HTMLCanvasElement, OffscreenCanvas oder ImageData mit texImage2D() oder texSubImage2D() hoch, konvertiert der Browser die Pixel vorher aus dem Quell-Farbraum in diesen Farbraum.
Gültige Werte sind "srgb" (Standard) und "display-p3". Mit "display-p3" bleibt der erweiterte Farbumfang von P3-Bildern erhalten (z. B. Fotos von aktuellen Smartphones), sonst werden sie auf sRGB beschnitten. Die Eigenschaft ist lesbar und schreibbar. Eine Änderung wirkt nur auf nachfolgende Uploads, bereits hochgeladene Texturen bleiben unverändert.
Setze die Eigenschaft in der Regel passend zu drawingBufferColorSpace. So liegen Texturen und Ausgabepuffer im selben Farbraum, und Shader rechnen konsistent. Ob die Konvertierung überhaupt stattfindet, hängt außerdem vom Pixelspeicher-Parameter UNPACK_COLORSPACE_CONVERSION_WEBGL ab. Steht er auf gl.NONE, findet keine Farbraum-Konvertierung statt.
Rückgabewert
"srgb". Beim Setzen sind nur diese beiden Werte erlaubt.Beispiele
Aktuellen Wert auslesen und Unterstützung prüfen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2') ?? canvas.getContext('webgl');
if ('unpackColorSpace' in gl) {
console.log('unpackColorSpace:', gl.unpackColorSpace);
} else {
console.log('unpackColorSpace wird nicht unterstützt');
}
P3-Foto ohne Farbverlust als Textur laden
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
// Nur auf P3 umschalten, wenn der Bildschirm den Farbraum darstellen kann
const wideGamut = matchMedia('(color-gamut: p3)').matches;
if (wideGamut && 'unpackColorSpace' in gl) {
gl.drawingBufferColorSpace = 'display-p3';
gl.unpackColorSpace = 'display-p3';
}
const loadTexture = async (url) => {
const img = new Image();
img.src = url;
await img.decode();
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// Wird jetzt in den Farbraum aus unpackColorSpace konvertiert
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
return tex;
};
const texture = await loadTexture('/bilder/sonnenuntergang-p3.jpg');
console.log(gl.unpackColorSpace);
Farbraum zwischen Uploads umschalten
const gl = document.createElement('canvas').getContext('webgl2');
const bitmap = await createImageBitmap(await (await fetch('/icon.png')).blob());
const texSrgb = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texSrgb);
gl.unpackColorSpace = 'srgb';
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
const texP3 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texP3);
gl.unpackColorSpace = 'display-p3'; // betrifft nur diesen und folgende Uploads
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
gl.unpackColorSpace = 'rec2020'; // ungültig: Wert wird ignoriert
console.log(gl.unpackColorSpace);
// Wichtig · Fallstricke
- Browserunterstützung: Chromium-Browser ab Version 104 und Safari ab 16.4 unterstützen die Eigenschaft. Firefox unterstützt sie derzeit nicht. Prüfe sie deshalb mit
'unpackColorSpace' in gl. Ohne Unterstützung werden Texturen wie bisher als sRGB behandelt. - Nur für Bildquellen: Rohdaten aus
ArrayBufferViews (z. B.Uint8Array) werden nie konvertiert. Die Eigenschaft wirkt nur auf DOM- und Bild-Objekte. - Konvertierung ausschalten: Mit
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE)findet keine Konvertierung statt. Das ist wichtig für Daten-Texturen wie Normal Maps, Höhenkarten oder Lookup-Tabellen, deren Werte nicht verändert werden dürfen. - Ungültige Werte: Andere Strings als
"srgb"oder"display-p3"werden ignoriert, der bisherige Wert bleibt erhalten. Je nach Implementierung erscheint eine Warnung in der Konsole. - Kein Gamma-Ersatz: Die Eigenschaft ändert nur die Farbprimärfarben (Gamut). Lineares Rechnen im Shader musst du weiterhin selbst umsetzen oder dafür sRGB-Texturformate wie
SRGB8_ALPHA8verwenden. - Leistung: Die Konvertierung kostet beim Upload etwas Zeit. Das kann bei vielen Video-Frames pro Sekunde messbar sein.