Signatur
Beschreibung
texStorage3D() legt für die gerade gebundene Textur vom Typ gl.TEXTURE_3D oder gl.TEXTURE_2D_ARRAY den Speicher für alle Mipmap-Ebenen auf einmal fest. Größe, Format und Anzahl der Ebenen gelten danach als unveränderlich (immutable storage). Die eigentlichen Pixeldaten werden erst anschließend mit texSubImage3D() oder compressedTexSubImage3D() hochgeladen.
Gegenüber mehrfachen texImage3D()-Aufrufen hat das Vorteile: Der Treiber kennt die komplette Textur von Anfang an, muss keine Vollständigkeitsprüfungen bei jedem Zeichenaufruf durchführen, und es können keine inkonsistenten Mipmap-Ketten entstehen. Deshalb ist texStorage3D() der empfohlene Weg, um Volumen-Texturen (z. B. für medizinische Daten, 3D-Rauschen, Farb-LUTs) oder Textur-Arrays (Sprite-Sheets, Terrain-Layer, Schatten-Kaskaden) anzulegen.
Als internalformat muss ein größenbehaftetes Format wie gl.RGBA8, gl.R16F oder gl.RGBA32F angegeben werden – unspezifizierte Formate wie gl.RGBA sind nicht erlaubt. Bei TEXTURE_3D wird bei jeder Mipmap-Ebene auch die Tiefe halbiert, bei TEXTURE_2D_ARRAY bleibt die Anzahl der Schichten (depth) auf allen Ebenen gleich.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Textur-Ziel: gl.TEXTURE_3D oder gl.TEXTURE_2D_ARRAY. |
|
| $levels Pflicht | GLsizei | Anzahl der Mipmap-Ebenen (mindestens 1). Maximal floor(log2(max(width, height[, depth]))) + 1. |
|
| $internalformat Pflicht | GLenum | Größenbehaftetes internes Format, z. B. gl.RGBA8, gl.R8, gl.RGBA16F, gl.DEPTH_COMPONENT24 oder ein komprimiertes Format einer aktiven Erweiterung. |
|
| $width Pflicht | GLsizei | Breite der Basisebene in Texeln. | |
| $height Pflicht | GLsizei | Höhe der Basisebene in Texeln. | |
| $depth Pflicht | GLsizei | Tiefe der 3D-Textur bzw. Anzahl der Schichten eines Textur-Arrays. |
Beispiele
Textur-Array für Sprite-Ebenen anlegen und befüllen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
const size = 64, layers = 4;
// Speicher für 1 Ebene, 4 Schichten à 64×64 RGBA8 reservieren
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, size, size, layers);
// Jede Schicht mit einer eigenen Farbe füllen
for (let layer = 0; layer < layers; layer++) {
const pixels = new Uint8Array(size * size * 4);
for (let i = 0; i < pixels.length; i += 4) {
pixels[i] = layer * 60;
pixels[i + 1] = 255 - layer * 60;
pixels[i + 2] = 128;
pixels[i + 3] = 255;
}
gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, layer,
size, size, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
}
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
console.log(gl.getError() === gl.NO_ERROR);
3D-Volumentextur mit vollständiger Mipmap-Kette
const gl = document.createElement('canvas').getContext('webgl2');
const w = 32, h = 32, d = 32;
const levels = Math.floor(Math.log2(Math.max(w, h, d))) + 1; // 6
const volume = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, volume);
gl.texStorage3D(gl.TEXTURE_3D, levels, gl.R8, w, h, d);
// Zufälliges Rauschen als Volumendaten
const data = new Uint8Array(w * h * d).map(() => Math.random() * 255);
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, w, h, d,
gl.RED, gl.UNSIGNED_BYTE, data);
gl.generateMipmap(gl.TEXTURE_3D);
console.log('Ebenen:', levels,
'immutable:', gl.getTexParameter(gl.TEXTURE_3D, gl.TEXTURE_IMMUTABLE_FORMAT));
Typischer Fehler: unspezifiziertes Format
const gl = document.createElement('canvas').getContext('webgl2');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
// gl.RGBA ist kein größenbehaftetes Format → Fehler
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA, 16, 16, 16);
console.log(gl.getError() === gl.INVALID_ENUM);
// Korrekt:
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 16, 16, 16);
console.log(gl.getError() === gl.NO_ERROR);
// Wichtig · Fallstricke
- Unveränderlich: Ein zweiter Aufruf von
texStorage3D()oder eintexImage3D()auf dieselbe Textur erzeugtINVALID_OPERATION. Für eine neue Größe muss eine neue Textur erstellt werden. INVALID_ENUMbei unzulässigemtargetoder unspezifizierteminternalformat;INVALID_VALUEbei Werten < 1 oder zu vielenlevels;INVALID_OPERATION, wenn keine Textur gebunden ist.- Tiefen-/Stencil-Formate und viele komprimierte Formate sind für
TEXTURE_3Dnicht zulässig, nur fürTEXTURE_2D_ARRAY. - Grenzen beachten:
gl.MAX_3D_TEXTURE_SIZE(oft 256–2048) undgl.MAX_ARRAY_TEXTURE_LAYERS(mind. 256). 3D-Texturen verbrauchen schnell viel Grafikspeicher (512³ RGBA8 = 512 MB). - Float-Formate wie
RGBA32Flassen sich ohne die ErweiterungOES_texture_float_linearnicht linear filtern. - Nur in WebGL 2 verfügbar; in WebGL 1 gibt es weder 3D-Texturen noch diese Methode.