Signatur
Beschreibung
vertexAttribIPointer() ist das Gegenstück zu vertexAttribPointer() für Ganzzahl-Attribute. Die Methode legt fest, wie die Daten eines Vertex-Attributs im gerade an gl.ARRAY_BUFFER gebundenen Puffer liegen: Anzahl der Komponenten, Datentyp, Abstand zwischen aufeinanderfolgenden Vertices (Stride) und Startposition (Offset). Diese Konfiguration wird im aktuell gebundenen Vertex Array Object (VAO) gespeichert.
Der entscheidende Unterschied: Die Werte kommen unverändert als Ganzzahlen im Shader an. Im GLSL-ES-3.00-Shader müssen die Attribute daher als int, ivec2..4, uint oder uvec2..4 deklariert sein. Bei vertexAttribPointer() würden die Werte dagegen immer in float umgewandelt (optional normalisiert).
Typische Einsatzfälle sind Knochen-Indizes beim Skinning, Material- oder Objekt-IDs, Bitmasken/Flags, Texturarray-Layer oder gepackte Daten, die im Shader mit Bitoperationen (>>, &) zerlegt werden. Damit die Konfiguration wirkt, muss das Attribut außerdem mit enableVertexAttribArray(index) aktiviert sein.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $index Pflicht | GLuint (number) | Index der Attribut-Location, z. B. aus gl.getAttribLocation() oder per layout(location = n) im Shader festgelegt. Muss kleiner als gl.MAX_VERTEX_ATTRIBS sein. |
|
| $size Pflicht | GLint (number) | Anzahl der Komponenten pro Vertex: 1, 2, 3 oder 4. |
|
| $type Pflicht | GLenum (number) | Datentyp der Elemente im Puffer: gl.BYTE, gl.UNSIGNED_BYTE, gl.SHORT, gl.UNSIGNED_SHORT, gl.INT oder gl.UNSIGNED_INT. Gleitkommatypen wie gl.FLOAT sind nicht erlaubt. |
|
| $stride Pflicht | GLsizei (number) | 0 | Abstand in Bytes zwischen dem Beginn zweier aufeinanderfolgender Vertices (0–255). 0 bedeutet dicht gepackt. Muss ein Vielfaches der Typgröße sein. |
| $offset Pflicht | GLintptr (number) | 0 | Byte-Offset der ersten Komponente im Puffer. Muss ein Vielfaches der Typgröße sein. |
Rückgabewert
undefined). Fehler werden über gl.getError() gemeldet.Beispiele
Objekt-IDs als uint-Attribut übergeben
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
// Vertex-Shader erwartet ein Ganzzahl-Attribut
const vsSource = `#version 300 es
layout(location = 0) in vec2 aPosition;
layout(location = 1) in uint aObjectId;
flat out uint vObjectId;
void main() {
vObjectId = aObjectId;
gl_Position = vec4(aPosition, 0.0, 1.0);
}`;
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
// Positionen (float)
const posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
// Objekt-IDs (Ganzzahl, bleiben Ganzzahl)
const idBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, idBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Uint32Array([7, 7, 7]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(1);
gl.vertexAttribIPointer(1, 1, gl.UNSIGNED_INT, 0, 0);
gl.bindVertexArray(null);
console.log(gl.getError() === gl.NO_ERROR);
Skinning: Knochen-Indizes in einem verschachtelten Puffer
const gl = document.querySelector('canvas').getContext('webgl2');
// Layout pro Vertex: 3 × float Position (12 Byte) + 4 × uint8 Knochen-Index (4 Byte) = 16 Byte
const STRIDE = 16;
const vertexCount = 3;
const data = new ArrayBuffer(STRIDE * vertexCount);
const view = new DataView(data);
const verts = [
{ pos: [0, 1, 0], bones: [0, 1, 0, 0] },
{ pos: [-1, -1, 0], bones: [1, 2, 0, 0] },
{ pos: [1, -1, 0], bones: [2, 3, 0, 0] }
];
verts.forEach((v, i) => {
const base = i * STRIDE;
v.pos.forEach((p, k) => view.setFloat32(base + k * 4, p, true));
v.bones.forEach((b, k) => view.setUint8(base + 12 + k, b));
});
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// location 0: vec3 aPosition
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, STRIDE, 0);
// location 1: uvec4 aBoneIndices (im Shader: in uvec4 aBoneIndices;)
gl.enableVertexAttribArray(1);
gl.vertexAttribIPointer(1, 4, gl.UNSIGNED_BYTE, STRIDE, 12);
console.log(gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_INTEGER));
Konfiguration prüfen und Fehler erkennen
const gl = document.querySelector('canvas').getContext('webgl2');
gl.bindVertexArray(gl.createVertexArray());
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Int16Array(8), gl.STATIC_DRAW);
// Falsch: FLOAT ist für vertexAttribIPointer nicht zulässig
gl.vertexAttribIPointer(0, 2, gl.FLOAT, 0, 0);
console.log(gl.getError() === gl.INVALID_ENUM);
// Richtig: SHORT, 2 Komponenten
gl.vertexAttribIPointer(0, 2, gl.SHORT, 0, 0);
console.log(gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE));