Signatur
Beschreibung
texSubImage2D() ersetzt einen rechteckigen Bereich eines Texturbildes, das vorher mit texImage2D() angelegt wurde. Der Speicher der Textur wird dabei nicht neu reserviert, nur die Texel im angegebenen Bereich werden ersetzt. Deshalb ist die Methode deutlich schneller als ein erneuter Aufruf von texImage2D(), wenn sich Größe und Format nicht ändern.
Typische Einsatzfälle sind Videotexturen, die in jedem Frame aktualisiert werden, Texturatlanten, in die Glyphen oder Sprites nachträglich eingefügt werden, dynamische Heightmaps und Datentexturen für GPGPU-Berechnungen oder Partikelsysteme.
Es gibt zwei Formen des Aufrufs:
- Mit rohen Pixeldaten: Du übergibst
width,heightund einArrayBufferView, zum Beispiel einUint8Array. - Mit einer DOM- oder Bildquelle, etwa
HTMLImageElement,HTMLCanvasElement,HTMLVideoElement,ImageBitmap,ImageDataoderOffscreenCanvas. Breite und Höhe werden dann aus der Quelle übernommen.
Die Textur muss vorher mit bindTexture() an das passende Ziel gebunden sein. format und type müssen zum internen Format passen, das beim ursprünglichen texImage2D() gewählt wurde.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Das Bindungsziel: gl.TEXTURE_2D oder eine Würfelseite wie gl.TEXTURE_CUBE_MAP_POSITIVE_X (entsprechend auch NEGATIVE_X, POSITIVE_Y usw.). |
|
| $level Pflicht | GLint | Die Mipmap-Stufe, die aktualisiert wird. 0 ist das Basisbild. |
|
| $xoffset Pflicht | GLint | Horizontaler Versatz des Teilrechtecks innerhalb der Textur, in Texeln. | |
| $yoffset Pflicht | GLint | Vertikaler Versatz des Teilrechtecks innerhalb der Textur, in Texeln. | |
| $width | GLsizei | Breite des Teilrechtecks. Gibt es nur in der Form mit ArrayBufferView. |
|
| $height | GLsizei | Höhe des Teilrechtecks. Gibt es nur in der Form mit ArrayBufferView. |
|
| $format Pflicht | GLenum | Das Format der Quelldaten, z. B. gl.RGBA, gl.RGB, gl.ALPHA, gl.LUMINANCE oder gl.LUMINANCE_ALPHA. Muss zum Format der Textur passen. |
|
| $type Pflicht | GLenum | Der Datentyp der Texel, z. B. gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_6_5, gl.UNSIGNED_SHORT_4_4_4_4 oder gl.FLOAT (braucht die Erweiterung OES_texture_float). |
|
| $pixels | ArrayBufferView | null | Die rohen Pixeldaten. Der typisierte Array-Typ muss zu type passen, etwa Uint8Array für UNSIGNED_BYTE oder Uint16Array für UNSIGNED_SHORT_5_6_5. |
|
| $source | ImageBitmap | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | VideoFrame | Eine Bild- oder Videoquelle. Wird statt width, height und pixels übergeben. |
Rückgabewert
undefined). Fehler meldet WebGL über gl.getError().Beispiele
Einzelnes Texel in einer Datentextur ändern
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// 4×4-Textur anlegen, komplett schwarz
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0,
gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4 * 4 * 4));
// Texel an Position (2, 1) auf Rot setzen
const red = new Uint8Array([255, 0, 0, 255]);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 2, 1, 1, 1,
gl.RGBA, gl.UNSIGNED_BYTE, red);
console.log(gl.getError() === gl.NO_ERROR);
Videotextur in jedem Frame aktualisieren
const gl = document.querySelector('#view').getContext('webgl');
const video = document.querySelector('video');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
video.addEventListener('loadeddata', () => {
// Speicher einmalig in Videogröße anlegen
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
const render = () => {
gl.bindTexture(gl.TEXTURE_2D, tex);
// Nur Inhalt ersetzen, kein neuer Speicher
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video);
// ... zeichnen ...
requestAnimationFrame(render);
};
requestAnimationFrame(render);
});
Bild in einen Texturatlas einfügen
const gl = document.querySelector('canvas').getContext('webgl');
const atlas = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, atlas);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1024, 1024, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null); // leerer Speicher
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
const addToAtlas = async (url, x, y) => {
const blob = await (await fetch(url)).blob();
const bitmap = await createImageBitmap(blob);
gl.bindTexture(gl.TEXTURE_2D, atlas);
gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
bitmap.close();
return { x, y, w: bitmap.width, h: bitmap.height };
};
const slot = await addToAtlas('/sprites/held.png', 128, 0);
console.log(slot);