Start · Sprachen · JavaScript · Referenz · EXT_color_buffer_float extension

EXT_color_buffer_float extension

Schnittstelle

WebGL-2-Erweiterung, mit der Gleitkomma-Texturformate wie <code>RGBA16F</code>, <code>RGBA32F</code> oder <code>R11F_G11F_B10F</code> als Farb-Renderziel in Framebuffern nutzbar werden.

seit JavaScript WebGL 2; Baseline: alle modernen Browser (auf Desk Kategorie: webapi

Signatur

interface EXT_color_buffer_float

Beschreibung

EXT_color_buffer_float ist eine Erweiterung für WebGL 2. Sie macht Gleitkommaformate color-renderable, also als Farbanhang (COLOR_ATTACHMENTn) eines Framebuffers verwendbar. Standardmäßig kann WebGL 2 Gleitkommatexturen zwar anlegen und auslesen, aber nicht in sie rendern. Mit der Erweiterung wird das für diese interne Formate möglich:

  • gl.R16F, gl.RG16F, gl.RGBA16F
  • gl.R32F, gl.RG32F, gl.RGBA32F
  • gl.R11F_G11F_B10F

Typische Einsatzgebiete sind HDR-Rendering und Tone-Mapping, Deferred Shading (G-Buffer mit Normalen oder Positionen in hoher Genauigkeit), GPGPU-Berechnungen wie Partikelsimulationen oder Strömungssimulationen, bei denen Zwischenergebnisse als Float-Texturen gespeichert werden, sowie Bloom- und Post-Processing-Ketten.

Die Erweiterung hat weder eigene Konstanten noch Methoden. Es reicht, sie mit gl.getExtension('EXT_color_buffer_float') einmal zu aktivieren. Danach nutzt du die normalen WebGL-2-Konstanten für die Formate. Ist die Erweiterung nicht verfügbar, gibt getExtension() null zurück. Framebuffer mit Float-Anhängen melden dann FRAMEBUFFER_INCOMPLETE_ATTACHMENT.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Wird an WebGL2RenderingContext.getExtension() übergeben und muss genau 'EXT_color_buffer_float' lauten.

Rückgabewert

Typ
EXT_color_buffer_float | null
Beschreibung
getExtension() gibt ein leeres Erweiterungsobjekt ohne Eigenschaften zurück, wenn die Erweiterung unterstützt wird. Wird sie nicht unterstützt, ist der Rückgabewert null. Schon der erfolgreiche Aufruf aktiviert die Erweiterung.

Beispiele

Erweiterung aktivieren und Unterstützung prüfen

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

if (!gl) {
  console.log('WebGL 2 wird nicht unterstützt');
} else {
  const ext = gl.getExtension('EXT_color_buffer_float');
  console.log(ext ? 'Float-Renderziele verfügbar' : 'Keine Float-Renderziele – Fallback auf RGBA8');
}
Float-Renderziele verfügbar

HDR-Framebuffer mit RGBA16F-Textur anlegen

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

const width = 1024;
const height = 768;

// Gleitkommatextur als Renderziel
const hdrTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, hdrTex);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA16F, width, height);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, hdrTex, 0);

const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(status === gl.FRAMEBUFFER_COMPLETE ? 'HDR-FBO bereit' : `Unvollständig: 0x${status.toString(16)}`);

// Werte > 1.0 bleiben erhalten
gl.viewport(0, 0, width, height);
gl.clearBufferfv(gl.COLOR, 0, [4.0, 2.0, 0.5, 1.0]);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
HDR-FBO bereit

GPGPU: Ergebnis aus RGBA32F-Framebuffer zurücklesen

const gl = document.createElement('canvas').getContext('webgl2');
gl.getExtension('EXT_color_buffer_float');

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA32F, 2, 2);

const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);

// Simuliertes Rechenergebnis
gl.clearBufferfv(gl.COLOR, 0, [3.14159, -1.5, 1e6, 0.001]);

// Float-Pixel auslesen (RGBA + FLOAT geht immer bei RGBA32F)
const pixels = new Float32Array(2 * 2 * 4);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.FLOAT, pixels);
console.log(Array.from(pixels.slice(0, 4)));
[3.141590118408203, -1.5, 1000000, 0.0010000000474974513]

// Wichtig · Fallstricke

  • Nur WebGL 2: In einem WebGL-1-Kontext gibt es diese Erweiterung nicht. Dort brauchst du WEBGL_color_buffer_float (für 32 Bit) und EXT_color_buffer_half_float (für 16 Bit), zusammen mit OES_texture_float bzw. OES_texture_half_float.
  • Keine RGB-Formate: RGB16F und RGB32F werden durch die Erweiterung nicht renderbar. Nimm stattdessen RGBA16F/RGBA32F oder das kompakte R11F_G11F_B10F.
  • Blending: Bei 32-Bit-Float-Zielen (R32F, RG32F, RGBA32F) setzt Blending zusätzlich die Erweiterung EXT_float_blend voraus. Ohne sie erzeugt ein Draw-Aufruf mit aktivem gl.BLEND den Fehler INVALID_OPERATION. 16-Bit-Formate lassen sich dagegen immer blenden.
  • Filterung: Lineare Filterung von 32-Bit-Float-Texturen braucht OES_texture_float_linear. Ohne die Erweiterung musst du NEAREST verwenden, sonst sampelt der Shader Schwarz.
  • Mobilgeräte: Viele mobile GPUs unterstützen die Erweiterung nicht oder nur eingeschränkt. Frag die Unterstützung immer zur Laufzeit ab und sieh einen Fallback vor, z. B. RGBA8 mit RGBM-Kodierung oder EXT_color_buffer_half_float. Prüf außerdem immer checkFramebufferStatus().
  • Speicherbedarf: RGBA32F belegt 16 Byte pro Pixel, also viermal so viel wie RGBA8. Für HDR reicht meist RGBA16F oder R11F_G11F_B10F.