Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.createTexture()

WebGLRenderingContext.createTexture()

Methode

Erstellt ein neues, leeres <code>WebGLTexture</code>-Objekt, das anschließend gebunden und mit Bilddaten befüllt werden kann.

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

Signatur

WebGLRenderingContext.prototype.createTexture()

Beschreibung

createTexture() legt auf der GPU ein neues Textur-Objekt an und gibt einen Verweis darauf als WebGLTexture zurück. Die Textur ist zunächst leer. Sie hat weder eine Größe noch ein Format oder Bilddaten. Diese Eigenschaften bekommt sie erst, wenn sie mit bindTexture() an ein Ziel wie gl.TEXTURE_2D oder gl.TEXTURE_CUBE_MAP gebunden wird und dann Daten über texImage2D() oder texSubImage2D() erhält.

Texturen braucht man für fast jede sichtbare WebGL-Anwendung: Bilder auf Geometrie legen, Sprites, Schriftatlanten, Normal-Maps, Lookup-Tabellen oder als Farbziel für einen Framebuffer (Render-to-Texture). Der übliche Ablauf ist:

  • createTexture() – Objekt anlegen
  • bindTexture(target, texture) – als aktive Textur setzen
  • texParameteri() – Filterung und Wrap-Modus festlegen
  • texImage2D() – Pixeldaten hochladen
  • optional generateMipmap()

Die Methode gibt es genauso auf WebGL2RenderingContext. Dort lassen sich die Texturen zusätzlich mit gl.TEXTURE_3D und gl.TEXTURE_2D_ARRAY verwenden. Wird die Textur nicht mehr gebraucht, sollte man sie mit deleteTexture() ausdrücklich freigeben. Auf die Speicherbereinigung von JavaScript kann man sich beim GPU-Speicher nicht verlassen.

Rückgabewert

Typ
WebGLTexture | null
Beschreibung
Ein neues WebGLTexture-Objekt. Ist der Kontext verloren gegangen (isContextLost() liefert true), wird null zurückgegeben.

Beispiele

Einfarbige Platzhalter-Textur anlegen

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

const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

// 1×1-Pixel in Blau als Platzhalter
const pixel = new Uint8Array([0, 0, 255, 255]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);

console.log(gl.isTexture(texture));
true

Bild asynchron laden und als Textur verwenden

const loadTexture = (gl, url) => new Promise((resolve, reject) => {
  const texture = gl.createTexture();
  const image = new Image();
  image.crossOrigin = 'anonymous';
  image.onload = () => {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    // Sicher auch für Bildgrößen, die keine Zweierpotenz sind (WebGL 1)
    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);
    resolve(texture);
  };
  image.onerror = () => {
    gl.deleteTexture(texture);
    reject(new Error(`Bild konnte nicht geladen werden: ${url}`));
  };
  image.src = url;
});

const gl = document.querySelector('canvas').getContext('webgl');
const tex = await loadTexture(gl, '/img/stein.png');
console.log(tex instanceof WebGLTexture);
true

Textur als Render-Ziel (Framebuffer) nutzen und wieder freigeben

const gl = document.querySelector('canvas').getContext('webgl');
const width = 512, height = 512;

const target = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, target);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);

const ok = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
console.log('Framebuffer bereit:', ok);

// Aufräumen, wenn nicht mehr benötigt
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteFramebuffer(fbo);
gl.deleteTexture(target);
Framebuffer bereit: true

// Wichtig · Fallstricke

  • Ohne Parameter bleibt die Textur „unvollständig“: Der Standardwert von TEXTURE_MIN_FILTER ist NEAREST_MIPMAP_LINEAR. Ohne generateMipmap() oder einen anderen Min-Filter wird die Textur beim Sampeln schwarz dargestellt.
  • Zweierpotenzen in WebGL 1: Bei Texturen, deren Größe keine Zweierpotenz ist (NPOT), sind nur CLAMP_TO_EDGE und Filter ohne Mipmaps erlaubt. WebGL 2 hat diese Einschränkung nicht.
  • CORS: Bilder von fremden Domains dürfen nur hochgeladen werden, wenn crossOrigin gesetzt ist und der Server passende CORS-Header sendet. Sonst wirft texImage2D() einen SecurityError.
  • Kontextverlust: Nach dem Ereignis webglcontextlost sind alle Texturen ungültig. Nach webglcontextrestored müssen sie neu erzeugt und neu befüllt werden.
  • Speicher: GPU-Speicher wird nicht zuverlässig von der Speicherbereinigung freigegeben. Nicht mehr benötigte Texturen sollte man mit deleteTexture() ausdrücklich löschen.
  • Ein WebGLTexture gehört immer zu genau dem Kontext, der es erzeugt hat. Mit einem anderen Kontext lässt es sich nicht verwenden.
  • Kompatibilität: Wird in allen modernen Browsern unterstützt (WebGL 1 und WebGL 2), auch in OffscreenCanvas innerhalb von Workern.