Start · Sprachen · JavaScript · Referenz · OES_standard_derivatives extension

OES_standard_derivatives extension

Schnittstelle

WebGL-1-Erweiterung, die im Fragment-Shader die GLSL-Ableitungsfunktionen <code>dFdx</code>, <code>dFdy</code> und <code>fwidth</code> freischaltet.

seit JavaScript WebGL 1 (Erweiterung); in WebGL 2 fest im Kern ent Kategorie: webapi

Signatur

interface OES_standard_derivatives

Beschreibung

Die Erweiterung OES_standard_derivatives gehört zur WebGL API. Ist sie aktiv, stehen in GLSL-ES-1.0-Fragment-Shadern die Funktionen dFdx(p), dFdy(p) und fwidth(p) zur Verfügung. Sie liefern, wie stark sich ein Wert von einem Bildpunkt zum benachbarten in x- bzw. y-Richtung ändert. fwidth(p) entspricht dabei abs(dFdx(p)) + abs(dFdy(p)).

Typische Anwendungen sind kantengeglättete Linien und Gitter (Antialiasing ohne MSAA), SDF-Schriftdarstellung (Signed Distance Fields), Flat Shading ohne eigene Normalen pro Fläche (die Normale wird aus cross(dFdx(pos), dFdy(pos)) berechnet) sowie eigene Berechnungen der Mip-Stufe.

Aktiviert wird die Erweiterung auf JavaScript-Seite mit gl.getExtension("OES_standard_derivatives"). Im Shader-Quelltext ist zusätzlich die Direktive #extension GL_OES_standard_derivatives : enable nötig. Das zurückgegebene Objekt hat keine Methoden, aber eine Konstante: FRAGMENT_SHADER_DERIVATIVE_HINT_OES (0x8B8B). Sie wird mit gl.hint() verwendet und bittet den Treiber um mehr Genauigkeit oder mehr Geschwindigkeit (gl.NICEST, gl.FASTEST, gl.DONT_CARE).

In WebGL 2 gehören diese Funktionen zum Standard von GLSL ES 3.00. Dort ist die Erweiterung weder vorhanden noch nötig, und getExtension gibt null zurück.

Parameter

Name Typ Default Beschreibung
$FRAGMENT_SHADER_DERIVATIVE_HINT_OES GLenum (0x8B8B) Konstante für gl.hint(target, mode) und gl.getParameter(). Legt fest, wie genau die Ableitungen berechnet werden sollen. Mögliche Werte für mode: gl.FASTEST, gl.NICEST oder gl.DONT_CARE (Standard).

Rückgabewert

Typ
OES_standard_derivatives | null
Beschreibung
gl.getExtension("OES_standard_derivatives") gibt das Erweiterungsobjekt zurück. Wird die Erweiterung nicht unterstützt oder handelt es sich um einen WebGL-2-Kontext, ist das Ergebnis null.

Beispiele

Erweiterung aktivieren und Hint setzen

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

const ext = gl.getExtension('OES_standard_derivatives');
if (!ext) {
  console.warn('Ableitungsfunktionen werden nicht unterstützt');
} else {
  // Höhere Genauigkeit anfordern
  gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.NICEST);
  const mode = gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
  console.log(mode === gl.NICEST);
}
true

Kantengeglättetes Gitter im Fragment-Shader

const gl = document.querySelector('canvas').getContext('webgl');
gl.getExtension('OES_standard_derivatives');

const fragSrc = `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
varying vec2 vUv;

void main() {
  vec2 coord = vUv * 10.0;
  // Breite eines Pixels im Gitterraum
  vec2 grid = abs(fract(coord - 0.5) - 0.5) / fwidth(coord);
  float line = min(grid.x, grid.y);
  float alpha = 1.0 - min(line, 1.0);
  gl_FragColor = vec4(vec3(alpha), 1.0);
}`;

const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fragSrc);
gl.compileShader(shader);
console.log(gl.getShaderParameter(shader, gl.COMPILE_STATUS));
true

Flat Shading mit Normalen aus dFdx/dFdy

const gl = document.querySelector('canvas').getContext('webgl');
const hasDerivatives = gl.getExtension('OES_standard_derivatives') !== null;

const fragSrc = `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
varying vec3 vViewPos;

void main() {
  // Flächennormale ohne Normalen-Attribut
  vec3 n = normalize(cross(dFdx(vViewPos), dFdy(vViewPos)));
  float light = max(dot(n, normalize(vec3(0.3, 0.5, 1.0))), 0.0);
  gl_FragColor = vec4(vec3(light), 1.0);
}`;

if (hasDerivatives) {
  const fs = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fs, fragSrc);
  gl.compileShader(fs);
  console.log(gl.getShaderInfoLog(fs) || 'Shader kompiliert');
}
Shader kompiliert

WebGL 1 und WebGL 2 gemeinsam behandeln

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

const supportsDerivatives = (gl) => {
  if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
    return true; // Fest im Kern von GLSL ES 3.00
  }
  return gl.getExtension('OES_standard_derivatives') !== null;
};

console.log(gl2 ? supportsDerivatives(gl2) : 'kein WebGL 2');
true

// Wichtig · Fallstricke

  • Es genügt nicht, nur getExtension() aufzurufen. Der Shader braucht zusätzlich #extension GL_OES_standard_derivatives : enable, sonst schlägt das Kompilieren mit „dFdx: no matching overloaded function“ oder einer ähnlichen Meldung fehl. Diese Direktive muss vor jedem anderen Code stehen, der kein Präprozessor-Code ist.
  • Die Funktionen gibt es nur im Fragment-Shader, nicht im Vertex-Shader.
  • Die Ableitungen werden für Blöcke von 2×2 Bildpunkten berechnet. Innerhalb von Verzweigungen, die nicht für alle Bildpunkte des Blocks gleich ausgehen (nicht-uniformer Kontrollfluss), sind die Ergebnisse undefiniert. Die Ableitungen sollten daher vor if-Zweigen berechnet werden.
  • Die Werte sind treiberabhängig und oft recht grob. FRAGMENT_SHADER_DERIVATIVE_HINT_OES ist nur ein Hinweis an den Treiber und keine Garantie.
  • In WebGL 2 (#version 300 es) gibt es die Erweiterung nicht. Dort darf auch keine #extension-Direktive für sie im Shader stehen.
  • Unterstützung: In WebGL 1 steht die Erweiterung in praktisch allen Desktop- und Mobil-Browsern zur Verfügung. Trotzdem sollte der Rückgabewert immer auf null geprüft werden.