Signatur
Beschreibung
getAttribLocation() ermittelt, unter welchem numerischen Index eine Attributvariable des Vertex-Shaders (in GLSL ES 1.0 attribute, in GLSL ES 3.0 in) im gelinkten Programm liegt. Diesen Index brauchst du, um Vertex-Daten aus einem Buffer mit dem Attribut zu verbinden, also für vertexAttribPointer(), enableVertexAttribArray() und vertexAttrib[1234]f[v]().
Normalerweise fragst du die Positionen einmal direkt nach linkProgram() ab und speicherst sie. Du solltest sie nicht in jedem Frame neu abfragen, denn der Aufruf kostet Zeit und die Werte ändern sich nur, wenn das Programm neu gelinkt wird.
Hat der Shader die Variable nicht deklariert oder der Compiler sie wegoptimiert, weil sie nicht verwendet wird, gibt die Methode -1 zurück. Wenn du selbst festlegen willst, welches Attribut welchen Index bekommt, rufst du vor dem Linken bindAttribLocation() auf. In WebGL 2 kannst du den Index auch im Shader mit layout(location = n) festlegen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das Programm mit dem Attribut. Es muss bereits erfolgreich mit linkProgram() gelinkt sein. |
|
| $name Pflicht | string | Name der Attributvariablen genau so, wie er im Shader-Quelltext steht (Groß-/Kleinschreibung zählt), z. B. "a_position". Namen mit dem Präfix webgl_ oder _webgl_ sind reserviert. |
Rückgabewert
-1.Beispiele
Attributposition abfragen und Buffer verbinden
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const vsSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}`;
const fsSource = `
precision mediump float;
void main() { gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); }`;
const compile = (type, src) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
return shader;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
// Position einmal nach dem Linken abfragen
const positionLoc = gl.getAttribLocation(program, 'a_position');
console.log('a_position liegt an Index', positionLoc);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]), gl.STATIC_DRAW);
gl.useProgram(program);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
Fehlende oder wegoptimierte Attribute erkennen
// program: ein bereits gelinktes WebGLProgram
const getAttribs = (gl, program, names) => {
const locations = {};
for (const name of names) {
const loc = gl.getAttribLocation(program, name);
if (loc === -1) {
console.warn(`Attribut "${name}" nicht gefunden oder unbenutzt`);
continue;
}
locations[name] = loc;
}
return locations;
};
const attribs = getAttribs(gl, program, ['a_position', 'a_color']);
console.log(attribs);
Alle aktiven Attribute auflisten
const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (let i = 0; i < count; i++) {
const info = gl.getActiveAttrib(program, i);
const loc = gl.getAttribLocation(program, info.name);
console.log(`${info.name} -> Index ${loc}`);
}
// Wichtig · Fallstricke
- Nur nach dem Linken gültig: Vor
linkProgram()oder bei einem fehlgeschlagenen Linkvorgang führt der Aufruf zugl.INVALID_OPERATION. Prüfe deshalb vorhergl.getProgramParameter(program, gl.LINK_STATUS). - Rückgabewert
-1immer prüfen: Übergibst du-1anenableVertexAttribArray()odervertexAttribPointer(), erzeugt dasgl.INVALID_VALUE. Der häufigste Grund für-1ist ein Attribut, das im Shader zwar deklariert, aber nicht benutzt wird. Der Compiler entfernt es dann. - Die Rückgabe ist eine Zahl, kein Objekt: Bei
getUniformLocation()bekommst du einWebGLUniformLocation-Objekt odernull. Verwechsle die beiden Prüfungen nicht. - Indizes sind nicht festgelegt: Verlass dich nicht darauf, dass die Reihenfolge im Shader den Indizes entspricht. Wenn mehrere Programme dieselbe Anordnung brauchen, zum Beispiel beim Teilen von Vertex Array Objects, verwende
bindAttribLocation()oder in WebGL 2layout(location = n). - Performance: Speichere die Positionen zwischen, statt sie in der Render-Schleife abzufragen.
- Kompatibilität: Die Methode gibt es in allen modernen Browsern, sowohl in
WebGLRenderingContextals auch inWebGL2RenderingContext. Nach einem Kontextverlust (webglcontextlost) gibt sie-1zurück.