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

WebGL2RenderingContext.texSubImage3D()

Methode

Überschreibt einen quaderförmigen Teilbereich einer bereits angelegten 3D-Textur oder eines 2D-Textur-Arrays mit neuen Pixeldaten, ohne den Speicher neu zu belegen.

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

Signatur

WebGL2RenderingContext.prototype.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, srcData, srcOffset?)

Beschreibung

texSubImage3D() schreibt Pixeldaten in einen Teilbereich einer schon angelegten Textur vom Typ gl.TEXTURE_3D oder gl.TEXTURE_2D_ARRAY. Der Bereich wird über einen Versatz (xoffset, yoffset, zoffset) und eine Größe (width, height, depth) festgelegt. Bei Textur-Arrays steht die z-Achse für den Index der Ebene (Layer).

Anders als texImage3D() belegt die Methode keinen neuen Speicher. Sie aktualisiert nur vorhandene Texel. Deshalb eignet sie sich für häufige Updates, etwa für Volumendaten beim Streaming, Sprite-Atlanten in Textur-Arrays oder das nachträgliche Befüllen einzelner Ebenen. Der Speicher wird vorher mit texStorage3D() (unveränderlich, empfohlen) oder mit texImage3D() angelegt.

Die Methode hat mehrere Überladungen. Die Quelle kann ein ArrayBufferView sein (optional mit srcOffset), ein Byte-Versatz in einen gebundenen PIXEL_UNPACK_BUFFER oder eine DOM-Bildquelle wie ImageBitmap, ImageData, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement oder OffscreenCanvas. format und type müssen zum internen Format der Textur passen.

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Ziel der Textur: gl.TEXTURE_3D oder gl.TEXTURE_2D_ARRAY.
$level Pflicht GLint Mipmap-Stufe. 0 ist das Basisbild.
$xoffset Pflicht GLint Versatz in x-Richtung (Texel) innerhalb der Textur.
$yoffset Pflicht GLint Versatz in y-Richtung (Texel).
$zoffset Pflicht GLint Versatz in z-Richtung. Bei TEXTURE_2D_ARRAY ist das der Index der ersten Ebene.
$width Pflicht GLsizei Breite des Teilbereichs in Texeln.
$height Pflicht GLsizei Höhe des Teilbereichs in Texeln.
$depth Pflicht GLsizei Tiefe des Teilbereichs bzw. Anzahl der Ebenen.
$format Pflicht GLenum Format der Quelldaten, z. B. gl.RGBA, gl.RED, gl.RG, gl.RGBA_INTEGER.
$type Pflicht GLenum Datentyp der Quelldaten, z. B. gl.UNSIGNED_BYTE, gl.FLOAT, gl.HALF_FLOAT.
$srcData Pflicht ArrayBufferView | null | GLintptr | ImageBitmap | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | VideoFrame Quelle der Pixel. Ein typisiertes Array, das zu type passt (z. B. Uint8Array für UNSIGNED_BYTE), ein Byte-Versatz in den gebundenen PIXEL_UNPACK_BUFFER oder eine Bildquelle.
$srcOffset GLuint 0 Nur bei ArrayBufferView: Startindex in Elementen (nicht in Bytes), ab dem gelesen wird.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler werden über gl.getError() gemeldet.

Beispiele

3D-Textur anlegen und einen Teilquader aktualisieren

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');

const size = 32;
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
// Unveränderlichen Speicher anlegen: 32×32×32 Texel, RGBA8
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, size, size, size);

// 8×8×8-Block mit Rot füllen, beginnend bei (4, 4, 4)
const w = 8, h = 8, d = 8;
const data = new Uint8Array(w * h * d * 4);
for (let i = 0; i < data.length; i += 4) {
  data[i] = 255;     // R
  data[i + 3] = 255; // A
}

gl.texSubImage3D(gl.TEXTURE_3D, 0, 4, 4, 4, w, h, d, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(gl.getError() === gl.NO_ERROR);
true

Einzelne Ebene eines Textur-Arrays mit einem Bild befüllen

const gl = document.querySelector('canvas').getContext('webgl2');

const layers = 4, size = 256;
const texArray = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D_ARRAY, texArray);
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, size, size, layers);
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

const loadLayer = async (url, layer) => {
  const blob = await (await fetch(url)).blob();
  const bitmap = await createImageBitmap(blob, { resizeWidth: size, resizeHeight: size });
  gl.bindTexture(gl.TEXTURE_2D_ARRAY, texArray);
  // depth = 1 -> genau eine Ebene, zoffset = Ebenenindex
  gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, layer, size, size, 1,
    gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
  bitmap.close();
};

await loadLayer('/img/gras.png', 0);
await loadLayer('/img/stein.png', 1);
console.log('Ebenen geladen');
Ebenen geladen

Float-Volumendaten mit srcOffset hochladen

const gl = document.createElement('canvas').getContext('webgl2');

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
gl.texStorage3D(gl.TEXTURE_3D, 1, gl.R32F, 16, 16, 16);

// Gesamtes Volumen im Speicher, nur die obere Hälfte (z = 8..15) hochladen
const volume = new Float32Array(16 * 16 * 16).map(() => Math.random());
const sliceSize = 16 * 16;

gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 8, 16, 16, 8,
  gl.RED, gl.FLOAT, volume, 8 * sliceSize); // srcOffset in Elementen
console.log(gl.getError());