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

WebGL2RenderingContext.getFragDataLocation()

Methode

Gibt die Farbnummer (den Index des Draw-Buffers) zurück, an die eine benutzerdefinierte <code>out</code>-Variable eines GLSL-ES-3.00-Fragment-Shaders gebunden ist.

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

Signatur

WebGL2RenderingContext.prototype.getFragDataLocation(program, name)

Beschreibung

Mit getFragDataLocation() fragst du in einem bereits gelinkten Shader-Programm ab, an welche Farbnummer eine out-Variable des Fragment-Shaders gebunden ist. Diese Nummer entspricht dem Index in der Liste, die du an drawBuffers() übergibst, also z. B. gl.COLOR_ATTACHMENT0 + n eines Framebuffers.

Nützlich ist die Methode vor allem bei Multiple Render Targets (MRT), etwa beim Deferred Shading. Dort schreibt ein Fragment-Shader gleichzeitig in mehrere Ausgaben (Albedo, Normalen, Position). Anhand der zurückgegebenen Nummern ordnest du jeder Ausgabe die richtige Textur im Framebuffer zu.

In WebGL 2 legst du die Nummern meist direkt im Shader mit layout(location = N) out vec4 ...; fest. Anders als in Desktop-OpenGL gibt es in WebGL 2 kein bindFragDataLocation(). Die Methode dient also nur zum Abfragen, zum Beispiel zur Kontrolle oder wenn es nur eine einzige Ausgabe ohne layout-Angabe gibt (die bekommt dann automatisch 0).

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram Das Shader-Programm, das schon erfolgreich mit linkProgram() gelinkt wurde.
$name Pflicht string Der Name der out-Variable im Fragment-Shader, z. B. "outColor".

Rückgabewert

Typ
number
Beschreibung
Ein GLint mit der Farbnummer, die an die Variable gebunden ist. Den Wert -1 bekommst du, wenn die Variable nicht existiert, keine out-Variable ist oder der Name mit dem reservierten Präfix gl_ oder webgl_ beginnt.

Beispiele

Einfache Abfrage einer Fragment-Ausgabe

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

const vsSource = `#version 300 es
in vec4 aPosition;
void main() { gl_Position = aPosition; }`;

const fsSource = `#version 300 es
precision highp float;
out vec4 outColor;
void main() { outColor = vec4(1.0, 0.0, 0.0, 1.0); }`;

const compile = (type, src) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, src);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(shader));
  }
  return shader;
};

const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);

console.log(gl.getFragDataLocation(program, 'outColor'));

MRT: Ausgaben eines G-Buffers prüfen (Deferred Shading)

// program wurde mit diesem Fragment-Shader gelinkt:
// #version 300 es
// precision highp float;
// layout(location = 0) out vec4 gAlbedo;
// layout(location = 1) out vec4 gNormal;
// layout(location = 2) out vec4 gPosition;

const outputs = ['gAlbedo', 'gNormal', 'gPosition'];
const locations = outputs.map((name) => gl.getFragDataLocation(program, name));
console.log(locations);

// Draw-Buffers passend zu den Farbnummern setzen
const buffers = [];
locations.forEach((loc) => {
  buffers[loc] = gl.COLOR_ATTACHMENT0 + loc;
});
gl.drawBuffers(buffers);
[0, 1, 2]

Nicht vorhandene oder reservierte Namen

console.log(gl.getFragDataLocation(program, 'gibtEsNicht'));
console.log(gl.getFragDataLocation(program, 'gl_FragColor'));

// Robuste Hilfsfunktion
const requireFragLocation = (prog, name) => {
  const loc = gl.getFragDataLocation(prog, name);
  if (loc === -1) throw new Error(`Fragment-Ausgabe "${name}" nicht gefunden`);
  return loc;
};
-1 -1

// Wichtig · Fallstricke

  • Die Methode gibt nur nach einem erfolgreichen linkProgram() sinnvolle Werte zurück. Den Link-Status prüfst du vorher mit getProgramParameter(program, gl.LINK_STATUS). Bei einem nicht gelinkten Programm erzeugt die Methode den Fehler INVALID_OPERATION.
  • Sie gibt es nur in WebGL 2 (getContext('webgl2')) und mit Shadern in GLSL ES 3.00 (#version 300 es). In WebGL 1 schreibst du stattdessen über die Erweiterung WEBGL_draw_buffers in gl_FragData[n].
  • In WebGL 2 gibt es kein bindFragDataLocation(). Hat ein Shader mehrere Ausgaben, musst du bei jeder layout(location = N) angeben, sonst schlägt das Linken fehl.
  • Wird eine out-Variable im Shader nicht benutzt, entfernt der Compiler sie unter Umständen. Dann kommt -1 zurück.
  • Die Browser-Unterstützung ist gut: Chrome, Edge, Firefox und Safari 15+ unterstützen WebGL 2.