Start · Sprachen · JavaScript · Referenz · WebGLShaderPrecisionFormat.precision

WebGLShaderPrecisionFormat.precision

Eigenschaft

Schreibgeschützte Eigenschaft, die die Anzahl der Präzisions-Bits (Mantisse) eines Shader-Zahlenformats angibt, bei Ganzzahlformaten immer <code>0</code>.

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

Signatur

WebGLShaderPrecisionFormat.precision

Beschreibung

Die Eigenschaft precision eines WebGLShaderPrecisionFormat-Objekts gibt als Ganzzahl an, wie viele Bits Genauigkeit ein Zahlenformat im Shader hat. Genauer gesagt ist es der Logarithmus zur Basis 2 der relativen Genauigkeit: Beim Wert 23 (typisch für highp float, also IEEE-754 single precision) lassen sich Werte mit einer relativen Genauigkeit von etwa 2-23 darstellen.

Das Objekt selbst bekommst du nicht über einen Konstruktor, sondern über gl.getShaderPrecisionFormat(shaderType, precisionType). shaderType ist gl.VERTEX_SHADER oder gl.FRAGMENT_SHADER, precisionType einer der Werte LOW_FLOAT, MEDIUM_FLOAT, HIGH_FLOAT, LOW_INT, MEDIUM_INT oder HIGH_INT.

Gebraucht wird das vor allem, wenn du zur Laufzeit entscheiden willst, ob ein Fragment-Shader mit precision highp float; oder mit mediump kompiliert werden soll. Auf Mobilgeräten liefert mediump oft nur 10 Bits (ein Half-Float). Das reicht nicht für Aufgaben wie Weltkoordinaten, Tiefenwerte oder feine Texturkoordinaten in großen Texturen.

Bei Ganzzahlformaten (*_INT) ist precision immer 0, weil Ganzzahlen exakt dargestellt werden. Dort ist nur der Wertebereich über rangeMin und rangeMax wichtig.

Rückgabewert

Typ
number
Beschreibung
Nicht-negative Ganzzahl mit der Anzahl der Präzisions-Bits. Bei *_INT-Formaten immer 0. Unterstützt das Gerät ein Format nicht (z. B. highp im Fragment-Shader auf alter GLES2-Hardware), sind precision, rangeMin und rangeMax alle 0.

Beispiele

Präzision von highp float im Fragment-Shader abfragen

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

const fmt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
console.log(`precision: ${fmt.precision}, range: [-2^${fmt.rangeMin}, 2^${fmt.rangeMax}]`);
precision: 23, range: [-2^127, 2^127]

Passende Float-Präzision für den Fragment-Shader wählen

const pickFragmentPrecision = (gl) => {
  const high = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
  // precision === 0 bedeutet: highp wird nicht unterstützt
  return high && high.precision > 0 ? 'highp' : 'mediump';
};

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

const fragmentSource = `precision ${precision} float;
void main() {
  gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
}`;

console.log(fragmentSource.split('\n')[0]);
precision highp float;

Alle Präzisionsformate 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, shaderType] of Object.entries(shaders)) {
  for (const type of types) {
    const { precision, rangeMin, rangeMax } = gl.getShaderPrecisionFormat(shaderType, gl[type]);
    rows.push({ shader: shaderName, type, precision, rangeMin, rangeMax });
  }
}
console.table(rows);
Tabelle, z. B. auf dem Desktop: HIGH_FLOAT → precision 23, HIGH_INT → precision 0 (rangeMin 31, rangeMax 30); auf Mobilgeräten oft MEDIUM_FLOAT → precision 10

// Wichtig · Fallstricke

  • Nur lesbar: Wenn du der Eigenschaft einen Wert zuweist, passiert nichts (im Strict Mode gibt es einen TypeError).
  • Desktop gegen Mobil: Desktop-GPUs geben oft für alle Float-Stufen 23 zurück, weil sie intern immer mit 32 Bit rechnen. Tests auf dem Desktop verdecken deshalb leicht Präzisionsfehler, die erst auf Mobilgeräten mit mediump = 10 sichtbar werden.
  • Kein Support = 0: Wird ein Format nicht unterstützt, sind alle drei Werte 0. Prüfe immer precision > 0, bevor du highp im Fragment-Shader verwendest (unter WebGL 1 ist das optional, unter WebGL 2 Pflicht).
  • Verlorener Kontext: Ist der WebGL-Kontext verloren, gibt getShaderPrecisionFormat() null zurück. Greife also nicht ungeprüft auf .precision zu.
  • Datenschutz: Die Werte gehören zu den Merkmalen für Browser-Fingerprinting. Manche Browser (z. B. mit Schutz gegen Fingerprinting) geben daher vereinheitlichte Werte zurück.
  • Verfügbar in WebGLRenderingContext und WebGL2RenderingContext in allen modernen Browsern.