Signatur
Beschreibung
Mit getVertexAttribOffset() fragst du ab, ab welchem Byte-Offset ein Vertex-Attribut seine Daten aus dem zugehörigen ARRAY_BUFFER liest. Diesen Wert hast du vorher als letzten Parameter (offset) an vertexAttribPointer() übergeben. Die Methode entspricht glGetVertexAttribPointerv aus OpenGL ES 2.0. Ein echter Speicherzeiger wird aber nicht zurückgegeben, sondern nur der Offset als Zahl.
Nützlich ist das vor allem beim Debuggen von verschachtelten (interleaved) Vertex-Layouts, in Werkzeugen, die den WebGL-Zustand prüfen, und wenn du den Zustand sichern und später wiederherstellen willst, zum Beispiel in Bibliotheken, die sich einen Kontext mit fremdem Code teilen.
Als zweiten Parameter gibt es nur den Wert gl.VERTEX_ATTRIB_ARRAY_POINTER. Die übrigen Einstellungen eines Attributs, etwa Stride, Größe, Typ oder gebundener Puffer, fragst du mit getVertexAttrib() ab.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $index Pflicht | GLuint (number) | Position (Location) des Vertex-Attributs, z. B. von getAttribLocation(). Muss kleiner sein als gl.getParameter(gl.MAX_VERTEX_ATTRIBS). |
|
| $pname Pflicht | GLenum (number) | Muss gl.VERTEX_ATTRIB_ARRAY_POINTER sein. |
Rückgabewert
0. Bei einem Fehler wird ebenfalls 0 zurückgegeben; den Fehler meldet dann getError().Beispiele
Offset eines Attributs in verschachtelten Daten abfragen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
// Verschachtelte Daten: x, y, r, g, b pro Vertex (5 Floats = 20 Byte)
const data = new Float32Array([
0, 0, 1, 0, 0,
1, 0, 0, 1, 0,
0, 1, 0, 0, 1
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
const STRIDE = 5 * Float32Array.BYTES_PER_ELEMENT;
// Attribut 0: Position, Attribut 1: Farbe (beginnt nach 2 Floats)
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, STRIDE, 0);
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, STRIDE, 2 * 4);
console.log(gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER));
console.log(gl.getVertexAttribOffset(1, gl.VERTEX_ATTRIB_ARRAY_POINTER));
Vertex-Layout zum Debuggen ausgeben
const describeAttrib = (gl, index) => ({
enabled: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_ENABLED),
size: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_SIZE),
stride: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_STRIDE),
offset: gl.getVertexAttribOffset(index, gl.VERTEX_ATTRIB_ARRAY_POINTER)
});
const gl = document.createElement('canvas').getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, 64, gl.STATIC_DRAW);
gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 16, 8);
gl.enableVertexAttribArray(2);
console.table(describeAttrib(gl, 2));
Attributzustand sichern und wiederherstellen
const saveAttribState = (gl, index) => ({
buffer: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING),
size: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_SIZE),
type: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_TYPE),
normalized: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED),
stride: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_STRIDE),
offset: gl.getVertexAttribOffset(index, gl.VERTEX_ATTRIB_ARRAY_POINTER)
});
const restoreAttribState = (gl, index, s) => {
if (!s.buffer) return; // kein Puffer gebunden – nichts wiederherzustellen
gl.bindBuffer(gl.ARRAY_BUFFER, s.buffer);
gl.vertexAttribPointer(index, s.size, s.type, s.normalized, s.stride, s.offset);
};
const gl = document.createElement('canvas').getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, 48, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 12, 0);
const state = saveAttribState(gl, 0);
// ... fremder Code verändert Attribut 0 ...
restoreAttribState(gl, 0, state);
console.log(state.offset);
// Wichtig · Fallstricke
- Ist
pnamenichtgl.VERTEX_ATTRIB_ARRAY_POINTER, meldet WebGL den FehlerINVALID_ENUM. Istindexgrößer oder gleichMAX_VERTEX_ATTRIBS, lautet erINVALID_VALUE. In beiden Fällen ist der Rückgabewert0. Prüfe deshalb mitgl.getError(), ob etwas schiefgelaufen ist. - Die Methode liefert keinen Speicherzeiger wie in nativem OpenGL, sondern nur den Offset als Zahl.
- Jede
get*-Abfrage kann die GPU-Pipeline zum Synchronisieren zwingen. Rufe die Methode deshalb nicht in der Render-Schleife auf, sondern speichere dir die Werte lieber selbst. - In WebGL 2 und mit der Erweiterung
OES_vertex_array_objectbezieht sich der Wert auf das gerade gebundene Vertex Array Object. Hast du ein anderes VAO gebunden, bekommst du andere Werte. - Kompatibilität: Die Methode ist in allen modernen Browsern verfügbar, sowohl in
WebGLRenderingContextals auch inWebGL2RenderingContext. Sie funktioniert auch in einemOffscreenCanvasin Web Workern.