Signatur
Beschreibung
texImage3D() ist das 3D-Gegenstück zu texImage2D(). Die Methode legt für die aktuell an target gebundene Textur eine Mipmap-Ebene mit Breite, Höhe und Tiefe an und überträgt optional Pixeldaten aus einem typisierten Array, einem WebGLBuffer (über PIXEL_UNPACK_BUFFER) oder einer Bildquelle wie ImageBitmap, HTMLImageElement, HTMLCanvasElement oder HTMLVideoElement.
Typische Einsatzgebiete sind Volumentexturen (z. B. medizinische CT-/MRT-Daten, Rauch, Wolken, 3D-Rauschen), Farb-Lookup-Tabellen (3D-LUTs) für Farbkorrektur sowie Textur-Arrays (TEXTURE_2D_ARRAY), mit denen viele gleich große 2D-Bilder – etwa Sprite-Frames oder Terrain-Schichten – in einer einzigen Textur gebündelt werden. Im Shader wird darauf mit sampler3D bzw. sampler2DArray zugegriffen.
Die Kombination aus internalformat, format und type muss einer der gültigen Kombinationen der WebGL-2-Spezifikation entsprechen (z. B. RGBA8/RGBA/UNSIGNED_BYTE oder R32F/RED/FLOAT). Wer die Textur nur einmal allokieren und später schichtweise befüllen will, übergibt null als Quelle und lädt die Daten anschließend mit texSubImage3D() hoch; für unveränderliche Speicherallokation empfiehlt sich texStorage3D().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Ziel der gebundenen Textur: gl.TEXTURE_3D oder gl.TEXTURE_2D_ARRAY. |
|
| $level Pflicht | GLint | Mipmap-Ebene; 0 ist das Basisbild. |
|
| $internalformat Pflicht | GLenum | Internes Speicherformat der Textur, z. B. gl.RGBA8, gl.R8, gl.R16F, gl.R32F, gl.RGBA16F, gl.SRGB8_ALPHA8. |
|
| $width Pflicht | GLsizei | Breite der Textur in Texeln. | |
| $height Pflicht | GLsizei | Höhe der Textur in Texeln. | |
| $depth Pflicht | GLsizei | Tiefe der Textur (Anzahl Schichten bei TEXTURE_2D_ARRAY). |
|
| $border Pflicht | GLint | 0 | Randbreite; muss immer 0 sein. |
| $format Pflicht | GLenum | Format der Quelldaten, z. B. gl.RGBA, gl.RGB, gl.RED, gl.RG, gl.RED_INTEGER. |
|
| $type Pflicht | GLenum | Datentyp der Quelldaten, z. B. gl.UNSIGNED_BYTE, gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_SHORT. |
|
| $source Pflicht | ArrayBufferView | null | GLintptr | ImageBitmap | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | VideoFrame | Pixeldaten. Ein typisiertes Array (Typ passend zu type, z. B. Uint8Array für UNSIGNED_BYTE), null zum reinen Allokieren, ein Byte-Offset in einen gebundenen PIXEL_UNPACK_BUFFER oder eine Bildquelle. Bei Bildquellen werden Schichten vertikal aus dem Bild gelesen (gesteuert über UNPACK_IMAGE_HEIGHT). |
|
| $srcOffset | GLuint | 0 | Nur bei ArrayBufferView: Element-Offset, ab dem aus dem Array gelesen wird. |
Rückgabewert
undefined). Fehler werden über gl.getError() gemeldet, z. B. INVALID_OPERATION bei ungültiger Format-Kombination.Beispiele
3D-Rauschtextur aus Uint8Array erzeugen
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
if (!gl) throw new Error('WebGL 2 wird nicht unterstützt');
const size = 32;
const data = new Uint8Array(size * size * size);
for (let i = 0; i < data.length; i++) {
data[i] = Math.floor(Math.random() * 256);
}
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, tex);
// Einkanal-Daten: Zeilen sind nicht 4-Byte-ausgerichtet
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
gl.texImage3D(
gl.TEXTURE_3D, 0, gl.R8,
size, size, size, 0,
gl.RED, gl.UNSIGNED_BYTE, data
);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.REPEAT);
console.log(gl.getError() === gl.NO_ERROR);
Textur-Array allokieren und Schichten nachladen
const gl = document.querySelector('canvas').getContext('webgl2');
const loadBitmap = async (url) => {
const res = await fetch(url);
return createImageBitmap(await res.blob());
};
const urls = ['gras.png', 'fels.png', 'sand.png', 'schnee.png'];
const bitmaps = await Promise.all(urls.map(loadBitmap));
const { width, height } = bitmaps[0]; // alle Bilder gleich groß
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex);
// Nur Speicher reservieren (source = null)
gl.texImage3D(
gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8,
width, height, bitmaps.length, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null
);
// Jede Schicht einzeln hochladen
bitmaps.forEach((bmp, layer) => {
gl.texSubImage3D(
gl.TEXTURE_2D_ARRAY, 0, 0, 0, layer,
width, height, 1,
gl.RGBA, gl.UNSIGNED_BYTE, bmp
);
});
gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
console.log(`${bitmaps.length} Schichten geladen`);
Zugriff im Shader (GLSL ES 3.00)
const fragmentSource = `#version 300 es
precision highp float;
precision highp sampler3D;
uniform sampler3D uVolume;
uniform float uSlice; // 0.0 bis 1.0
in vec2 vUv;
out vec4 outColor;
void main() {
float d = texture(uVolume, vec3(vUv, uSlice)).r;
outColor = vec4(vec3(d), 1.0);
}`;
const gl = document.querySelector('canvas').getContext('webgl2');
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fragmentSource);
gl.compileShader(shader);
console.log(gl.getShaderParameter(shader, gl.COMPILE_STATUS));