Start · Sprachen · JavaScript · Referenz · EXT_color_buffer_half_float extension

EXT_color_buffer_half_float extension

Schnittstelle

WebGL-Erweiterung, mit der Texturen und Renderbuffer im 16-Bit-Gleitkommaformat (Half Float) als Farbanhang eines Framebuffers verwendet und beschrieben werden können.

seit JavaScript WebGL 1 und WebGL 2 (Baseline: weit verbreitet, ab Kategorie: webapi

Signatur

interface EXT_color_buffer_half_float

Beschreibung

EXT_color_buffer_half_float erlaubt es, in Farbpuffer mit 16-Bit-Gleitkommawerten zu rendern. Ohne sie kann WebGL 1 nur in 8-Bit-Formate mit normalisierten Werten zwischen 0 und 1 schreiben. Für HDR-Rendering, Tone-Mapping, Bloom, Deferred Shading, Partikelsimulationen oder GPGPU-Berechnungen reichen Wertebereich und Genauigkeit dann oft nicht aus. Half Float bietet Werte bis etwa ±65504 bei rund drei Dezimalstellen Genauigkeit und braucht dabei nur halb so viel Speicher und Bandbreite wie 32-Bit-Float.

Du aktivierst die Erweiterung mit gl.getExtension("EXT_color_buffer_half_float"). Das zurückgegebene Objekt hat keine Methoden, sondern nur Konstanten:

  • ext.RGBA16F_EXT (0x881A): internes Format für RGBA-Renderbuffer mit 16-Bit-Float-Werten.
  • ext.RGB16F_EXT (0x881B): internes Format für RGB-Renderbuffer. Als Renderziel wird es in der Praxis selten unterstützt.
  • ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT (0x8211): Abfrage-Schlüssel für getFramebufferAttachmentParameter(). Liefert den Komponententyp eines Anhangs.
  • ext.UNSIGNED_NORMALIZED_EXT (0x8C17): möglicher Rückgabewert dieser Abfrage (normalisierte Ganzzahlen ohne Vorzeichen, also ein „normaler“ 8-Bit-Puffer). Bei Float-Anhängen wird stattdessen gl.FLOAT geliefert.

In WebGL 1 brauchst du zum Rendern in eine Textur zusätzlich OES_texture_half_float. Die Textur legst du dann mit dem Typ HALF_FLOAT_OES (0x8D61) an. In WebGL 2 sind Half-Float-Texturen schon im Kern enthalten (gl.RGBA16F, gl.HALF_FLOAT). Hier sorgt die Erweiterung nur dafür, dass R16F, RG16F und RGBA16F als Renderziel gültig sind („color-renderable“). Wer auch 32-Bit-Float-Ziele braucht, nutzt in WebGL 2 stattdessen EXT_color_buffer_float. Diese Erweiterung schließt die 16-Bit-Formate mit ein.

Rückgabewert

Typ
EXT_color_buffer_half_float | null
Beschreibung
gl.getExtension("EXT_color_buffer_half_float") gibt das Erweiterungsobjekt mit den Konstanten zurück. Wird die Erweiterung vom Browser oder der GPU nicht unterstützt, ist das Ergebnis null.

Beispiele

WebGL 1: in eine Half-Float-Textur rendern

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

const texExt = gl.getExtension('OES_texture_half_float');
const cbExt = gl.getExtension('EXT_color_buffer_half_float');

if (!texExt || !cbExt) {
  throw new Error('Half-Float-Rendering wird nicht unterstützt');
}

const width = 512;
const height = 512;

// Textur mit 16-Bit-Float pro Kanal anlegen
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
  gl.RGBA, texExt.HALF_FLOAT_OES, null);
// Lineares Filtern bräuchte OES_texture_half_float_linear
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

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

const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(status === gl.FRAMEBUFFER_COMPLETE ? 'HDR-FBO bereit' : 'FBO unvollständig');
HDR-FBO bereit

WebGL 1: Renderbuffer mit RGBA16F_EXT

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

if (ext) {
  const rb = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
  gl.renderbufferStorage(gl.RENDERBUFFER, ext.RGBA16F_EXT, 256, 256);

  const fbo = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    gl.RENDERBUFFER, rb);

  // Komponententyp des Anhangs abfragen
  const type = gl.getFramebufferAttachmentParameter(
    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT);

  console.log(type === gl.FLOAT ? 'Float-Anhang' : 'Normalisierter Anhang');
}
Float-Anhang

WebGL 2: RGBA16F-Renderziel mit Fallback

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

// EXT_color_buffer_float deckt 16- und 32-Bit-Float ab
const canRenderHalf =
  gl.getExtension('EXT_color_buffer_float') !== null ||
  gl.getExtension('EXT_color_buffer_half_float') !== null;

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);

if (canRenderHalf) {
  gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA16F, 1024, 1024);
} else {
  // Fallback: 8-Bit, kein HDR
  gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1024, 1024);
}

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

console.log(canRenderHalf ? 'Rendern in RGBA16F' : 'Fallback RGBA8');
Rendern in RGBA16F