2
votes

I'm trying to implement a ray picking algorithm, for painting and selecting blocks (thus I need a fair amount of accuracy). Initially I went with a ray casting implementation, but I didn't feel it was accurate enough (although the fault may have been with my intersection testing). Regardless, I decided to try picking by using the depth buffer, and transforming the mouse coordinates to world coordinates. Implementation below:

glm::vec3 Renderer::getMouseLocation(glm::vec2 coordinates) {
    float depth = deferredFBO->getDepth(coordinates);

    // Calculate the width and height of the deferredFBO
    float viewPortWidth = deferredArea.z - deferredArea.x;
    float viewPortHeight = deferredArea.w - deferredArea.y;

    // Calculate homogenous coordinates for mouse x and y
    float windowX = (2.0f * coordinates.x) / viewPortWidth - 1.0f;
    float windowY = 1.0f - (2.0f * coordinates.y) / viewPortHeight;

    // cameraToClip = projection matrix
    glm::vec4 cameraCoordinates = glm::inverse(cameraToClipMatrix) 
                                * glm::vec4(windowX, windowY, depth, 1.0f);

    // Normalize
    cameraCoordinates /= cameraCoordinates.w;

    glm::vec4 worldCoordinates = glm::inverse(worldToCameraMatrix) 
                               * cameraCoordinates;

    return glm::vec3(worldCoordinates);
}

The problem is that the values are easily ±3 units (blocks are 1 unit wide), only getting accurate enough when very close to the near clipping plane.

Does the inaccuracy stem from using single-precision floats, or maybe some step in my calculations? Would it help if I used double-precision values, and does OpenGL even support that for depth buffers?

And lastly, if this method doesn't work, am I best off using colour IDs to accurately identify which polygon was picked?

1
It should be more accurate when close to the near, not the far. Yes, you should use colors to identify which polygon is picked. Unless you want to ray pick.Jean-Simon Brochu
Oops, fixed that, you're right, it's more accurate close to the near plane. Bringing the far clipping plane closer did help, though. If you ignore the fact that over half the model gets clipped...Fault
Are you sure deferredFBO->getDepth(...) is returning the clip z co-ordinate (in [-1,1]) and not a depth value like you'd get from glReadPixels (in [0,1])?Mike Dinsdale
I'm rendering the depth values to a texture, and grabbing the pixel with <code>glGetTexImage</code>. Pretty inefficient, considering I need to grab the entire texture, and can't just read the one pixel, but I assume it's the clip z coordinate?Fault
I would have thought you'd get a number in [0,1] from glGetTexImage, but then again you would probably have noticed this - the effect would be larger than what you seem to be describing (and would probably be worst close to the near plane). So perhaps it does give a clip z value.Mike Dinsdale

1 Answers

1
votes

Colors are the way to go, the depth buffers accuracy depend on the plane distances, the resolution of the FBO texture, also on the normal or slope of the surface.The same precision problem happens during the standard shadowing.(Using colors is a bit easier because of with the depth intersection test one object have more "color", depth values. It's more accurate if one object has one color.)

Also, maybe its just me, but I like to avoid rather complex matrix calculations if they're not necessary. It's enough for the poor CPU to do the other stuffs.

For double precision values, that could drop performance badly. I've encountered this kind of performance drop, it was about 3x slower for me to use doubles rather than floats:

my post: GLSL performance - function return value/type and an article about this: https://superuser.com/questions/386456/why-does-a-geforce-card-perform-4x-slower-in-double-precision-than-a-tesla-card

so yep, you can, use 64 bit floats (double): http://www.opengl.org/registry/specs...hader_fp64.txt, and http://www.opengl.org/registry/specs...trib_64bit.txt, but you should not.

All in all use colored polys, I like colors khmm...

EDIT: more about double precision depth : http://www.opengl.org/discussion_boards/showthread.php/173450-Double-Precision, its a pretty good discussion