11
votes

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.

3
Did you actually get an answer to this? The answer you've marked doesn't look like it actually answers the question. - Samuel Harmer
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
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

3 Answers

9
votes

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);
5
votes

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

1
votes

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)