Start · Sprachen · JavaScript · Referenz · OES_texture_float extension

OES_texture_float extension

Schnittstelle

WebGL-1-Erweiterung, mit der Texturen Gleitkomma-Pixeldaten vom Typ <code>gl.FLOAT</code> (32 Bit) speichern können.

seit JavaScript WebGL 1 (Erweiterung); in WebGL 2 fest integriert Kategorie: webapi

Signatur

interface OES_texture_float

Beschreibung

Die Erweiterung OES_texture_float gehört zur WebGL-API. Sie erlaubt es, gl.FLOAT als Typ-Parameter in texImage2D() und texSubImage2D() anzugeben. Texturen speichern ihre Werte dann als 32-Bit-Gleitkommazahlen statt als 8-Bit-Ganzzahlen von 0 bis 255. Die Schnittstelle bringt weder eigene Methoden noch Konstanten mit. Ist die Erweiterung aktiviert, akzeptiert WebGL einfach den bereits vorhandenen Wert gl.FLOAT.

Gleitkomma-Texturen braucht man vor allem für GPGPU-Berechnungen (z. B. Partikelsimulationen, Physik, Bildfilter mit hoher Genauigkeit), für HDR-Rendering, Shadow Maps, Deferred Shading und für Daten wie Höhenkarten, deren Werte außerhalb von [0, 1] liegen.

Sie aktivieren die Erweiterung mit gl.getExtension('OES_texture_float'). Ist sie nicht verfügbar, erhalten Sie null. Wichtig: Die Erweiterung erlaubt nur das Hochladen und Abtasten mit gl.NEAREST. Für lineare Filterung brauchen Sie zusätzlich OES_texture_float_linear. Um in eine Float-Textur zu rendern (als Anhang eines Framebuffers), brauchen Sie WEBGL_color_buffer_float.

In WebGL 2 ist die Funktion Teil des Kerns. Dort nutzen Sie ein Sized Internal Format wie gl.RGBA32F zusammen mit gl.FLOAT. Die Erweiterung gibt es in WebGL-2-Kontexten nicht.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Argument für gl.getExtension(): exakt 'OES_texture_float'.

Rückgabewert

Typ
OES_texture_float | null
Beschreibung
gl.getExtension('OES_texture_float') gibt das Erweiterungsobjekt zurück, falls die Erweiterung unterstützt wird, sonst null. Das Objekt selbst hat keine Eigenschaften oder Methoden.

Beispiele

Erweiterung aktivieren und Unterstützung prüfen

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

const ext = gl.getExtension('OES_texture_float');
if (!ext) {
  console.warn('Gleitkomma-Texturen werden nicht unterstützt.');
} else {
  console.log('OES_texture_float aktiv:', ext);
}
OES_texture_float aktiv: OES_texture_float {}

Float-Textur mit Simulationsdaten erstellen

const gl = document.createElement('canvas').getContext('webgl');
if (!gl.getExtension('OES_texture_float')) {
  throw new Error('Keine Float-Texturen verfügbar');
}

const size = 64;
// Positionen von 64×64 Partikeln (RGBA = x, y, z, w)
const data = new Float32Array(size * size * 4);
for (let i = 0; i < data.length; i += 4) {
  data[i] = Math.random() * 100 - 50;     // Werte außerhalb von [0,1] möglich
  data[i + 1] = Math.random() * 100 - 50;
  data[i + 2] = 0;
  data[i + 3] = 1;
}

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
// Ohne OES_texture_float_linear nur NEAREST verwenden!
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.FLOAT, data);

console.log('Fehler:', gl.getError() === gl.NO_ERROR ? 'keiner' : gl.getError());
Fehler: keiner

Prüfen, ob in Float-Texturen gerendert werden kann

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

const canRenderToFloat = () => {
  const tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.FLOAT, null);

  const fb = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
  const ok = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;

  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.deleteFramebuffer(fb);
  gl.deleteTexture(tex);
  return ok;
};

console.log('Render-to-Float möglich:', canRenderToFloat());
Render-to-Float möglich: true

WebGL 2: gleiche Funktion ohne Erweiterung

const gl2 = document.createElement('canvas').getContext('webgl2');
const tex = gl2.createTexture();
gl2.bindTexture(gl2.TEXTURE_2D, tex);
gl2.texParameteri(gl2.TEXTURE_2D, gl2.TEXTURE_MIN_FILTER, gl2.NEAREST);
gl2.texParameteri(gl2.TEXTURE_2D, gl2.TEXTURE_MAG_FILTER, gl2.NEAREST);
// Sized Internal Format RGBA32F statt RGBA
gl2.texImage2D(gl2.TEXTURE_2D, 0, gl2.RGBA32F, 2, 2, 0, gl2.RGBA, gl2.FLOAT,
  new Float32Array(16).fill(1.5));
console.log(gl2.getExtension('OES_texture_float'));
null

// Wichtig · Fallstricke

  • Filterung: Ohne OES_texture_float_linear ist eine Float-Textur mit gl.LINEAR oder Mipmap-Filtern „unvollständig“. Im Shader wird sie dann als Schwarz (0, 0, 0, 1) abgetastet. Eine Fehlermeldung gibt es dabei nicht.
  • Rendern in Float-Texturen: Das garantiert die Erweiterung nicht. Aktivieren Sie WEBGL_color_buffer_float und prüfen Sie immer mit checkFramebufferStatus(). Manche älteren Implementierungen haben das stillschweigend erlaubt. Darauf sollten Sie sich nicht verlassen.
  • Mobilgeräte: Viele Mobil-GPUs unterstützen zwar 16-Bit-Floats (OES_texture_half_float), aber keine 32-Bit-Floats oder deren Filterung. Planen Sie eine Ausweichlösung ein.
  • Datenquelle: Mit gl.FLOAT muss das Pixel-Array ein Float32Array sein. Ein Uint8Array führt zu INVALID_OPERATION.
  • WebGL 2: Dort gibt getExtension('OES_texture_float') null zurück. Verwenden Sie Sized Formats wie gl.RGBA32F, gl.R32F und für Framebuffer EXT_color_buffer_float.
  • Speicher: Eine RGBA32F-Textur belegt 16 Byte pro Pixel, viermal so viel wie RGBA8. Eine 4096×4096-Textur braucht also etwa 256 MB.
  • Fingerprinting: Welche Erweiterungen verfügbar sind, kann zur Identifizierung von Geräten beitragen. Einige Browser schränken die Liste deshalb im Datenschutzmodus ein.