Signatur
Beschreibung
Die Methodenfamilie vertexAttrib1f(), vertexAttrib2f(), vertexAttrib3f(), vertexAttrib4f() und ihre Vektor-Varianten vertexAttrib1fv() bis vertexAttrib4fv() setzen einen konstanten Wert für ein generisches Vertex-Attribut. Dieser Wert gilt dann für alle Vertices eines Zeichenaufrufs. Die Ziffer im Namen gibt an, wie viele Komponenten du übergibst. Die f-Varianten nehmen einzelne Zahlen entgegen, die fv-Varianten ein Array oder ein Float32Array.
Der Konstantwert wirkt nur, solange das Attribut mit disableVertexAttribArray(index) deaktiviert ist (das ist der Ausgangszustand). Ist das Attribut per enableVertexAttribArray() aktiviert, liest WebGL die Werte stattdessen pro Vertex aus dem gebundenen Puffer.
Das ist nützlich, wenn ein Shader ein Attribut erwartet, das für ein bestimmtes Objekt aber überall gleich ist, zum Beispiel eine einheitliche Farbe, eine feste Normale oder ein Standard-Gewicht. So musst du keinen eigenen Puffer anlegen und denselben Shader trotzdem für Meshes mit und ohne Farbdaten pro Vertex verwenden.
Fehlen Komponenten, ergänzt WebGL sie: Übergibst du weniger als vier Werte, werden y und z auf 0 und w auf 1 gesetzt. vertexAttrib2f(i, 0.5, 0.5) ergibt also (0.5, 0.5, 0.0, 1.0).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $index Pflicht | GLuint (number) | Position (Location) des Vertex-Attributs, meist über gl.getAttribLocation(program, name) ermittelt. Muss kleiner als gl.getParameter(gl.MAX_VERTEX_ATTRIBS) sein. |
|
| $v0, v1, v2, v3 Pflicht | GLfloat (number) | Nur bei den f-Varianten: je nach Variante 1 bis 4 Gleitkommawerte für die Komponenten x, y, z, w. |
|
| $value Pflicht | Float32Array | number[] | Nur bei den fv-Varianten: Array mit mindestens so vielen Elementen, wie die Ziffer im Methodennamen angibt. |
Rückgabewert
undefined).Beispiele
Einheitliche Farbe für ein Mesh ohne Farbpuffer
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const vsSource = `
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main() {
vColor = aColor;
gl_Position = vec4(aPosition, 0.0, 1.0);
}`;
const fsSource = `
precision mediump float;
varying vec4 vColor;
void main() { gl_FragColor = vColor; }`;
const compile = (type, src) => {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
return s;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
gl.useProgram(program);
// Positionen kommen aus einem Puffer
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);
const posLoc = gl.getAttribLocation(program, 'aPosition');
gl.enableVertexAttribArray(posLoc);
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
// Farbe ist konstant: kein Puffer, Array deaktiviert lassen
const colorLoc = gl.getAttribLocation(program, 'aColor');
gl.disableVertexAttribArray(colorLoc);
gl.vertexAttrib4f(colorLoc, 1.0, 0.5, 0.0, 1.0); // Orange
gl.drawArrays(gl.TRIANGLES, 0, 3);
Vektor-Variante mit Float32Array
// gl, program wie oben
const colorLoc = gl.getAttribLocation(program, 'aColor');
const teal = new Float32Array([0.0, 0.6, 0.6, 1.0]);
gl.disableVertexAttribArray(colorLoc);
gl.vertexAttrib4fv(colorLoc, teal);
// Aktuellen Wert auslesen
console.log(gl.getVertexAttrib(colorLoc, gl.CURRENT_VERTEX_ATTRIB));
Automatisches Auffüllen fehlender Komponenten
const loc = 1;
gl.vertexAttrib2f(loc, 0.25, 0.75);
console.log(gl.getVertexAttrib(loc, gl.CURRENT_VERTEX_ATTRIB));
gl.vertexAttrib1fv(loc, [3]);
console.log(gl.getVertexAttrib(loc, gl.CURRENT_VERTEX_ATTRIB));
Mehrere Objekte mit unterschiedlicher Farbe zeichnen
const objects = [
{ first: 0, count: 3, color: [1, 0, 0, 1] },
{ first: 3, count: 3, color: [0, 0, 1, 1] }
];
gl.disableVertexAttribArray(colorLoc);
for (const { first, count, color } of objects) {
gl.vertexAttrib4fv(colorLoc, color); // Farbe pro Zeichenaufruf wechseln
gl.drawArrays(gl.TRIANGLES, first, count);
}
// Wichtig · Fallstricke
- Wirkt nur bei deaktiviertem Array: Ist
enableVertexAttribArray(index)aktiv, wird der Konstantwert ignoriert. Das ist der häufigste Grund, warum „die Farbe nicht ankommt“. - Zustand gehört zum Kontext: Konstante Attributwerte gehören zum Kontext und nicht zum Programm. Sie bleiben über
useProgram()-Wechsel hinweg gesetzt. In WebGL 2 sind sie auch nicht Teil eines Vertex Array Objects (VAO). - Attribut 0: Manche Desktop-Implementierungen (älteres OpenGL) arbeiten schlechter, wenn Attribut 0 nicht als Array aktiviert ist. Browser emulieren das zwar, es kann aber Leistung kosten. Die Location 0 legst du deshalb am besten per
bindAttribLocation()auf ein Attribut, das aus einem Puffer gelesen wird, etwa die Position. - Fehler: Ist
index≥MAX_VERTEX_ATTRIBS, entstehtINVALID_VALUE. Ein zu kurzes Array bei denfv-Varianten löst ebenfalls einen Fehler aus. - Integer-Attribute: Für
ivec/uvec-Attribute in WebGL 2 sindvertexAttribI4i[v]()bzw.vertexAttribI4ui[v]()zu verwenden. Dief-Varianten passen nicht zum Typ. - Die Methoden gibt es in allen Browsern mit WebGL 1 und ebenso bei
WebGL2RenderingContext.