Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.vertexAttribIPointer()

WebGL2RenderingContext.vertexAttribIPointer()

Methode

Beschreibt Aufbau und Position eines <strong>ganzzahligen</strong> Vertex-Attributs im aktuell gebundenen <code>ARRAY_BUFFER</code>, ohne die Werte in Gleitkommazahlen umzuwandeln.

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

Signatur

WebGL2RenderingContext.prototype.vertexAttribIPointer(index, size, type, stride, offset)

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

Typ
void
Beschreibung
Kein 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);
true

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

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