Start · Sprachen · JavaScript · Referenz · EXT_shader_texture_lod extension

EXT_shader_texture_lod extension

Schnittstelle

WebGL-1-Erweiterung, mit der Fragment-Shader das Mipmap-Level (LOD) oder die Gradienten beim Texturzugriff ausdrücklich selbst festlegen können.

seit JavaScript WebGL 1 (Erweiterung); in WebGL 2 fester Bestandte Kategorie: webapi

Signatur

interface EXT_shader_texture_lod

Beschreibung

EXT_shader_texture_lod ist eine Erweiterung für WebGL 1. Normalerweise wählt die GPU im Fragment-Shader das Mipmap-Level einer Textur automatisch aus. Grundlage dafür sind die Bildschirm-Ableitungen der Texturkoordinaten. Mit dieser Erweiterung bestimmt der Shader das Level selbst, entweder direkt als LOD-Wert oder über eigene Gradienten.

Das Erweiterungsobjekt in JavaScript hat keine eigenen Methoden oder Konstanten. Es genügt, gl.getExtension('EXT_shader_texture_lod') aufzurufen. Danach aktiviert der GLSL-Code die Erweiterung mit #extension GL_EXT_shader_texture_lod : enable. Anschließend stehen im Fragment-Shader diese Funktionen bereit:

  • texture2DLodEXT(sampler2D, vec2 coord, float lod)
  • texture2DProjLodEXT(sampler2D, vec3|vec4 coord, float lod)
  • textureCubeLodEXT(samplerCube, vec3 coord, float lod)
  • texture2DGradEXT(sampler2D, vec2 coord, vec2 dPdx, vec2 dPdy)
  • texture2DProjGradEXT(sampler2D, vec3|vec4 coord, vec2 dPdx, vec2 dPdy)
  • textureCubeGradEXT(samplerCube, vec3 coord, vec3 dPdx, vec3 dPdy)

Typische Einsatzfälle:

  • Physikalisch basiertes Rendering (PBR): Eine vorgefilterte Umgebungs-Cubemap wird passend zur Rauheit der Oberfläche in einem bestimmten Mipmap-Level gelesen.
  • Texturatlanten mit Kachelung: fract() erzeugt Sprünge in den Koordinaten, und die automatisch berechneten Ableitungen werden dort riesig. Mit eigenen Gradienten entstehen keine sichtbaren Nähte.
  • Gezielte Unschärfe und Nachbearbeitung: Bloom-, Tiefenschärfe- oder Blur-Effekte lesen absichtlich gröbere Mipmap-Stufen.
  • Texturzugriff in Verzweigungen und Schleifen: Dort sind die automatischen Ableitungen undefiniert. Ein ausdrücklicher LOD macht das Ergebnis vorhersagbar.

Rückgabewert

Typ
EXT_shader_texture_lod | null
Beschreibung
gl.getExtension('EXT_shader_texture_lod') gibt ein Erweiterungsobjekt ohne eigene Mitglieder zurück. Wird die Erweiterung nicht unterstützt, ist der Rückgabewert null.

Beispiele

Erweiterung aktivieren und Unterstützung prüfen

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

const ext = gl.getExtension('EXT_shader_texture_lod');
if (ext) {
  console.log('EXT_shader_texture_lod verfügbar');
} else {
  console.warn('Nicht unterstützt – Fallback auf texture2D mit Bias nötig');
}
EXT_shader_texture_lod verfügbar

PBR: Umgebungs-Cubemap passend zur Rauheit lesen

const gl = document.querySelector('canvas').getContext('webgl');
if (!gl.getExtension('EXT_shader_texture_lod')) {
  throw new Error('EXT_shader_texture_lod fehlt');
}

const fragmentSource = `
#extension GL_EXT_shader_texture_lod : enable
precision mediump float;

uniform samplerCube uEnvMap;
uniform float uRoughness;   // 0.0 = glatt, 1.0 = rau
uniform float uMaxLod;      // z. B. log2(Kantenlänge)
varying vec3 vReflectDir;

void main() {
  float lod = uRoughness * uMaxLod;
  vec3 color = textureCubeLodEXT(uEnvMap, normalize(vReflectDir), lod).rgb;
  gl_FragColor = vec4(color, 1.0);
}`;

const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fragmentSource);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  console.error(gl.getShaderInfoLog(shader));
} else {
  console.log('Shader kompiliert');
}
Shader kompiliert

Nahtlose Kachelung im Texturatlas mit eigenen Gradienten

const gl = document.querySelector('canvas').getContext('webgl');
gl.getExtension('EXT_shader_texture_lod');
// dFdx/dFdy benötigen zusätzlich OES_standard_derivatives
gl.getExtension('OES_standard_derivatives');

const fragmentSource = `
#extension GL_EXT_shader_texture_lod : enable
#extension GL_OES_standard_derivatives : enable
precision mediump float;

uniform sampler2D uAtlas;
uniform vec4 uTileRect;  // xy = Offset, zw = Größe im Atlas
varying vec2 vUv;

void main() {
  vec2 tiled = fract(vUv * 4.0);
  vec2 atlasUv = uTileRect.xy + tiled * uTileRect.zw;
  // Gradienten aus den stetigen Koordinaten, nicht aus fract()
  vec2 grad = vUv * 4.0 * uTileRect.zw;
  gl_FragColor = texture2DGradEXT(uAtlas, atlasUv, dFdx(grad), dFdy(grad));
}`;

const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fragmentSource);
gl.compileShader(shader);
console.log(gl.getShaderParameter(shader, gl.COMPILE_STATUS));
true

// Wichtig · Fallstricke

  • Reihenfolge: gl.getExtension() muss vor dem Kompilieren des Shaders aufgerufen werden. Sonst bricht das Kompilieren bei der #extension-Direktive oder bei den *EXT-Funktionen ab.
  • Die #extension-Direktive muss vor allen anderen Anweisungen stehen, also auch vor precision.
  • WebGL 2: Dort gibt es diese Erweiterung nicht. In GLSL ES 3.00 (#version 300 es) sind textureLod() und textureGrad() fest eingebaut.
  • Die Funktionen sind nur im Fragment-Shader verfügbar. Im Vertex-Shader von WebGL 1 gibt es bereits texture2DLod() ohne Suffix.
  • Die Textur braucht vollständige Mipmaps (gl.generateMipmap()) und einen Mipmap-Filter wie gl.LINEAR_MIPMAP_LINEAR. Sonst hat der LOD-Wert keine Wirkung. In WebGL 1 setzt generateMipmap Texturen mit Zweierpotenz-Maßen voraus.
  • Für dFdx/dFdy ist zusätzlich OES_standard_derivatives nötig.
  • Kompatibilität: Auf Desktop-Browsern breit unterstützt, auf älteren Mobilgeräten teils nicht. Plane immer einen Fallback ein, etwa texture2D(sampler, uv, bias).