Skip to content

Proper Colour Picking in CubicVR

May 12, 2012

So I needed to be able to accurately pick at things in a 3D scene in CubicVR, but a bounding box ray test (scene.bbRayTest()) wasn’t providing that. If a mesh had an odd shape, or holes, it wouldn’t be very accurate, since everything was picked based on a bounding box. So I looked up online how other people were doing it. The general answer was called colour picking. The general process for this would be:

1. Render each pickable object to a backbuffer with a slightly different colour.

2. Get the colour at the pixel your mouse is at.

3. See if it matches up with anything in the scene that is pickable. If so, you have a match.

It seems simple enough, but there’s a lot of little things that needed to be taken care of before it would actually work.

– It needed to be flat shaded, no lights at all.

– Nothing should affect the color (such as texture, wireframe mode, ambient, specular, etc..). So the material has to be completely different, and wireframe mode on the scene object needs to be set off.

gl.readPixels() does not work on Google Chrome without setting preserveDrawingBuffer to true when getting the WebGL context

– CubicVR stores colors as floats between 0 and 1, gl.readPixels() gives you bytes. You need to take that into account.

– The mouse position y you send to gl.readPixels() has to be flipped, so you use height – mouseY instead.

To test this, I took the CubicVR picking demo that already existed, and tried to use my colour picking code instead of scene.bbRayTest(). Click here to view this test, and here to view the original test. It’s amazing how something simple can have a lot of edge cases you need to take care of before anything will work.

Edit: It seems that in the example, I actually had a couple of issues that I still didn’t catch. Mainly that I was doing the picking code in the main loop, creating the backbuffer every check, and creating a new material for each object every check. Firefox didn’t like this if left alone. So, I cached both the unique material, and the drawing buffer. Then I only called the picking code on movemove, an recreated the buffer during window resize. That should solve the earlier issues I had.

From → Open Source

Leave a Comment

Leave a comment