function main() {
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) {
return alert('need webgl2');
}
// without this we can't render to RGBA32F
if (!gl.getExtension('EXT_color_buffer_float')) {
return alert('need EXT_color_buffer_float');
}
// just guessing without this we can't downsample
if (!gl.getExtension('OES_texture_float_linear')) {
return alert('need OES_texture_float_linear');
}
const msFB = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, msFB);
const msRB = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, msRB);
const samples = 4;
const internalFormat = gl.RGBA32F;
const width = 16;
const height = 16;
gl.renderbufferStorageMultisample(
gl.RENDERBUFFER, samples, internalFormat, width, height);
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msRB);
checkFramebuffer(gl);
gl.clearColor(1,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
const texFB = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, texFB);
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
const level = 0;
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, 0,
gl.RGBA, gl.FLOAT, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.framebufferTexture2D(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
checkFramebuffer(gl);
// check before
checkPixel(gl, 'before blit')
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, msFB);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, texFB);
gl.blitFramebuffer(
0, 0, width, height,
0, 0, width, height,
gl.COLOR_BUFFER_BIT, gl.LINEAR);
console.log('ERROR?:', glEnumToString(gl, gl.getError()));
gl.bindFramebuffer(gl.FRAMEBUFFER, texFB);
checkPixel(gl, 'after blit:');
}
function checkFramebuffer(gl) {
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status !== gl.FRAMEBUFFER_COMPLETE) {
console.error(glEnumToString(gl, status));
}
}
function checkPixel(gl, msg) {
const pixel = new Float32Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, pixel);
console.log(msg, Array.from(pixel).join(', '));
}
function glEnumToString(gl, v) {
const hits = [];
for (const key in gl) {
if (gl[key] === v) {
hits.push(key);
}
}
return hits.length ? hits.join(' | ') : `0x${v.toString(16)}`;
}
main();
<canvas></canvas>