使用深度缓冲器进行光线拾取:非常不准确?

时间:2013-12-03 19:34:43

标签: c++ opengl floating-accuracy ray-picking

我正在尝试实施光线拾取算法,用于绘制和选择块(因此我需要相当高的精度)。最初我使用光线投射实现,但我觉得它不够准确(虽然故障可能是我的交叉测试)。无论如何,我决定尝试使用深度缓冲区进行拾取,并将鼠标坐标转换为世界坐标。实施如下:

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);
}

问题是这些值很容易±3个单位(块是1个单位宽),只有在非常靠近近剪裁平面时才能得到足够的精确度。

这种不准确性是源于使用单精度浮点数,还是计算中的一些步骤?如果我使用双精度值会有帮助吗,OpenGL是否支持深度缓冲区呢?

最后,如果这种方法不起作用,我最好使用颜色ID来准确识别被选中的多边形吗?

1 个答案:

答案 0 :(得分:1)

颜色是要走的路,深度缓冲精度取决于平面距离,FBO纹理的分辨率,也取决于表面的法线或斜率。标准阴影期间会出现同样的精度问题。 (使用颜色会更容易,因为通过深度交叉测试,一个对象具有更多“颜色”,深度值。如果一个对象有一种颜色,则更准确。)

此外,也许只是我,但我喜欢避免相当复杂的矩阵计算,如果他们没有必要。对于可怜的CPU来说,做其他事情已经足够了。

对于双精度值,可能会严重降低性能。我遇到了这种性能下降,使用双打而不是花车慢了大约3倍

我的帖子: GLSL performance - function return value/type和 关于这个的文章: https://superuser.com/questions/386456/why-does-a-geforce-card-perform-4x-slower-in-double-precision-than-a-tesla-card

所以是的,你可以使用64位浮点数(双): http://www.opengl.org/registry/specs...hader_fp64.txt, 和http://www.opengl.org/registry/specs...trib_64bit.txt, 但你不应该。

总而言之,使用彩色多边形,我喜欢颜色khmm ......

编辑关于双精度深度的更多信息:http://www.opengl.org/discussion_boards/showthread.php/173450-Double-Precision,这是一次非常好的讨论