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

WebGLRenderingContext.vertexAttribPointer()

Methode

Verknüpft den aktuell an <code>gl.ARRAY_BUFFER</code> gebundenen Puffer mit einem Vertex-Attribut und legt fest, wie die Daten darin angeordnet sind.

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

Signatur

WebGLRenderingContext.prototype.vertexAttribPointer(index, size, type, normalized, stride, offset)

Beschreibung

vertexAttribPointer() sagt der GPU, wie sie die Rohdaten eines Vertex-Puffers lesen soll: wie viele Komponenten zu einem Attribut gehören (z. B. 3 bei einer Position vec3), welchen Datentyp sie haben, ob sie normalisiert werden, wie viele Bytes zwischen zwei aufeinanderfolgenden Vertices liegen (stride) und ab welchem Byte das Attribut beginnt (offset).

Der Aufruf bezieht sich immer auf den Puffer, der zum Zeitpunkt des Aufrufs an gl.ARRAY_BUFFER gebunden ist. Diese Verknüpfung wird im Attribut-Zustand gespeichert. Danach kannst du einen anderen Puffer binden, ohne dass sich die Zuordnung ändert. So lassen sich mehrere Attribute aus verschiedenen Puffern speisen, oder aus einem einzigen verschachtelten Puffer (interleaved), bei dem Position, Farbe und Texturkoordinaten direkt hintereinander liegen.

Damit das Attribut beim Zeichnen wirklich aus dem Puffer gelesen wird, musst du es zusätzlich mit gl.enableVertexAttribArray(index) aktivieren. Den index bekommst du normalerweise über gl.getAttribLocation(program, "aName"). In WebGL 2 (oder mit der Erweiterung OES_vertex_array_object) wird dieser ganze Zustand in einem Vertex Array Object (VAO) gespeichert. Das spart beim Zeichnen viele Aufrufe.

Parameter

Name Typ Default Beschreibung
$index Pflicht GLuint (number) Index des Vertex-Attributs, meist aus gl.getAttribLocation(). Muss kleiner als gl.getParameter(gl.MAX_VERTEX_ATTRIBS) sein.
$size Pflicht GLint (1 | 2 | 3 | 4) Anzahl der Komponenten pro Vertex-Attribut, z. B. 2 für vec2 und 3 für vec3.
$type Pflicht GLenum Datentyp jeder Komponente: gl.FLOAT, gl.BYTE, gl.UNSIGNED_BYTE, gl.SHORT oder gl.UNSIGNED_SHORT. WebGL 2 erlaubt zusätzlich gl.HALF_FLOAT, gl.INT, gl.UNSIGNED_INT und gl.INT_2_10_10_10_REV.
$normalized Pflicht GLboolean (boolean) Nur für Ganzzahltypen relevant. Bei true werden die Werte auf [0, 1] (vorzeichenlos) bzw. [-1, 1] (vorzeichenbehaftet) abgebildet, z. B. 255 → 1.0 bei UNSIGNED_BYTE. Bei gl.FLOAT hat der Wert keine Wirkung.
$stride Pflicht GLsizei (number) Abstand in Bytes zwischen dem Anfang zweier aufeinanderfolgender Vertices (0–255). 0 bedeutet: dicht gepackt, die Schrittweite ergibt sich dann aus size × Typgröße.
$offset Pflicht GLintptr (number) Byte-Offset des ersten Elements im Puffer. Muss ein Vielfaches der Byte-Größe von type sein.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Fehler lassen sich über gl.getError() abfragen.

Beispiele

Dicht gepackte Positionsdaten für ein Dreieck

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.4, 0.1, 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 positions = new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

const loc = gl.getAttribLocation(program, 'aPosition');
// 2 Floats pro Vertex, dicht gepackt (stride 0), ab Byte 0
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(loc);

gl.drawArrays(gl.TRIANGLES, 0, 3);
Ein orangefarbenes Dreieck wird auf das Canvas gezeichnet.

Verschachtelter Puffer: Position und Farbe

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

const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
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, stride, 0);
gl.enableVertexAttribArray(posLoc);

// Farbe beginnt nach 2 Floats = 8 Bytes
gl.vertexAttribPointer(colLoc, 3, gl.FLOAT, false, stride, 2 * FSIZE);
gl.enableVertexAttribArray(colLoc);

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

Kompakte Farben als normalisierte Bytes

// RGBA als Uint8 (0–255) spart 75 % Speicher gegenüber Float32
const colors = new Uint8Array([
  255, 0, 0, 255,
  0, 255, 0, 255,
  0, 0, 255, 255,
]);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

const colLoc = gl.getAttribLocation(program, 'aColor'); // vec4 im Shader
// normalized = true: 255 wird im Shader zu 1.0
gl.vertexAttribPointer(colLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);
gl.enableVertexAttribArray(colLoc);
Der Shader erhält aColor-Werte im Bereich 0.0–1.0.