Signatur
Beschreibung
copyTexImage2D() liest Pixel aus dem aktuell zum Lesen gebundenen Framebuffer, also dem Standard-Framebuffer des Canvas oder einem gebundenen WebGLFramebuffer. Daraus wird für die an target gebundene Textur ein neues Texturbild angelegt. Speicher und Format der gewählten Mip-Stufe werden dabei neu festgelegt, ähnlich wie bei texImage2D(). Die Daten kommen aber direkt von der GPU und nicht aus JavaScript.
Typische Einsatzfälle sind:
- eine gerenderte Szene als Textur weiterverwenden, etwa für Spiegelungen, Bildschirmfotos oder Feedback-Effekte
- ein Zwischenergebnis beim Multi-Pass-Rendering sichern
- Bereiche des Canvas für Post-Processing kopieren, ohne den langsamen Umweg über
readPixels()zu nehmen
Soll nur ein Teil einer schon vorhandenen Textur überschrieben werden, ist copyTexSubImage2D() meist schneller, weil dabei kein Speicher neu angelegt wird. In vielen Fällen ist es noch effizienter, gleich in eine Textur zu rendern, die an ein Framebuffer-Objekt angehängt ist. Dann entfällt das Kopieren ganz.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Ziel der Textur: gl.TEXTURE_2D oder eine Würfelseite wie gl.TEXTURE_CUBE_MAP_POSITIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, …_POSITIVE_Y, …_NEGATIVE_Y, …_POSITIVE_Z, …_NEGATIVE_Z. |
|
| $level Pflicht | GLint | Mip-Stufe, in die geschrieben wird. 0 ist das Basisbild. |
|
| $internalformat Pflicht | GLenum | Farbformat der Textur: gl.ALPHA, gl.LUMINANCE, gl.LUMINANCE_ALPHA, gl.RGB oder gl.RGBA. Das Format muss zum Format des Framebuffers passen. Bei einem RGB-Framebuffer ist gl.RGBA zum Beispiel nicht erlaubt. |
|
| $x Pflicht | GLint | x-Koordinate der unteren linken Ecke des Quellbereichs im Framebuffer, gemessen in Pixeln. | |
| $y Pflicht | GLint | y-Koordinate der unteren linken Ecke des Quellbereichs. Der Ursprung liegt unten links. | |
| $width Pflicht | GLsizei | Breite des kopierten Bereichs und damit der Textur, in Pixeln. | |
| $height Pflicht | GLsizei | Höhe des kopierten Bereichs und damit der Textur, in Pixeln. | |
| $border Pflicht | GLint | 0 | Breite des Rahmens. Muss immer 0 sein. |
Rückgabewert
gl.getError() gemeldet, z. B. INVALID_ENUM, INVALID_VALUE, INVALID_OPERATION oder INVALID_FRAMEBUFFER_OPERATION.Beispiele
Canvas-Inhalt in eine Textur kopieren
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true });
// Etwas zeichnen: hier nur den Hintergrund einfärben
gl.clearColor(0.2, 0.4, 0.8, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Zieltextur anlegen und binden
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// Den ganzen Standard-Framebuffer in die Textur kopieren
gl.copyTexImage2D(
gl.TEXTURE_2D, 0, gl.RGBA,
0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight,
0
);
// Filter ohne Mipmaps setzen, damit die Textur auch bei NPOT-Größen vollständig ist
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);
console.log(gl.getError() === gl.NO_ERROR);
Ausschnitt aus einem Framebuffer-Objekt kopieren
const gl = document.createElement('canvas').getContext('webgl');
// Quelltextur (256×256) mit angehängtem Framebuffer
const srcTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, srcTex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, srcTex, 0);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Einen 64×64-Ausschnitt ab (32, 32) in eine neue Textur kopieren
const dstTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, dstTex);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 64, 64, 0);
gl.generateMipmap(gl.TEXTURE_2D); // 64 ist eine Zweierpotenz, also sind Mipmaps erlaubt
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
console.log(gl.getError());
Fehler bei unpassendem Format erkennen
// Canvas ohne Alphakanal: Der Standard-Framebuffer ist dann RGB
const gl = document.createElement('canvas').getContext('webgl', { alpha: false });
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// RGBA verlangt einen Alphakanal, den die Quelle nicht hat
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 16, 16, 0);
console.log(gl.getError() === gl.INVALID_OPERATION);
// Mit RGB funktioniert es
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, 0, 0, 16, 16, 0);
console.log(gl.getError() === gl.NO_ERROR);