I'm having trouble using webgl2 to render to an integer renderbuffer. Using the example code at the bottom, I get all zeros in the pixels array and the following error on Firefox:
WebGL warning: readPixels: Format and type RGBA_INTEGER/<enum 0x1400> incompatible with this RGBA8I attachment. This framebuffer requires either RGBA_INTEGER/INT or getParameter(IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE) RGBA_INTEGER/INT.
When I substitute:
gl.readPixels(
0, 0, 256, 256,
gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT),
gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE),
pixels
);
for
gl.readPixels(0, 0, 256, 256, gl.RGBA_INTEGER, gl.BYTE, pixels);
The error becomes:
WebGL warning: readPixels: `pixels` type does not match `type`.
(On Firefox, gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE) returns gl.INT instead of gl.BYTE.)
I've tried changing the TypedArray for pixels between Uint8Array and Int8Array, but none options works. I should note that the provided example does work on Chrome. Is there a way to render to int buffer on Firefox or is it entirely bugged?
const gl = document.getElementById('target').getContext('webgl2', { preserveDrawingBuffer: true });
const prog = gl.createProgram()
const vert = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vert, `#version 300 es
in vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0., 1.);
}`);
gl.compileShader(vert);
gl.attachShader(prog, vert);
const frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frag, `#version 300 es
precision highp isampler2D;
out ivec4 color;
void main() {
color = ivec4(255, 0, 0, 255);
}`);
gl.compileShader(frag);
gl.attachShader(prog, frag);
gl.linkProgram(prog);
const vao = gl.createVertexArray();
gl.bindVertexArray(vao)
const buff = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buff);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([-1,-1, -1,1, 1,-1, 1,1, -1,1, 1,-1]),
gl.STATIC_DRAW
);
const pos = gl.getAttribLocation(prog, 'a_position');
gl.enableVertexAttribArray(pos);
gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0)
const rbo = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8I, 256, 256);
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.RENDERBUFFER, rbo
);
gl.viewport(0, 0, 256, 256);
gl.clearColor(0,0,0,0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.disable(gl.DEPTH_TEST);
gl.useProgram(prog);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.readBuffer(gl.COLOR_ATTACHMENT0);
const pixels = new Int8Array(256 ** 2 * 4);
gl.readPixels(0, 0, 256, 256, gl.RGBA_INTEGER, gl.BYTE, pixels);
console.log(pixels);
Figured it out. For whatever reason, Firefox wants gl.INT and Int32Array to be passed to readPixels. Note that this is not to spec and fails on Chrome.