Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.getShaderPrecisionFormat()

WebGLRenderingContext.getShaderPrecisionFormat()

Methode

Liefert ein <code>WebGLShaderPrecisionFormat</code>-Objekt mit Wertebereich und Präzision eines numerischen Formats (z. B. <code>HIGH_FLOAT</code>) für Vertex- oder Fragment-Shader.

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

Signatur

WebGLRenderingContext.prototype.getShaderPrecisionFormat(shaderType, precisionType)

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);
127 127 23 // typischer Wert auf Desktop-GPUs (IEEE-754-float)

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));
highp true

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);
Tabelle mit 12 Zeilen, z. B. FRAGMENT_SHADER | HIGH_INT | 31 | 30 | 0

// Wichtig · Fallstricke

  • Ungültige Enums: Übergibst du falsche Werte, erzeugt die Methode den Fehler gl.INVALID_ENUM (abrufbar mit gl.getError()) und gibt null zurück.
  • Werte sind Exponenten: rangeMin und rangeMax sind Basis-2-Logarithmen und keine absoluten Werte. rangeMax = 127 bedeutet also einen Betrag bis etwa 2127.
  • Hardware-Unterschiede: Auf Desktop-Rechnern melden oft alle Stufen dieselbe 32-Bit-Präzision, weil lowp und mediump intern 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 highp im Fragment-Shader unterstützt werden. Dort dient die Abfrage vor allem der Diagnose.
  • Die Methode wird in allen modernen Browsern unterstützt.