Start · Sprachen · JavaScript · Referenz · OES_vertex_array_object extension

OES_vertex_array_object extension

Schnittstelle

WebGL-1-Erweiterung, die Vertex Array Objects (VAOs) bereitstellt, mit denen sich der komplette Vertex-Attribut-Zustand speichern und per Bindung wiederherstellen lässt.

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

Signatur

interface OES_vertex_array_object

Beschreibung

Die Erweiterung OES_vertex_array_object gehört zur WebGL-API und stellt in einem WebGLRenderingContext (WebGL 1) Vertex Array Objects (VAOs) bereit. Ein VAO speichert den gesamten Zustand der Vertex-Attribute: welche Puffer an welche Attribute gebunden sind (vertexAttribPointer), welche Attribute aktiviert sind (enableVertexAttribArray) und den gebundenen ELEMENT_ARRAY_BUFFER.

Ohne VAOs musst du vor jedem Zeichenaufruf alle Attribute neu einrichten. Mit VAOs richtest du die Attribute einmal beim Laden ein und bindest beim Rendern nur noch das passende VAO mit bindVertexArrayOES(). Das verringert die Zahl der WebGL-Aufrufe pro Frame spürbar und macht den Code übersichtlicher, vor allem bei Szenen mit vielen verschiedenen Meshes.

Du erhältst die Erweiterung über gl.getExtension("OES_vertex_array_object"). Das zurückgegebene Objekt stellt folgende Methoden und Konstanten bereit:

  • createVertexArrayOES() – erzeugt ein neues WebGLVertexArrayObjectOES.
  • deleteVertexArrayOES(vao) – löscht ein VAO.
  • isVertexArrayOES(vao) – prüft, ob es sich um ein gültiges VAO handelt.
  • bindVertexArrayOES(vao) – bindet ein VAO; null stellt wieder das Standard-VAO her.
  • VERTEX_ARRAY_BINDING_OES – Konstante für gl.getParameter(), liefert das aktuell gebundene VAO.

In WebGL 2 ist diese Funktion fester Bestandteil des Kontexts (gl.createVertexArray(), gl.bindVertexArray() usw.). Die Erweiterung ist dort nicht verfügbar.

Parameter

Name Typ Default Beschreibung
$vao WebGLVertexArrayObjectOES | null Parameter von bindVertexArrayOES(), deleteVertexArrayOES() und isVertexArrayOES(): das betroffene VAO. Bei bindVertexArrayOES(null) wird das Standard-VAO gebunden.

Beispiele

Erweiterung abrufen und VAO einrichten

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 wird nicht unterstützt");
}

// Einfaches Shader-Programm
const vsSource = `attribute vec2 aPos; void main() { gl_Position = vec4(aPos, 0.0, 1.0); }`;
const fsSource = `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, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);

// VAO erzeugen und binden – ab jetzt wird der Attribut-Zustand darin gespeichert
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.5, -0.5, -0.5, 0.5, -0.5]), gl.STATIC_DRAW);

const loc = gl.getAttribLocation(program, "aPos");
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

// VAO lösen, damit spätere Aufrufe es nicht versehentlich verändern
ext.bindVertexArrayOES(null);

// Zeichnen: nur noch VAO binden
gl.useProgram(program);
ext.bindVertexArrayOES(vao);
gl.drawArrays(gl.TRIANGLES, 0, 3);
ext.bindVertexArrayOES(null);

console.log(ext.isVertexArrayOES(vao));
true

Mehrere Meshes in der Render-Schleife

// meshes: [{ vao, count }], zuvor wie oben eingerichtet
const render = (gl, ext, program, meshes) => {
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.useProgram(program);
  for (const { vao, count } of meshes) {
    ext.bindVertexArrayOES(vao); // ersetzt alle bindBuffer/vertexAttribPointer-Aufrufe
    gl.drawArrays(gl.TRIANGLES, 0, count);
  }
  ext.bindVertexArrayOES(null);
  requestAnimationFrame(() => render(gl, ext, program, meshes));
};

Einheitliche Hilfsfunktionen für WebGL 1 und WebGL 2

const createVaoApi = (gl) => {
  if (typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext) {
    return {
      create: () => gl.createVertexArray(),
      bind: (vao) => gl.bindVertexArray(vao),
      remove: (vao) => gl.deleteVertexArray(vao),
    };
  }
  const ext = gl.getExtension("OES_vertex_array_object");
  if (!ext) return null;
  return {
    create: () => ext.createVertexArrayOES(),
    bind: (vao) => ext.bindVertexArrayOES(vao),
    remove: (vao) => ext.deleteVertexArrayOES(vao),
  };
};

const gl = document.createElement("canvas").getContext("webgl");
const vaoApi = createVaoApi(gl);
console.log(vaoApi ? "VAOs verfügbar" : "keine VAO-Unterstützung");
VAOs verfügbar

// Wichtig · Fallstricke

  • Nur WebGL 1: In einem WebGL-2-Kontext liefert getExtension("OES_vertex_array_object") null. Dort nutzt du die eingebauten Methoden createVertexArray() und bindVertexArray().
  • Verfügbarkeit immer prüfen: Die Erweiterung wird praktisch überall unterstützt, kann aber auf seltener Hardware oder in Software-Renderern fehlen. Prüfe den Rückgabewert auf null und sieh einen Ausweichpfad ohne VAOs vor.
  • Nicht gespeichert wird: Der ARRAY_BUFFER-Binding-Punkt selbst gehört nicht zum VAO-Zustand; gespeichert wird nur der Puffer, der beim Aufruf von vertexAttribPointer() gebunden war. Der ELEMENT_ARRAY_BUFFER gehört dagegen zum VAO. Wer ihn bindet, während ein VAO aktiv ist, verändert dieses VAO.
  • Nach der Einrichtung lösen: Rufe nach dem Einrichten bindVertexArrayOES(null) auf. Sonst verändert späterer Code (z. B. Bibliotheken) das VAO unbemerkt.
  • Kontextverlust: Nach webglcontextlost sind alle VAOs ungültig. Du musst die Erweiterung neu abrufen und die VAOs neu anlegen.
  • Die Methoden gehören zum Erweiterungsobjekt, nicht zu gl. Ein Aufruf wie gl.createVertexArrayOES() schlägt fehl.