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

WebGLRenderingContext.copyTexImage2D()

Methode

Kopiert einen rechteckigen Pixelbereich aus dem aktuell gebundenen Framebuffer (oder dem Canvas) in ein neu angelegtes 2D-Texturbild.

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

Signatur

WebGLRenderingContext.prototype.copyTexImage2D(target, level, internalformat, x, y, width, height, border)

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

Typ
void
Beschreibung
Kein Rückgabewert. Fehler werden über 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);
true

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