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

OES_vertex_array_object.createVertexArrayOES()

Methode

Erstellt ein neues <code>WebGLVertexArrayObject</code> (VAO), das in WebGL 1 den kompletten Vertex-Attribut-Zustand zum schnellen Umschalten speichert.

seit JavaScript WebGL 1 Extension, Baseline: alle modernen Browser Kategorie: webapi

Signatur

OES_vertex_array_object.createVertexArrayOES()

Beschreibung

Die Methode createVertexArrayOES() der WebGL-1-Erweiterung OES_vertex_array_object legt ein neues, leeres Vertex-Array-Objekt (VAO) an. Ein VAO speichert alle Einstellungen, die mit vertexAttribPointer(), enableVertexAttribArray() und dem gebundenen ELEMENT_ARRAY_BUFFER gemacht werden. Danach kann man diesen Zustand mit einem einzigen Aufruf von bindVertexArrayOES() wiederherstellen.

Das lohnt sich vor allem, wenn eine Szene viele verschiedene Meshes enthält. Ohne VAO musst du vor jedem Draw-Call alle Attribut-Zeiger neu setzen. Mit VAO bindest du pro Mesh nur ein Objekt. Das macht den Code übersichtlicher und spart CPU-Zeit im Treiber.

Die Erweiterung holst du mit gl.getExtension("OES_vertex_array_object"). In WebGL 2 gehören VAOs zum Kern der API. Dort heißt die Methode gl.createVertexArray() und du brauchst keine Erweiterung.

Das erzeugte Objekt ist zuerst nur ein Name ohne Zustand. Es wird erst dann gültig und befüllt, wenn du es mit bindVertexArrayOES() bindest und danach Attribute konfigurierst.

Rückgabewert

Typ
WebGLVertexArrayObject | null
Beschreibung
Ein neues WebGLVertexArrayObject. Ist der WebGL-Kontext verloren gegangen, kommt null zurück.

Beispiele

Erweiterung abfragen und VAO erstellen

const canvas = document.createElement("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");
}

const vao = ext.createVertexArrayOES();
console.log(vao instanceof WebGLVertexArrayObjectOES);
console.log(ext.isVertexArrayOES(vao)); // noch nicht gebunden
true false

Attribut-Zustand in einem VAO speichern und zum Zeichnen nutzen

const gl = document.querySelector("canvas").getContext("webgl");
const ext = gl.getExtension("OES_vertex_array_object");

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 anlegen und binden – alles Folgende wird darin gespeichert
const triangleVAO = ext.createVertexArrayOES();
ext.bindVertexArrayOES(triangleVAO);

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

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

ext.bindVertexArrayOES(null); // Zustand "einfrieren"

// Im Render-Loop reicht ein einziger Bind-Aufruf
const render = () => {
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.useProgram(program);
  ext.bindVertexArrayOES(triangleVAO);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
  ext.bindVertexArrayOES(null);
};
render();

Fallback-Helfer 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);
const vao = vaoApi?.create();
console.log(vao ? "VAO bereit" : "Keine VAO-Unterstützung");
VAO bereit

// Wichtig · Fallstricke

  • Nur WebGL 1: In einem WebGL-2-Kontext gibt getExtension("OES_vertex_array_object") null zurück. Nimm dort gl.createVertexArray().
  • Immer mit dem Kontext prüfen: Die Erweiterung wird praktisch überall unterstützt, auch auf Mobilgeräten. Trotzdem solltest du vor der Nutzung auf null prüfen.
  • ARRAY_BUFFER wird nicht gespeichert: Das VAO merkt sich nicht die aktuelle ARRAY_BUFFER-Bindung selbst. Es speichert nur den Buffer, der beim Aufruf von vertexAttribPointer() gebunden war. Den ELEMENT_ARRAY_BUFFER speichert es dagegen schon. Wenn du ihn bindest, während ein VAO aktiv ist, veränderst du also dieses VAO.
  • Nach der Einrichtung entbinden: Rufe danach bindVertexArrayOES(null) auf. So veränderst du nicht aus Versehen den Zustand des VAOs, zum Beispiel in Code von Drittbibliotheken, der nichts von VAOs weiß.
  • Speicher freigeben: Nicht mehr benötigte VAOs löschst du mit deleteVertexArrayOES(). Wenn der Kontext verloren geht (webglcontextlost), werden alle VAOs ungültig und müssen neu erzeugt werden.
  • VAOs sind an den Kontext gebunden, in dem sie erzeugt wurden. Zwischen verschiedenen Kontexten kannst du sie nicht teilen.