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

WebGLRenderingContext.enableVertexAttribArray()

Methode

Aktiviert das generische Vertex-Attribut-Array am angegebenen <code>index</code>, damit der Vertex-Shader beim Zeichnen Daten aus dem gebundenen Puffer liest.

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

Signatur

WebGLRenderingContext.prototype.enableVertexAttribArray(index)

Beschreibung

In WebGL bekommt der Vertex-Shader seine Daten (Positionen, Normalen, Texturkoordinaten, Farben …) über Attribute. Jedes Attribut hat einen numerischen Index (Location). Standardmäßig sind alle Attribut-Arrays deaktiviert. Dann liefert das Attribut bei jedem Vertex denselben konstanten Wert, den man mit vertexAttrib[1234]f[v]() setzt. Erst enableVertexAttribArray(index) sorgt dafür, dass drawArrays() und drawElements() für jeden Vertex eigene Werte aus dem Puffer lesen, der mit vertexAttribPointer() beschrieben wurde.

Der übliche Ablauf sieht so aus: Mit getAttribLocation() den Index ermitteln, den Puffer mit bindBuffer(gl.ARRAY_BUFFER, …) binden, das Datenlayout mit vertexAttribPointer() festlegen und das Array mit enableVertexAttribArray() aktivieren. Die Reihenfolge von vertexAttribPointer() und enableVertexAttribArray() spielt keine Rolle. Wichtig ist nur, dass vor dem Zeichenaufruf beides erledigt ist.

Der Aktivierungszustand ist globaler Zustand des Kontexts (bei WebGL 2 bzw. mit der Erweiterung OES_vertex_array_object gehört er zum aktuell gebundenen Vertex Array Object). Mit disableVertexAttribArray() schaltet man ein Attribut wieder ab, zum Beispiel wenn ein anderes Shader-Programm dieses Attribut nicht nutzt.

Parameter

Name Typ Default Beschreibung
$index Pflicht GLuint (number) Index (Location) des Vertex-Attributs, das aktiviert werden soll. Man erhält ihn meist über gl.getAttribLocation(program, name). Er muss kleiner sein als gl.getParameter(gl.MAX_VERTEX_ATTRIBS).

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler meldet die Methode über gl.getError().

Beispiele

Positionsattribut für ein Dreieck aktivieren

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

const vsSource = `
  attribute vec2 aPosition;
  void main() { gl_Position = vec4(aPosition, 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);
gl.useProgram(program);

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, 'aPosition');
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(loc); // ohne diese Zeile: alle Vertices = (0,0,0,1)

gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
Ein orangefarbenes Dreieck wird auf schwarzem Hintergrund gezeichnet.

Verschachtelte Daten: Position und Farbe aus einem Puffer

// Layout pro Vertex: x, y, r, g, b  (5 Floats = 20 Bytes)
const data = new Float32Array([
   0.0,  0.8, 1, 0, 0,
  -0.8, -0.8, 0, 1, 0,
   0.8, -0.8, 0, 0, 1,
]);
const FSIZE = data.BYTES_PER_ELEMENT;

gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);

const posLoc = gl.getAttribLocation(program, 'aPosition');
const colLoc = gl.getAttribLocation(program, 'aColor');

gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 5 * FSIZE, 0);
gl.vertexAttribPointer(colLoc, 3, gl.FLOAT, false, 5 * FSIZE, 2 * FSIZE);

// Beide Attribut-Arrays aktivieren
[posLoc, colLoc].forEach((loc) => gl.enableVertexAttribArray(loc));

gl.drawArrays(gl.TRIANGLES, 0, 3);
Dreieck mit Farbverlauf Rot → Grün → Blau.

Location prüfen und Fehler abfragen

const loc = gl.getAttribLocation(program, 'aNormal');

if (loc === -1) {
  // Attribut existiert nicht oder wurde vom Compiler wegoptimiert
  console.warn('aNormal nicht gefunden – Aktivierung übersprungen');
} else {
  gl.enableVertexAttribArray(loc);
}

console.log('Max. Attribute:', gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
gl.enableVertexAttribArray(9999);
console.log(gl.getError() === gl.INVALID_VALUE);
aNormal nicht gefunden – Aktivierung übersprungen Max. Attribute: 16 true

// Wichtig · Fallstricke

  • Location -1: getAttribLocation() gibt -1 zurück, wenn das Attribut nicht existiert oder im Shader nicht benutzt und deshalb wegoptimiert wurde. enableVertexAttribArray(-1) wird zu einem sehr großen GLuint umgewandelt und löst INVALID_VALUE aus. Deshalb die Location vorher immer prüfen.
  • Index zu groß: Ist index >= MAX_VERTEX_ATTRIBS (garantiert sind mindestens 8, üblich sind 16), setzt WebGL den Fehler gl.INVALID_VALUE. Eine Ausnahme wird dabei nicht geworfen.
  • Aktiviert, aber kein Puffer gebunden: Ist ein Attribut-Array aktiviert, ohne dass über vertexAttribPointer() ein Puffer zugeordnet wurde, oder reicht der Puffer nicht für alle gezeichneten Vertices, dann lösen drawArrays() und drawElements() INVALID_OPERATION aus und es wird nichts gezeichnet.
  • Zustand bleibt bestehen: Die Aktivierung gilt für den ganzen Kontext bzw. für das gebundene VAO und nicht für das Shader-Programm. Beim Wechsel zwischen Programmen mit unterschiedlichen Attributen sollte man nicht benötigte Arrays mit disableVertexAttribArray() abschalten. Alternativ nutzt man Vertex Array Objects (WebGL 2: createVertexArray(), WebGL 1: Erweiterung OES_vertex_array_object).
  • Attribut 0: Manche Desktop-OpenGL-Treiber arbeiten langsamer, wenn das Attribut 0 nicht als Array aktiviert ist. Mit bindAttribLocation(program, 0, 'aPosition') vor dem Linken lässt sich ein immer genutztes Attribut auf Index 0 legen.
  • Die Methode gibt es genauso auch in WebGL2RenderingContext. Alle modernen Browser unterstützen sie.