Using WebGL readPixels? Turn on preserveDrawingBuffer August 1, 2011
Posted by Andor Salga in JavaScript, Open Source, point cloud, webgl, XB PointStream.trackback
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.
Did you try doing context2d.drawImage( canvas3d, 0, 0 ); ?
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.
This was very helpfull. I did not see any mention of it in the spec for readPixels.
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?
Thanks!
Thanks,
Fixed it. Looks like it’s using an old version. I’ll update that as well.
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.
[...] I found out about this: {preserveDrawingBuffer: true} From This Blog [...]
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.
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.
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?
Thanks.
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.
[...] – gl.readPixels() does not work on Google Chrome without setting preserveDrawingBuffer to true when ge… [...]