Signatur
Beschreibung
getActiveUniforms() fragt eine einzelne Eigenschaft (pname) für eine ganze Liste von Uniform-Indizes gleichzeitig ab. Anders als getActiveUniform(), das Name, Typ und Größe eines Uniforms zurückgibt, arbeitet diese Methode im Stapel. Das Ergebnis ist ein Array, das in der Reihenfolge von uniformIndices sortiert ist.
Am häufigsten brauchst du sie bei Uniform Buffer Objects (UBOs). Mit gl.UNIFORM_OFFSET, gl.UNIFORM_ARRAY_STRIDE und gl.UNIFORM_MATRIX_STRIDE erfährst du, an welcher Byte-Position der Treiber jedes Mitglied eines Uniform-Blocks erwartet. So befüllst du einen ArrayBuffer korrekt, ohne die std140-Regeln selbst nachzurechnen. Mit gl.UNIFORM_BLOCK_INDEX kannst du außerdem trennen: Welche Uniforms liegen im Standard-Block (Wert -1) und welche in einem benannten Block?
Die Uniform-Indizes bekommst du entweder über gl.getUniformIndices(program, names) oder als Bereich 0 … n-1, wobei n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS). Das Programm muss vorher erfolgreich gelinkt worden sein.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das erfolgreich gelinkte Shader-Programm, dessen Uniforms abgefragt werden. | |
| $uniformIndices Pflicht | Array<number> | Uint32Array | Liste der Uniform-Indizes, z. B. aus gl.getUniformIndices(). Werte müssen kleiner als gl.ACTIVE_UNIFORMS sein. |
|
| $pname Pflicht | GLenum | Die abzufragende Eigenschaft:
|
Rückgabewert
gl.UNIFORM_IS_ROW_MAJOR enthält es Booleans, sonst Zahlen. Bei einem Fehler (z. B. ungültiges pname) wird null zurückgegeben und gl.getError() meldet den Fehlercode.Beispiele
Alle Uniforms auflisten und nach Block trennen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const vsSource = `#version 300 es
uniform mat4 uModel;
uniform Camera { mat4 view; mat4 proj; vec3 eye; };
in vec4 aPos;
void main() { gl_Position = proj * view * uModel * aPos + vec4(eye * 0.0, 0.0); }`;
const fsSource = `#version 300 es
precision highp float;
uniform vec4 uColor;
out vec4 outColor;
void main() { outColor = uColor; }`;
const compile = (type, src) => {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(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);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(program));
const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
const indices = [...Array(count).keys()];
const blockIdx = gl.getActiveUniforms(program, indices, gl.UNIFORM_BLOCK_INDEX);
indices.forEach((i) => {
const { name } = gl.getActiveUniform(program, i);
console.log(name, blockIdx[i] === -1 ? '(Standard-Block)' : `(Block ${blockIdx[i]})`);
});
UBO-Layout ermitteln und Puffer korrekt befüllen
// Voraussetzung: gl und program aus dem vorherigen Beispiel
const names = ['view', 'proj', 'eye'];
const indices = gl.getUniformIndices(program, names);
const offsets = gl.getActiveUniforms(program, indices, gl.UNIFORM_OFFSET);
const blockIndex = gl.getUniformBlockIndex(program, 'Camera');
const blockSize = gl.getActiveUniformBlockParameter(
program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE
);
const data = new Float32Array(blockSize / 4);
const identity = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
data.set(identity, offsets[0] / 4); // view
data.set(identity, offsets[1] / 4); // proj
data.set([0, 2, 5], offsets[2] / 4); // eye
const ubo = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
gl.bufferData(gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW);
gl.uniformBlockBinding(program, blockIndex, 0);
gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
console.log('Offsets:', offsets, 'Blockgröße:', blockSize);
Typen und Matrix-Strides abfragen
const indices = gl.getUniformIndices(program, ['view', 'eye']);
const types = gl.getActiveUniforms(program, indices, gl.UNIFORM_TYPE);
const strides = gl.getActiveUniforms(program, indices, gl.UNIFORM_MATRIX_STRIDE);
const rowMajor = gl.getActiveUniforms(program, indices, gl.UNIFORM_IS_ROW_MAJOR);
console.log(types[0] === gl.FLOAT_MAT4, types[1] === gl.FLOAT_VEC3);
console.log(strides, rowMajor);