jump to navigation

Using WebGL readPixels? Turn on preserveDrawingBuffer August 1, 2011

Posted by Andor Salga in Open Source, JavaScript, webgl, XB PointStream, point cloud.

Since I’ve already written a few blogs about WebGL’s readPixels and because developers seem to find my page mostly by this keyword, I decided to help clarify a recent issue I found.

In some of my WebGL scripts I have a feature which allows users to convert 3D images to 2D (see here). The script does this simply by making a call to readPixels.

This used to work until browsers (namely WebKit and Chrome) began implementing the preserveDrawingBuffer option. This is an option set when the WebGL context is acquired and as its name suggests it preserves drawing buffers between frames.

What this means is if preserveDrawingBuffer is false/off (which it is by default) it will not save the depth and color buffers after each draw call. Trying to call readPixels in this state will result in an array of zero’ed out data.

If you’re planning on calling readPixels, you’ll need to turn on this option when you get your WebGL context.

var context = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});

The WebGL spec states that this may cause a performance hit on some machines so only enable it if you really need to.


1. Mr.doob - August 1, 2011

Did you try doing context2d.drawImage( canvas3d, 0, 0 ); ?

cbyars - September 4, 2013

ctx.drawImage(renderer.domElement,0,0) does not work in Safari OSX 6.0.5. Anyone know why?

2. Benoit Jacob - August 1, 2011

With preserveDrawingBuffer=false, the backbuffer is cleared after being presented to the HTML compositor i.e. after your JS callback function has returned. So, as long as you call readPixels from the same callback function as where you do the drawing, it won’t have been cleared.

3. cody - August 3, 2011

This was very helpfull. I did not see any mention of it in the spec for readPixels.

4. nemo - August 5, 2011

Hey, just a quick note.

Error: ps.getVersion is not a function
Source File: http://scotland.proximity.on.ca/asalga/demos/eggenburg/eggenburg.js
Line: 72

Mind terribly fixing this demo?

5. Andor Salga - August 5, 2011

Fixed it. Looks like it’s using an old version. I’ll update that as well.

6. gman - August 16, 2011

Another comment. If you want to save screenshots it’s much easier IMO to do canvas.toDataURL rather than readPixels.

In some (most?) HTML5 browsers you can then assign the result to an img.src and the user can right click to save.

You can also XHR that string to a server. It’s just a few lines in Python or Node.js to then save that as a .pnga

I’m sure with the FileAPI it would also be trivial to pop up the open to save the file locally.

7. More Mucking Around… « OSD600 - October 26, 2011

[…]     I found out about this: {preserveDrawingBuffer: true} From This Blog […]

8. rpr - January 26, 2012

Hi, I would like to see your script to convert 3D images to 2D by means readPixels but the link is broken.
Would you mind telling me how to see that?

Thanks so much.

9. Andor Salga - January 26, 2012

Sorry rpr, our server has been down for a couple of days. I’ll copy the files over to another one soon and let you know.

rpr - January 27, 2012

Thanks, by the way I tested readPixels function on webgl but it only works correctly on Firefox.
It doesn’t work on Chrome even though I set the option preserveDrawingBuffer to true (I get the buffer data but the values are all zero).
Have you tested it recently on Chrome?


rpr - January 31, 2012

Filnally, I solved it. The problem was a library called scene.js that doesn’t allow to enable the preserveDrawingBuffer option.

So, if someone has the same problem there is to modify the library searching getContext methods and adding {preserveDrawingBuffer: true} option.

10. Proper Colour Picking in CubicVR « Jesse Silver's Blog - May 12, 2012

[…] – gl.readPixels() does not work on Google Chrome without setting preserveDrawingBuffer to true when ge… […]

11. sytzez - February 9, 2015

Thanks so much!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.

%d bloggers like this: