5

I made a framebuffer object using the webgl_draw_buffers extension in order to provide three color buffers:

  colorBuffer0 = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer0);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, IMAGE_SOURCE_SIZE, IMAGE_SOURCE_SIZE);

  colorBuffer1 = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer1);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, IMAGE_SOURCE_SIZE, IMAGE_SOURCE_SIZE);

  colorBuffer2 = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer2);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, IMAGE_SOURCE_SIZE, IMAGE_SOURCE_SIZE);

  var framebuffer = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);

  WEBGL_draw_buffers.drawBuffersWEBGL([WEBGL_draw_buffers.COLOR_ATTACHMENT0_WEBGL,
                                       WEBGL_draw_buffers.COLOR_ATTACHMENT1_WEBGL,
                                       WEBGL_draw_buffers.COLOR_ATTACHMENT2_WEBGL]);

  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, WEBGL_draw_buffers.COLOR_ATTACHMENT0_WEBGL, gl.RENDERBUFFER, colorBuffer0);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, WEBGL_draw_buffers.COLOR_ATTACHMENT1_WEBGL, gl.RENDERBUFFER, colorBuffer1);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, WEBGL_draw_buffers.COLOR_ATTACHMENT2_WEBGL, gl.RENDERBUFFER, colorBuffer2);

And I fill them in the fragment shader:

  gl_FragData[0] = vec4(ch1.x, ch1.y, 0.0, 1.0);
  gl_FragData[1] = vec4(ch2.x, ch2.y, 0.0, 1.0);
  gl_FragData[2] = vec4(ch3.x, ch3.y, 0.0, 1.0);

Now, when I use readPixels I always get the colorBuffer0:

  pixels  = new Uint8Array(IMAGE_SOURCE_SIZE*IMAGE_SOURCE_SIZE*4);
  gl.readPixels(0,0, IMAGE_SOURCE_SIZE, IMAGE_SOURCE_SIZE, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

I am not able to retrieve the other two color buffers using readPixels. Could I bind each buffer before using readPixels? How could I read the other two color buffers?

JRM
  • 51
  • 2
  • Do you really want `gl.RGBA4`? I ask because it's uncommon. It seems like you'd want texture attachments using `gl.RGBA, gl.UNSIGNED_BYTE` otherwise you might get low-res buffers. On desktop you'll likely actually get 8bits per channel buffers because the spec says it's okay for an implementation of give you higher res than you ask for but on mobile you might actually 4bits per channel buffers. – gman Dec 08 '15 at 16:30

2 Answers2

5

Create more framebuffers. Assign each renderbuffer to a different framebuffer. Bind those framebuffers when you want to read a specific renderbuffer.

A framebuffer is just an array of attachments. Framebuffers are cheap. The attachments, renderbuffers and textures, are the expensive parts. You can put the same renderbuffers and textures in as many framebuffers as you want. For example it's common to share a depth renderbuffer in multiple framebuffers.

gman
  • 100,619
  • 31
  • 269
  • 393
  • 1
    To clarify, having many framebuffers is cheap, but validating them after attachment changes isn't free, and shouldn't be done every frame. Keep them around and reuse them. – Jeff Gilbert Apr 21 '17 at 21:33
0

Thanks, it works. I added two more framebuffers next to the code above:

framebuffer1 = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer1);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, WEBGL_draw_buffers.COLOR_ATTACHMENT0_WEBGL, gl.RENDERBUFFER, colorBuffer1);

framebuffer2 = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer2);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, WEBGL_draw_buffers.COLOR_ATTACHMENT0_WEBGL, gl.RENDERBUFFER, colorBuffer2);

Now, I can read those buffers using readPixels.

JRM
  • 51
  • 2
  • 2
    JRM, can you add a readPixels example, so we can see the full round trip of drawArrays, switching frame buffers, and reading pixels? – Robert Plummer Jun 05 '17 at 01:19