我正在尝试实施光线拾取算法,用于绘制和选择块(因此我需要相当高的精度)。最初我使用光线投射实现,但我觉得它不够准确(虽然故障可能是我的交叉测试)。无论如何,我决定尝试使用深度缓冲区进行拾取,并将鼠标坐标转换为世界坐标。实施如下:
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来准确识别被选中的多边形吗?
答案 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,这是一次非常好的讨论