Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.vertexAttrib[1234]f[v]()

WebGLRenderingContext.vertexAttrib[1234]f[v]()

Methode

Legt einen konstanten Wert für ein generisches Vertex-Attribut fest, der benutzt wird, wenn für dieses Attribut kein Vertex-Array aktiviert ist.

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

Signatur

WebGLRenderingContext.prototype.vertexAttrib[1234]f[v](index, v0, v1, v2, v3)

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

Typ
void
Beschreibung
Kein 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);
Ein orangefarbenes Dreieck wird gezeichnet.

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));
Float32Array(4) [0, 0.6000000238418579, 0.6000000238418579, 1]

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));
Float32Array(4) [0.25, 0.75, 0, 1] Float32Array(4) [3, 0, 0, 1]

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, entsteht INVALID_VALUE. Ein zu kurzes Array bei den fv-Varianten löst ebenfalls einen Fehler aus.
  • Integer-Attribute: Für ivec/uvec-Attribute in WebGL 2 sind vertexAttribI4i[v]() bzw. vertexAttribI4ui[v]() zu verwenden. Die f-Varianten passen nicht zum Typ.
  • Die Methoden gibt es in allen Browsern mit WebGL 1 und ebenso bei WebGL2RenderingContext.