Start · Sprachen · JavaScript · Referenz · WebGLShaderPrecisionFormat

WebGLShaderPrecisionFormat

Schnittstelle

Beschreibt Wertebereich und Genauigkeit eines Shader-Zahlenformats, wie sie <code>getShaderPrecisionFormat()</code> für einen Shader-Typ und eine Präzisionsstufe liefert.

seit JavaScript WebGL 1.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

interface WebGLShaderPrecisionFormat

Beschreibung

WebGLShaderPrecisionFormat ist ein reines Datenobjekt der WebGL-API. Man erzeugt es nicht selbst. Man bekommt es als Rückgabewert von WebGLRenderingContext.getShaderPrecisionFormat(shaderType, precisionType) bzw. der gleichnamigen Methode von WebGL2RenderingContext. Das Objekt sagt, wie genau die GPU Gleitkomma- oder Ganzzahlen einer bestimmten Präzisionsstufe (lowp, mediump, highp) im Vertex- oder Fragment-Shader tatsächlich darstellt.

Es hat drei schreibgeschützte Eigenschaften:

  • rangeMin (number): Basis-2-Logarithmus des Betrags der kleinsten darstellbaren Zahl, z. B. 127 für etwa −2127.
  • rangeMax (number): Basis-2-Logarithmus des Betrags der größten darstellbaren Zahl.
  • precision (number): Anzahl der Bits Genauigkeit (Mantisse). Bei Ganzzahlformaten ist der Wert 0.

In der Praxis nutzt man die Schnittstelle vor allem, um herauszufinden, ob highp im Fragment-Shader unterstützt wird. Auf manchen mobilen GPUs liefert sie dann precision === 0. Mit dieser Information kann man GLSL-Code mit passender precision-Deklaration erzeugen oder Genauigkeitsfehler (Banding, Flackern, Z-Fighting bei Berechnungen im Shader) erklären.

Rückgabewert

Typ
WebGLShaderPrecisionFormat
Beschreibung
Instanzen entstehen nur durch gl.getShaderPrecisionFormat(). Die Methode gibt null zurück, wenn der Kontext verloren ist (context lost).

Beispiele

Präzisionsformat abfragen

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

const fmt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
console.log(fmt instanceof WebGLShaderPrecisionFormat);
console.log(fmt.rangeMin, fmt.rangeMax, fmt.precision);
true 127 127 23 // typisch für Desktop-GPUs (IEEE-754 float32)

highp-Unterstützung im Fragment-Shader prüfen und GLSL anpassen

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

const supportsHighpFragment = (gl) => {
  const fmt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
  return fmt !== null && fmt.precision > 0;
};

const precision = supportsHighpFragment(gl) ? 'highp' : 'mediump';
const fragmentSource = `precision ${precision} float;
void main() {
  gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
}`;

console.log(`Verwende ${precision}`);
Verwende highp

Übersicht aller Formate als Tabelle ausgeben

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

const shaders = { VERTEX: gl.VERTEX_SHADER, FRAGMENT: gl.FRAGMENT_SHADER };
const types = ['LOW_FLOAT', 'MEDIUM_FLOAT', 'HIGH_FLOAT', 'LOW_INT', 'MEDIUM_INT', 'HIGH_INT'];

const rows = [];
for (const [shaderName, shader] of Object.entries(shaders)) {
  for (const type of types) {
    const { rangeMin, rangeMax, precision } = gl.getShaderPrecisionFormat(shader, gl[type]);
    rows.push({ shader: shaderName, type, rangeMin, rangeMax, precision });
  }
}
console.table(rows);
Tabelle mit 12 Zeilen, z. B. FRAGMENT | MEDIUM_FLOAT | 14 | 14 | 10 auf mobilen GPUs

// Wichtig · Fallstricke

  • Kein Konstruktor: new WebGLShaderPrecisionFormat() wirft einen TypeError. Instanzen liefert nur getShaderPrecisionFormat().
  • rangeMin/rangeMax sind Exponenten (log2), keine absoluten Werte. rangeMin steht für den Betrag des negativen Grenzwerts und ist deshalb positiv.
  • Desktop gegen Mobil: Desktop-Browser melden oft für alle Stufen die Werte von highp (127/127/23), weil die GPU intern immer mit 32 Bit rechnet. Wenn der Desktop mediump meldet, heißt das also nicht, dass Mobilgeräte es genauso umsetzen. Auf mobilen Geräten deshalb gezielt testen.
  • Ganzzahlformate: Bei LOW_INT, MEDIUM_INT und HIGH_INT ist precision immer 0.
  • Kontextverlust: Ist der Kontext verloren, gibt getShaderPrecisionFormat() null zurück. Vor dem Zugriff auf die Eigenschaften also auf null prüfen.
  • Fingerprinting: Die Werte verraten Eigenschaften der Hardware. Datenschutzorientierte Browser (z. B. Firefox mit privacy.resistFingerprinting, Tor Browser) können vereinheitlichte Werte melden.
  • Kompatibilität: Wird in allen modernen Browsern unterstützt, in WebGL 1 und WebGL 2 gleich.