具有 FLOAT 纹理的帧缓冲区上的 webGL 2 readPixels
webGL 2 readPixels on framebuffers with FLOAT textures
是否可以在具有多个附件的帧缓冲区上以浮点形式检索像素值? (WebGL 2)
我试过了:
var framebuffer = _gl.createFramebuffer();
_gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, texture1, 0);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT1, _gl.TEXTURE_2D, texture2, 0);
_gl.drawBuffers([_gl.COLOR_ATTACHMENT0, _gl.COLOR_ATTACHMENT1]);
浮动纹理设置如下:
_gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA32F, 256, 256, 0, _gl.RGBA, _gl.FLOAT, null);
然后我绑定帧缓冲区并调用 readPixels 以获取第一个附件的值:
_gl.readPixels(0, 0, 1, 256, _gl.RGBA, _gl.FLOAT, 0);
在没有浮动纹理的情况下,这项工作有效,但对于浮动纹理,帧缓冲区保持不完整。
WebGL 2 规范似乎说这应该有效,但我现在有些怀疑,似乎 _gl.RGBA32F 似乎是问题所在,内部格式为 _gl.RGBA,它会产生不兼容的类型错误。
首先,浮点渲染需要 WebGL2 中的扩展,EXT_color_buffer_float
。
您可以在 table here copied from the spec section 3.8.3.2 中看到浮点纹理在默认情况下无法在 WebGL2 中渲染。
否则在调用 gl.readPixels
之前调用 gl.readBuffer
设置要读取的缓冲区
示例:
function main() {
const gl = document.createElement("canvas").getContext("webgl2");
if (!gl) {
alert("need WebGL2");
return;
}
const ext = gl.getExtension("EXT_color_buffer_float");
if (!ext) {
alert("need EXT_color_buffer_float");
return;
}
const tex1 = createTexture(gl, [12, 0, 0, 34]);
const tex2 = createTexture(gl, [0, 56, 78, 0]);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex2, 0);
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
readPixelsFromBuffer(gl, gl.COLOR_ATTACHMENT0);
readPixelsFromBuffer(gl, gl.COLOR_ATTACHMENT1);
}
function readPixelsFromBuffer(gl, attachment) {
gl.readBuffer(attachment);
const data = new Float32Array(4);
const x = 0;
const y = 0;
const width = 1;
const height = 1;
const format = gl.RGBA;
const type = gl.FLOAT;
gl.readPixels(x, y, width, height, format, type, data);
log(glEnumToString(gl, attachment), data);
}
function createTexture(gl, color) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
const level = 0;
const internalFormat = gl.RGBA32F;
const width = 1;
const height = 1;
const border = 0;
const format = gl.RGBA;
const type = gl.FLOAT;
const data = new Float32Array(color);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border,
format, type, data);
// unless we get `OES_texture_float_linear` we can not filter floating point
// textures
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
return tex;
}
function glEnumToString(gl, value) {
for (let key in gl) {
if (gl[key] === value) {
return key;
}
}
return `0x${value.toString(16)}`;
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
main();
是否可以在具有多个附件的帧缓冲区上以浮点形式检索像素值? (WebGL 2)
我试过了:
var framebuffer = _gl.createFramebuffer();
_gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, texture1, 0);
_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT1, _gl.TEXTURE_2D, texture2, 0);
_gl.drawBuffers([_gl.COLOR_ATTACHMENT0, _gl.COLOR_ATTACHMENT1]);
浮动纹理设置如下:
_gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA32F, 256, 256, 0, _gl.RGBA, _gl.FLOAT, null);
然后我绑定帧缓冲区并调用 readPixels 以获取第一个附件的值:
_gl.readPixels(0, 0, 1, 256, _gl.RGBA, _gl.FLOAT, 0);
在没有浮动纹理的情况下,这项工作有效,但对于浮动纹理,帧缓冲区保持不完整。
WebGL 2 规范似乎说这应该有效,但我现在有些怀疑,似乎 _gl.RGBA32F 似乎是问题所在,内部格式为 _gl.RGBA,它会产生不兼容的类型错误。
首先,浮点渲染需要 WebGL2 中的扩展,EXT_color_buffer_float
。
您可以在 table here copied from the spec section 3.8.3.2 中看到浮点纹理在默认情况下无法在 WebGL2 中渲染。
否则在调用 gl.readPixels
gl.readBuffer
设置要读取的缓冲区
示例:
function main() {
const gl = document.createElement("canvas").getContext("webgl2");
if (!gl) {
alert("need WebGL2");
return;
}
const ext = gl.getExtension("EXT_color_buffer_float");
if (!ext) {
alert("need EXT_color_buffer_float");
return;
}
const tex1 = createTexture(gl, [12, 0, 0, 34]);
const tex2 = createTexture(gl, [0, 56, 78, 0]);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex2, 0);
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
readPixelsFromBuffer(gl, gl.COLOR_ATTACHMENT0);
readPixelsFromBuffer(gl, gl.COLOR_ATTACHMENT1);
}
function readPixelsFromBuffer(gl, attachment) {
gl.readBuffer(attachment);
const data = new Float32Array(4);
const x = 0;
const y = 0;
const width = 1;
const height = 1;
const format = gl.RGBA;
const type = gl.FLOAT;
gl.readPixels(x, y, width, height, format, type, data);
log(glEnumToString(gl, attachment), data);
}
function createTexture(gl, color) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
const level = 0;
const internalFormat = gl.RGBA32F;
const width = 1;
const height = 1;
const border = 0;
const format = gl.RGBA;
const type = gl.FLOAT;
const data = new Float32Array(color);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border,
format, type, data);
// unless we get `OES_texture_float_linear` we can not filter floating point
// textures
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
return tex;
}
function glEnumToString(gl, value) {
for (let key in gl) {
if (gl[key] === value) {
return key;
}
}
return `0x${value.toString(16)}`;
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
main();