Signatur
Beschreibung
Mit bindAttribLocation() legst du selbst fest, an welchem generischen Vertex-Attribut-Index (0 bis MAX_VERTEX_ATTRIBS - 1) eine Attributvariable des Vertex-Shaders liegt. Ohne diesen Aufruf vergibt der Treiber die Indizes beim Linken selbst, und du musst sie danach mit getAttribLocation() abfragen.
Die Zuordnung wird erst beim nächsten Aufruf von linkProgram() wirksam. Deshalb rufst du die Methode nach attachShader() und vor linkProgram() auf. Rufst du sie nach dem Linken auf, ändert sich nichts, bis du das Programm neu linkst.
Sinnvoll ist das vor allem, wenn mehrere Shader-Programme dasselbe Vertex-Layout nutzen sollen (z. B. a_position immer auf 0, a_normal immer auf 1). Dann kannst du Vertex Array Objects oder Pufferbelegungen für alle Programme wiederverwenden, ohne die Indizes jedes Mal neu abzufragen. Außerdem empfiehlt es sich, Index 0 an ein Attribut zu binden, das tatsächlich als Array genutzt wird (siehe Hinweise).
Du kannst auch Namen binden, die im Shader nicht vorkommen oder vom Compiler wegoptimiert werden. Solche Zuordnungen werden einfach ignoriert. Es ist sogar erlaubt, zwei Namen an denselben Index zu binden (Aliasing). Werden beide Attribute tatsächlich genutzt, schlägt das Linken in WebGL allerdings fehl.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das Shader-Programm, dessen Attribut-Zuordnung festgelegt werden soll. | |
| $index Pflicht | GLuint (number) | Generischer Vertex-Attribut-Index. Muss kleiner als gl.getParameter(gl.MAX_VERTEX_ATTRIBS) sein (mindestens 8, meist 16). |
|
| $name Pflicht | string | Name der attribute- bzw. in-Variable im Vertex-Shader, z. B. "a_position". Namen mit dem Präfix webgl_ oder _webgl_ sind reserviert. |
Rückgabewert
undefined). Fehler meldet die Methode über gl.getError().Beispiele
Attribute vor dem Linken festen Indizes zuordnen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const vsSource = `
attribute vec3 a_position;
attribute vec2 a_uv;
varying vec2 v_uv;
void main() {
v_uv = a_uv;
gl_Position = vec4(a_position, 1.0);
}`;
const fsSource = `
precision mediump float;
varying vec2 v_uv;
void main() { gl_FragColor = vec4(v_uv, 0.0, 1.0); }`;
const compile = (type, src) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(shader));
}
return shader;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
// WICHTIG: vor linkProgram()
gl.bindAttribLocation(program, 0, 'a_position');
gl.bindAttribLocation(program, 1, 'a_uv');
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
console.log(gl.getAttribLocation(program, 'a_position'));
console.log(gl.getAttribLocation(program, 'a_uv'));
Einheitliches Vertex-Layout für mehrere Programme
// Zentrales Layout, das alle Shader-Programme teilen
const ATTRIBS = { a_position: 0, a_normal: 1, a_uv: 2 };
const createProgram = (gl, vs, fs) => {
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
for (const [name, index] of Object.entries(ATTRIBS)) {
// Nicht vorhandene Attribute werden einfach ignoriert
gl.bindAttribLocation(program, index, name);
}
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
return program;
};
// Pufferbelegung einmalig – gilt für jedes Programm aus createProgram()
const setupPositionBuffer = (gl, buffer) => {
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.enableVertexAttribArray(ATTRIBS.a_position);
gl.vertexAttribPointer(ATTRIBS.a_position, 3, gl.FLOAT, false, 0, 0);
};
Nachträgliches Binden wirkt erst nach erneutem Linken
// program ist bereits gelinkt, a_position liegt z. B. auf Index 1
gl.bindAttribLocation(program, 3, 'a_position');
console.log(gl.getAttribLocation(program, 'a_position')); // unverändert
gl.linkProgram(program); // jetzt greift die neue Zuordnung
console.log(gl.getAttribLocation(program, 'a_position'));
// Wichtig · Fallstricke
- Zeitpunkt: Die Zuordnung greift erst beim nächsten
linkProgram(). Ein häufiger Fehler ist der Aufruf nach dem Linken. - Index 0: Auf manchen Desktop-Plattformen (vor allem über ANGLE bzw. ältere OpenGL-Treiber) ist es langsamer, wenn Attribut 0 nicht als Array aktiviert ist. Binde deshalb ein immer genutztes Attribut wie
a_positionan Index 0. - Fehler:
INVALID_VALUE, wennindex >= MAX_VERTEX_ATTRIBSist.INVALID_OPERATION, wennnamemitgl_,webgl_oder_webgl_beginnt. Enthält der Name ungültige Zeichen oder ist er länger als 256 Zeichen, gibt es ebenfalls einen Fehler. - Nur Attribute: Die Methode gilt nur für Attribute. Für Uniforms verwendest du
getUniformLocation(). - WebGL 2: Dort kannst du alternativ im GLSL-ES-3.00-Shader
layout(location = 0) in vec3 a_position;schreiben. Eine Layout-Angabe im Shader hat Vorrang vorbindAttribLocation(). - Kompatibilität: Wird in allen modernen Browsern unterstützt, sowohl in
WebGLRenderingContextals auch inWebGL2RenderingContext.