Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.texStorage3D()

WebGL2RenderingContext.texStorage3D()

Methode

Reserviert auf einen Schlag unveränderlichen Speicher für alle Mipmap-Ebenen einer 3D-Textur oder eines 2D-Textur-Arrays.

seit JavaScript WebGL 2.0 – Baseline: alle modernen Browser (seit Kategorie: webapi

Signatur

WebGL2RenderingContext.prototype.texStorage3D(target, levels, internalformat, width, height, depth)

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

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));
Ebenen: 6 immutable: true

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

// Wichtig · Fallstricke

  • Unveränderlich: Ein zweiter Aufruf von texStorage3D() oder ein texImage3D() auf dieselbe Textur erzeugt INVALID_OPERATION. Für eine neue Größe muss eine neue Textur erstellt werden.
  • INVALID_ENUM bei unzulässigem target oder unspezifiziertem internalformat; INVALID_VALUE bei Werten < 1 oder zu vielen levels; INVALID_OPERATION, wenn keine Textur gebunden ist.
  • Tiefen-/Stencil-Formate und viele komprimierte Formate sind für TEXTURE_3D nicht zulässig, nur für TEXTURE_2D_ARRAY.
  • Grenzen beachten: gl.MAX_3D_TEXTURE_SIZE (oft 256–2048) und gl.MAX_ARRAY_TEXTURE_LAYERS (mind. 256). 3D-Texturen verbrauchen schnell viel Grafikspeicher (512³ RGBA8 = 512 MB).
  • Float-Formate wie RGBA32F lassen sich ohne die Erweiterung OES_texture_float_linear nicht linear filtern.
  • Nur in WebGL 2 verfügbar; in WebGL 1 gibt es weder 3D-Texturen noch diese Methode.