Signatur
Beschreibung
Die schreibgeschützte Eigenschaft rangeMin eines WebGLShaderPrecisionFormat-Objekts sagt, wie weit der Wertebereich eines Shader-Datentyps (z. B. mediump float im Fragment-Shader) in den negativen Bereich reicht. Der Wert ist der Basis-2-Logarithmus des Betrags des kleinsten darstellbaren Wertes. Bei rangeMin = 127 reicht der Bereich also bis etwa -2^127.
Das Objekt bekommt man über gl.getShaderPrecisionFormat(shaderType, precisionType). Zusammen mit rangeMax und precision lässt sich damit prüfen, ob die GPU zum Beispiel highp im Fragment-Shader unterstützt oder ob mediump für Berechnungen mit großen Werten reicht. Das ist gerade auf Mobilgeräten wichtig.
Bei Gleitkommatypen entspricht rangeMin ungefähr dem Exponentenbereich: 127 bei IEEE-754-Single-Precision (highp float) und oft 15 bei Half-Precision (mediump float). Bei Ganzzahltypen (LOW_INT, MEDIUM_INT, HIGH_INT) gibt der Wert die Bitbreite des Bereichs an. Bei 32-Bit-Integern ist rangeMin zum Beispiel 31, der Bereich reicht dann also bis -2^31.
Rückgabewert
log2(|kleinster darstellbarer Wert|). Ist ein Präzisionstyp nicht verfügbar, ist der Wert 0.Beispiele
Wertebereich von highp float im Fragment-Shader auslesen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const fmt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
console.log('rangeMin:', fmt.rangeMin);
console.log('rangeMax:', fmt.rangeMax);
console.log('precision:', fmt.precision);
highp-Unterstützung prüfen und Shader-Präzision wählen
const gl = document.createElement('canvas').getContext('webgl');
const supportsHighp = () => {
const fmt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
// Ist highp nicht vorhanden, sind alle Felder 0
return fmt.rangeMin > 0 && fmt.precision > 0;
};
const precision = supportsHighp() ? 'highp' : 'mediump';
const fragmentSrc = `precision ${precision} float;
void main() { gl_FragColor = vec4(1.0); }`;
console.log('Verwende:', precision);
Übersicht aller Präzisionstypen als Tabelle
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 [sName, sType] of Object.entries(shaders)) {
for (const t of types) {
const { rangeMin, rangeMax, precision } = gl.getShaderPrecisionFormat(sType, gl[t]);
// Ungefährer kleinster Wert: -(2^rangeMin)
rows.push({ shader: sName, typ: t, rangeMin, rangeMax, precision, min: -(2 ** rangeMin) });
}
}
console.table(rows);
// Wichtig · Fallstricke
- Logarithmus, kein echter Wert:
rangeMinist ein Exponent. Den ungefähren kleinsten Wert bekommt man mit-(2 ** rangeMin). Der Wert ist positiv, obwohl er die untere, also negative Grenze beschreibt. - Hardwareabhängig: Die Werte kommen vom Treiber und von der GPU. Desktop-GPUs melden oft auch bei
LOW_FLOATundMEDIUM_FLOATdieselben Werte wie beihighp(127/127/23). Mobile GPUs melden dagegen häufig echte Half-Precision-Werte (15/15/10). - Nicht unterstützt: Fehlt ein Präzisionstyp, zum Beispiel
highpim Fragment-Shader unter WebGL 1 auf alter Hardware, sind alle drei Felder0. - Fingerprinting: Die Werte verraten Details über die Hardware und werden für Browser-Fingerprinting genutzt. Datenschutzfreundliche Browser können Standardwerte zurückgeben.
- Kompatibilität: Gibt es in WebGL 1 und WebGL 2 (
WebGL2RenderingContext) in allen modernen Browsern. Ist der Kontext verloren, gibtgetShaderPrecisionFormatnullzurück. Vor dem Zugriff also prüfen.