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

WebGL2RenderingContext.texImage3D()

Methode

Reserviert Speicher für ein dreidimensionales Texturbild oder ein 2D-Textur-Array (<code>TEXTURE_3D</code> / <code>TEXTURE_2D_ARRAY</code>) und befüllt ihn optional mit Pixeldaten.

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

Signatur

WebGL2RenderingContext.prototype.texImage3D(target, level, internalformat, width, height, depth, border, format, type, source)

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

Typ
void
Beschreibung
Kein 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);
true

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