Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.uniformMatrix[234]x[234]fv()

WebGL2RenderingContext.uniformMatrix[234]x[234]fv()

Methode

Setzt Werte für nicht-quadratische Matrix-Uniforms (<code>mat2x3</code>, <code>mat3x4</code>, <code>mat4x3</code> …) im gerade aktiven WebGL-2-Shaderprogramm.

seit JavaScript WebGL 2.0 – Baseline: alle modernen Browser (seit Kategorie: webapi

Signatur

WebGL2RenderingContext.prototype.uniformMatrix[234]x[234]fv(location, transpose, data, srcOffset, srcLength)

Beschreibung

Die Methodenfamilie uniformMatrix2x3fv(), uniformMatrix2x4fv(), uniformMatrix3x2fv(), uniformMatrix3x4fv(), uniformMatrix4x2fv() und uniformMatrix4x3fv() überträgt Gleitkomma-Matrizen an nicht-quadratische Uniform-Variablen eines GLSL-ES-3.00-Shaders. Diese Matrixtypen gibt es erst ab WebGL 2; für quadratische Matrizen gibt es uniformMatrix2fv(), uniformMatrix3fv() und uniformMatrix4fv().

Die Namen folgen der GLSL-Schreibweise matCxR: Die erste Zahl steht für die Spalten, die zweite für die Zeilen. uniformMatrix2x3fv() gehört also zu einem mat2x3 (2 Spalten, 3 Zeilen) und erwartet pro Matrix 6 Werte. Die Werte werden standardmäßig spaltenweise (column-major) gelesen, d. h. zuerst alle Zeilen der ersten Spalte, dann der zweiten usw.

Typische Einsatzfälle sind platzsparende Transformationen: Eine affine 3D-Transformation (Rotation, Skalierung, Verschiebung) kommt ohne die letzte Zeile 0 0 0 1 aus und passt in ein mat4x3 (12 statt 16 Floats) – ideal etwa für Knochenmatrizen beim Skinning, wo Uniform-Speicher knapp ist. Ein mat3x2 reicht für affine 2D-Transformationen.

Die Methode wirkt immer auf das Programm, das zuvor mit gl.useProgram() aktiviert wurde. Mit srcOffset und srcLength lässt sich ein Ausschnitt aus einem größeren Float32Array übertragen, ohne ein neues Teil-Array anlegen zu müssen.

Parameter

Name Typ Default Beschreibung
$location Pflicht WebGLUniformLocation | null Position der Uniform-Variablen, ermittelt über gl.getUniformLocation(). Bei null wird der Aufruf stillschweigend ignoriert.
$transpose Pflicht boolean true, wenn die Daten zeilenweise (row-major) vorliegen und beim Hochladen transponiert werden sollen. In WebGL 2 ist – anders als in WebGL 1 – auch true erlaubt.
$data Pflicht Float32Array | Array<number> Die Matrixwerte. Die Länge muss ein Vielfaches der Elementanzahl sein (z. B. 6 für 2x3/3x2, 8 für 2x4/4x2, 12 für 3x4/4x3). Mehrere Matrizen hintereinander füllen ein Uniform-Array.
$srcOffset number 0 Index in data, ab dem gelesen wird.
$srcLength number 0 Anzahl der zu lesenden Werte. 0 bedeutet: alles ab srcOffset bis zum Ende von data.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler werden über gl.getError() gemeldet.

Beispiele

mat3x2 für eine affine 2D-Transformation

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');

const vsSource = `#version 300 es
in vec2 aPos;
uniform mat3x2 uTransform; // 3 Spalten, 2 Zeilen
void main() {
  vec2 p = uTransform * vec3(aPos, 1.0);
  gl_Position = vec4(p, 0.0, 1.0);
}`;
const fsSource = `#version 300 es
precision mediump float;
out vec4 color;
void main() { color = vec4(1.0, 0.5, 0.0, 1.0); }`;

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); // Pflicht vor dem Setzen der Uniforms

// Rotation um 45° + Verschiebung (0.2, -0.1), spaltenweise
const a = Math.PI / 4;
const transform = new Float32Array([
  Math.cos(a), Math.sin(a),   // Spalte 0
  -Math.sin(a), Math.cos(a),  // Spalte 1
  0.2, -0.1                   // Spalte 2 (Translation)
]);

const loc = gl.getUniformLocation(program, 'uTransform');
gl.uniformMatrix3x2fv(loc, false, transform);
console.log(gl.getError() === gl.NO_ERROR);
true

Knochenmatrizen als mat4x3-Array mit srcOffset/srcLength

// Im Shader: uniform mat4x3 uBones[32];
const BONE_FLOATS = 12; // 4 Spalten × 3 Zeilen
const allBones = new Float32Array(64 * BONE_FLOATS); // Pool für 64 Knochen

// Einheitsmatrix (ohne letzte Zeile) für jeden Knochen setzen
for (let i = 0; i < 64; i++) {
  allBones.set([1,0,0, 0,1,0, 0,0,1, 0,0,0], i * BONE_FLOATS);
}

const uploadBones = (gl, program, firstBone, count) => {
  gl.useProgram(program);
  const loc = gl.getUniformLocation(program, 'uBones');
  // Nur einen Ausschnitt übertragen – ohne subarray()-Kopie
  gl.uniformMatrix4x3fv(
    loc,
    false,
    allBones,
    firstBone * BONE_FLOATS,
    count * BONE_FLOATS
  );
};

// z. B. Knochen 16–47 für das aktuelle Mesh
// uploadBones(gl, skinProgram, 16, 32);

Zeilenweise Daten mit transpose = true

// Im Shader: uniform mat2x3 uM; (2 Spalten, 3 Zeilen)
// Daten liegen mathematisch lesbar zeilenweise vor (2 Werte pro Zeile):
const rowMajor = new Float32Array([
  1, 2,  // Zeile 0
  3, 4,  // Zeile 1
  5, 6   // Zeile 2
]);

// WebGL 2 transponiert beim Hochladen – in WebGL 1 wäre true ein Fehler
gl.useProgram(program);
gl.uniformMatrix2x3fv(gl.getUniformLocation(program, 'uM'), true, rowMajor);

// Kontrolle: getUniform liefert immer spaltenweise
console.log(Array.from(gl.getUniform(program, gl.getUniformLocation(program, 'uM'))));
[1, 3, 5, 2, 4, 6]