Signatur
Beschreibung
WebGLTexture steht für ein Texturobjekt, das im Speicher der Grafikkarte liegt. Das Objekt ist undurchsichtig: Es hat keine eigenen öffentlichen Methoden oder Eigenschaften und dient nur als Referenz (Handle), die du an Methoden von WebGLRenderingContext bzw. WebGL2RenderingContext übergibst.
Erzeugt wird eine Textur nicht mit new, sondern mit gl.createTexture(). Danach bindest du sie mit gl.bindTexture(target, texture) an ein Ziel wie gl.TEXTURE_2D oder gl.TEXTURE_CUBE_MAP (in WebGL 2 zusätzlich TEXTURE_3D und TEXTURE_2D_ARRAY). Alle weiteren Aufrufe beziehen sich dann auf die gebundene Textur, zum Beispiel texImage2D() zum Hochladen von Pixeldaten, texParameteri() für Filter und Wrapping oder generateMipmap().
Texturen brauchst du für alles, was Bilddaten auf Geometrie abbildet: Sprites, Materialien in 3D-Szenen, Schriftatlanten, Videos als Textur und auch Render-to-Texture-Techniken, bei denen du eine Textur über ein WebGLFramebuffer als Zeichenziel verwendest. Im Shader liest du sie über eine sampler2D-Uniform, die auf eine Textureinheit (gl.activeTexture(gl.TEXTURE0 + n)) zeigt.
Wenn du eine Textur nicht mehr brauchst, gibst du den GPU-Speicher mit gl.deleteTexture(texture) frei. Ob ein Wert überhaupt eine gültige Textur ist, prüfst du mit gl.isTexture(texture).
Rückgabewert
gl.createTexture(). Die Methode gibt null zurück, wenn der Kontext verloren gegangen ist.Beispiele
Textur erzeugen und mit einem Platzhalter-Pixel füllen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// 1×1 blaues Pixel als Platzhalter, bis das echte Bild geladen ist
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(texture instanceof WebGLTexture);
console.log(gl.isTexture(texture));
Bild asynchron laden und als Textur hochladen
const loadTexture = async (gl, url) => {
const img = new Image();
img.crossOrigin = 'anonymous'; // nötig bei Bildern von fremden Origins (CORS)
img.src = url;
await img.decode();
const texture = gl.createTexture();
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, img);
const isPowerOf2 = (v) => (v & (v - 1)) === 0;
if (isPowerOf2(img.width) && isPowerOf2(img.height)) {
gl.generateMipmap(gl.TEXTURE_2D);
} else {
// WebGL 1: Nicht-Zweierpotenz-Texturen brauchen CLAMP_TO_EDGE und keine Mipmaps
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);
}
return texture;
};
const gl = document.querySelector('canvas').getContext('webgl');
const tex = await loadTexture(gl, '/img/kiste.png');
console.log('Textur bereit:', gl.isTexture(tex));
Textur im Shader verwenden und danach freigeben
// Annahme: program ist ein gelinktes WebGLProgram mit 'uniform sampler2D u_texture;'
const drawWithTexture = (gl, program, texture, vertexCount) => {
gl.useProgram(program);
gl.activeTexture(gl.TEXTURE0); // Textureinheit 0 auswählen
gl.bindTexture(gl.TEXTURE_2D, texture); // Textur an Einheit 0 binden
const loc = gl.getUniformLocation(program, 'u_texture');
gl.uniform1i(loc, 0); // Sampler zeigt auf Einheit 0
gl.drawArrays(gl.TRIANGLES, 0, vertexCount);
};
// Aufräumen, z. B. beim Szenenwechsel
const disposeTexture = (gl, texture) => {
gl.deleteTexture(texture);
console.log(gl.isTexture(texture));
};
// Wichtig · Fallstricke
- Kein Konstruktor:
new WebGLTexture()wirft einenTypeError. Texturen erzeugst du nur übergl.createTexture(). - Nur ein Kontext: Eine Textur gehört zu genau dem Kontext, der sie erzeugt hat. In einem anderen Canvas bzw. Kontext führt sie zu
INVALID_OPERATION. - Unvollständige Texturen: Der Standardfilter
TEXTURE_MIN_FILTERistNEAREST_MIPMAP_LINEAR. Ohne Mipmaps wird die Textur deshalb schwarz gerendert, bis dugenerateMipmap()aufrufst oder den Filter aufLINEARbzw.NEARESTstellst. - Nicht-Zweierpotenzen (NPOT): In WebGL 1 funktionieren NPOT-Texturen nur mit
CLAMP_TO_EDGEund ohne Mipmaps. In WebGL 2 gilt diese Einschränkung nicht mehr. - CORS und Sicherheit: Bilder oder Videos von fremden Origins darfst du nur hochladen, wenn der Server CORS erlaubt und
crossOrigingesetzt ist. Sonst wirfttexImage2D()einenSecurityError. So wird verhindert, dass Pixeldaten fremder Seiten ausgelesen werden. - Speicher: Der Garbage Collector gibt GPU-Speicher nicht zuverlässig frei. Ruf deshalb ausdrücklich
gl.deleteTexture()auf. Geht der Kontext verloren (webglcontextlost), werden alle Texturen ungültig und müssen nachwebglcontextrestoredneu erzeugt werden. - Kompatibilität: Wird von allen modernen Browsern unterstützt, auch in Web Workers über
OffscreenCanvas.