12

Is there a way to get the raw pixel data from a WebGL render buffer or frame buffer that is off screen?

I'm using WebGL to do some image processing, e.g. blurring an image, adjusting color, etc. I'm using frame buffers to render to textures at the full image size, then using that texture to display in the viewport at a smaller size. Can I get the pixel data of a buffer or texture so I can work with it in a normal canvas 2d context? Or am I stuck with changing the viewport to the full image size and grabbing the data with canvas.toDataURL()?

Thanks.

Sean Kent
  • 574
  • 1
  • 5
  • 10
  • Did you actually get an answer to this? The answer you've marked doesn't look like it actually answers the question. – Samuel Harmer Nov 12 '12 at 08:57
  • I suppose the actual answer is no, you can't get pixel data from a buffer. You have to use `readPixels()` That was the closest I got to an answer, so I accepted it. Should I unaccept that answer? – Sean Kent Nov 20 '12 at 20:25
  • I don't think that's necessary. Unless someone provides a more useful answer, brainjam has indirectly answered your question. I was just curious. – Samuel Harmer Nov 20 '12 at 22:02

3 Answers3

11

This is very old question, but I have looked for the same in three.js recently. There is no direct way to render to frame buffer, but actually it is done by render to texture (RTT) process. I check the framework source code and figure out the following code:

renderer.render( rttScene, rttCamera, rttTexture, true );

// ...

var width = rttTexture.width;
var height = rttTexture.height;
var pixels = new Uint8Array(4 * width * height); // be careful - allocate memory only once

// ...

var gl = renderer.context;
var framebuffer = rttTexture.__webglFramebuffer;
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);        
gl.viewport(0, 0, width, height);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
to_masz
  • 214
  • 3
  • 7
5

readPixels() should do what you want. Read more in the WebGL spec at http://www.khronos.org/registry/webgl/specs/latest/

brainjam
  • 18,863
  • 8
  • 57
  • 82
  • Thanks, I'll try that. Unfortunately though, it looks like I still have to resize the canvas to the size I want to read the pixels. This causes a 'flash' when resizing. Maybe using a separate context off-screen, then reading pixels from that might work...? – Sean Kent May 31 '11 at 23:50
  • 2
    Yes, using a separate offscreen context should work .. but I haven't tried this. Also, you can apparently create auxiliary framebuffers that can be used for rendering, but which aren't displayed. See http://learningwebgl.com/blog/?p=1786 for an explanation of how to create such a framebuffer and use its contents as a texture. Hopefully that will get you going. – brainjam Jun 01 '11 at 02:52
  • I am using a framebuffer as texture in a webgl context, however the problem I'm having is getting that data out of the context to use elsewhere in my application. I've got the separate off-screen context sorta working, so I'm going to pursue that route for now. Thanks. – Sean Kent Jun 01 '11 at 15:41
1

Yes, you can read raw pixel data. Set preserveDrawingBuffer as true while getting webgl context and afterwards make use of readPixels by WebGL.

var context = canvasElement.getContext("webgl", {preserveDrawingBuffer: true}
var pixels = new Uint8Array(4 * width * height);
context.readPixels(x, y, width, height, context.RGBA, context.UNSIGNED_BYTE, pixels)