Start · Sprachen · JavaScript · Referenz · OES_vertex_array_object.bindVertexArrayOES()

OES_vertex_array_object.bindVertexArrayOES()

Methode

Bindet ein <code>WebGLVertexArrayObjectOES</code> an den WebGL-1-Kontext, sodass dessen gespeicherte Vertex-Attribut-Konfiguration aktiv wird.

seit JavaScript WebGL 1 Erweiterung; Baseline: alle modernen Brows Kategorie: webapi

Signatur

OES_vertex_array_object.prototype.bindVertexArrayOES(arrayObject)

Beschreibung

Die Methode bindVertexArrayOES() gehört zur WebGL-1-Erweiterung OES_vertex_array_object. Sie macht ein Vertex Array Object (VAO) zum aktuell gebundenen VAO. Ein VAO speichert den kompletten Zustand der Vertex-Attribute: welche Attribute mit enableVertexAttribArray() aktiviert sind, die Einstellungen aus vertexAttribPointer() (inklusive des dabei gebundenen ARRAY_BUFFER) sowie den gebundenen ELEMENT_ARRAY_BUFFER.

Der typische Ablauf: Einmalig beim Initialisieren ein VAO mit createVertexArrayOES() erzeugen, binden, Puffer und Attribute konfigurieren und anschließend wieder lösen. Beim Zeichnen genügt dann ein einziger Aufruf von bindVertexArrayOES(vao) statt vieler bindBuffer-/vertexAttribPointer-Aufrufe. Das reduziert den Overhead pro Draw-Call deutlich, besonders bei vielen unterschiedlichen Meshes.

Wird null übergeben, wird das Standard-VAO des Kontexts wieder gebunden. Das ist wichtig, damit nachfolgender Code, der keine VAOs kennt, nicht versehentlich das Zustandsobjekt eines Meshes verändert.

In WebGL 2 ist die Funktionalität fest eingebaut und heißt WebGL2RenderingContext.bindVertexArray() – die Erweiterung wird dort nicht benötigt.

Parameter

Name Typ Default Beschreibung
$arrayObject Pflicht WebGLVertexArrayObjectOES | null Das zu bindende VAO, erzeugt mit createVertexArrayOES(). null bindet wieder das Standard-VAO.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

VAO einrichten und beim Zeichnen binden

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const ext = gl.getExtension('OES_vertex_array_object');
if (!ext) throw new Error('OES_vertex_array_object nicht verfügbar');

// Minimales Shader-Programm
const vsSrc = 'attribute vec2 aPos; void main(){ gl_Position = vec4(aPos, 0.0, 1.0); }';
const fsSrc = 'precision mediump float; void main(){ gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); }';
const compile = (type, src) => {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  return s;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSrc));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSrc));
gl.linkProgram(program);
const aPos = gl.getAttribLocation(program, 'aPos');

// VAO anlegen und Zustand aufzeichnen
const vao = ext.createVertexArrayOES();
ext.bindVertexArrayOES(vao);

const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.8, -0.8, -0.8, 0.8, -0.8]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);

ext.bindVertexArrayOES(null); // Aufzeichnung beenden

// Zeichnen: ein Bind genügt
gl.useProgram(program);
ext.bindVertexArrayOES(vao);
gl.drawArrays(gl.TRIANGLES, 0, 3);
ext.bindVertexArrayOES(null);
Ein orangefarbenes Dreieck wird auf das Canvas gezeichnet.

Mehrere Meshes mit eigenem VAO rendern

// Annahme: gl, ext, program wie oben; meshes enthält { vao, count }
const render = (meshes) => {
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.useProgram(program);
  for (const { vao, count } of meshes) {
    ext.bindVertexArrayOES(vao);
    gl.drawArrays(gl.TRIANGLES, 0, count);
  }
  ext.bindVertexArrayOES(null);
};

Fallback: WebGL 2 oder Erweiterung

const canvas = document.createElement('canvas');
const gl2 = canvas.getContext('webgl2');
let bindVAO, createVAO;
if (gl2) {
  createVAO = () => gl2.createVertexArray();
  bindVAO = (vao) => gl2.bindVertexArray(vao);
} else {
  const gl = canvas.getContext('webgl');
  const ext = gl.getExtension('OES_vertex_array_object');
  createVAO = () => ext.createVertexArrayOES();
  bindVAO = (vao) => ext.bindVertexArrayOES(vao);
}
const vao = createVAO();
bindVAO(vao);
console.log('VAO gebunden:', vao !== null);
bindVAO(null);
VAO gebunden: true

// Wichtig · Fallstricke

  • Zustand vergessen zu lösen: Bleibt ein VAO gebunden, landen spätere vertexAttribPointer()- oder bindBuffer(ELEMENT_ARRAY_BUFFER, …)-Aufrufe in diesem VAO und überschreiben dessen Konfiguration. Nach dem Einrichten daher immer bindVertexArrayOES(null) aufrufen.
  • ARRAY_BUFFER vs. ELEMENT_ARRAY_BUFFER: Die ARRAY_BUFFER-Bindung selbst gehört nicht zum VAO-Zustand – gespeichert wird nur der Puffer, der beim vertexAttribPointer()-Aufruf gebunden war. Die ELEMENT_ARRAY_BUFFER-Bindung ist dagegen Teil des VAO.
  • Kontextübergreifend: Das VAO muss aus derselben Erweiterungsinstanz und demselben Kontext stammen, sonst entsteht ein INVALID_OPERATION-Fehler. Ein mit deleteVertexArrayOES() gelöschtes VAO darf nicht mehr gebunden werden.
  • Kompatibilität: Die Erweiterung ist in praktisch allen WebGL-1-Implementierungen verfügbar, muss aber per gl.getExtension('OES_vertex_array_object') aktiviert werden. In WebGL-2-Kontexten ist sie nicht vorhanden – dort bindVertexArray() verwenden.
  • Nach einem Kontextverlust (webglcontextlost) sind alle VAOs ungültig und müssen neu erzeugt werden.