Signatur
Beschreibung
Mit getShaderPrecisionFormat() fragst du ab, wie genau die GPU bestimmte numerische Formate in GLSL-Shadern tatsächlich darstellt. Du bekommst ein WebGLShaderPrecisionFormat-Objekt mit drei schreibgeschützten Eigenschaften: rangeMin und rangeMax (Basis-2-Logarithmus des kleinsten bzw. größten darstellbaren Betrags) sowie precision (Anzahl der Präzisionsbits, bei Ganzzahlformaten immer 0).
Besonders nützlich ist die Methode, bevor du einen Fragment-Shader mit precision highp float; kompilierst: In GLSL ES 1.0 ist highp im Fragment-Shader nämlich optional. Viele ältere Mobil-GPUs unterstützen dort nur mediump. Meldet HIGH_FLOAT im FRAGMENT_SHADER eine Präzision von 0, gibt es keine Unterstützung. Dann solltest du auf mediump ausweichen.
Gültige Werte für den Shader-Typ sind gl.VERTEX_SHADER und gl.FRAGMENT_SHADER. Als Präzisionstyp sind LOW_FLOAT, MEDIUM_FLOAT, HIGH_FLOAT, LOW_INT, MEDIUM_INT und HIGH_INT möglich. Die Methode gibt es auch in WebGL2RenderingContext.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $shaderType Pflicht | GLenum | Shader-Typ: gl.VERTEX_SHADER oder gl.FRAGMENT_SHADER. |
|
| $precisionType Pflicht | GLenum | Numerisches Format: gl.LOW_FLOAT, gl.MEDIUM_FLOAT, gl.HIGH_FLOAT, gl.LOW_INT, gl.MEDIUM_INT oder gl.HIGH_INT. |
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(fmt.rangeMin, fmt.rangeMax, fmt.precision);
Passende Präzisionsangabe für den Shader wählen
const pickFragmentPrecision = (gl) => {
const high = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
return high && high.precision > 0 ? 'highp' : 'mediump';
};
const gl = document.createElement('canvas').getContext('webgl');
const precision = pickFragmentPrecision(gl);
const fsSource = `precision ${precision} float;
void main() {
gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
}`;
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fsSource);
gl.compileShader(shader);
console.log(precision, gl.getShaderParameter(shader, gl.COMPILE_STATUS));
Alle Formate als Tabelle ausgeben (Diagnose)
const gl = document.createElement('canvas').getContext('webgl');
const shaders = { VERTEX_SHADER: gl.VERTEX_SHADER, FRAGMENT_SHADER: 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]);
rows.push({ shader: sName, type: t, rangeMin, rangeMax, precision });
}
}
console.table(rows);
// Wichtig · Fallstricke
- Ungültige Enums: Übergibst du falsche Werte, erzeugt die Methode den Fehler
gl.INVALID_ENUM(abrufbar mitgl.getError()) und gibtnullzurück. - Werte sind Exponenten:
rangeMinundrangeMaxsind Basis-2-Logarithmen und keine absoluten Werte.rangeMax = 127bedeutet also einen Betrag bis etwa 2127. - Hardware-Unterschiede: Auf Desktop-Rechnern melden oft alle Stufen dieselbe 32-Bit-Präzision, weil
lowpundmediumpintern hochgestuft werden. Wenn du auf dem Desktop testest, übersiehst du deshalb leicht Präzisionsfehler, die nur auf Mobilgeräten auftreten. - Fingerprinting: Die Werte können zur Geräteerkennung genutzt werden. Manche Browser mit Datenschutzmodus (z. B. Tor, Brave) geben deshalb vereinheitlichte Werte zurück.
- In WebGL 2 (GLSL ES 3.00) muss
highpim Fragment-Shader unterstützt werden. Dort dient die Abfrage vor allem der Diagnose. - Die Methode wird in allen modernen Browsern unterstützt.