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

WebGLRenderingContext.getVertexAttribOffset()

Methode

Gibt den Byte-Offset zurück, der für ein Vertex-Attribut per <code>vertexAttribPointer()</code> im gebundenen Puffer festgelegt wurde.

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

Signatur

WebGLRenderingContext.prototype.getVertexAttribOffset(index, pname)

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

Typ
GLintptr (number)
Beschreibung
Der Byte-Offset des Attributs im gebundenen Vertex-Puffer. Wurde nichts gesetzt, ist der Wert 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));
0 8

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));
{ enabled: true, size: 2, stride: 16, offset: 8 }

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 pname nicht gl.VERTEX_ATTRIB_ARRAY_POINTER, meldet WebGL den Fehler INVALID_ENUM. Ist index größer oder gleich MAX_VERTEX_ATTRIBS, lautet er INVALID_VALUE. In beiden Fällen ist der Rückgabewert 0. Prüfe deshalb mit gl.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_object bezieht 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 WebGLRenderingContext als auch in WebGL2RenderingContext. Sie funktioniert auch in einem OffscreenCanvas in Web Workern.