Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.getActiveUniforms()

WebGL2RenderingContext.getActiveUniforms()

Methode

Liefert für mehrere aktive Uniforms eines <code>WebGLProgram</code> auf einmal eine bestimmte Eigenschaft, z. B. Typ, Größe, Block-Index oder Byte-Offset, als Array.

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

Signatur

WebGL2RenderingContext.prototype.getActiveUniforms(program, uniformIndices, pname)

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:
  • gl.UNIFORM_TYPE: GLSL-Typ als GLenum (z. B. gl.FLOAT_VEC4)
  • gl.UNIFORM_SIZE: Array-Länge (1 bei Nicht-Arrays)
  • gl.UNIFORM_BLOCK_INDEX: Index des Uniform-Blocks oder -1
  • gl.UNIFORM_OFFSET: Byte-Offset im Block oder -1
  • gl.UNIFORM_ARRAY_STRIDE: Byte-Abstand zwischen Array-Elementen oder -1
  • gl.UNIFORM_MATRIX_STRIDE: Byte-Abstand zwischen Matrix-Spalten/-Zeilen oder -1
  • gl.UNIFORM_IS_ROW_MAJOR: true, wenn die Matrix zeilenweise gespeichert ist

Rückgabewert

Typ
Array<number> | Array<boolean> | null
Beschreibung
Ein Array mit einem Wert pro übergebenem Index, in derselben Reihenfolge. Bei 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]})`);
});
uModel (Standard-Block) view (Block 0) proj (Block 0) eye (Block 0) uColor (Standard-Block) (Reihenfolge und Namen können je nach Treiber abweichen)

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);
Offsets: [0, 64, 128] Blockgröße: 144

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);
true true [16, 0] [false, false]