如何在OpenGL中有效地实现“高点映射”选择?

时间:2012-09-17 16:03:32

标签: opengl gpu projective-geometry ray-picking

我想跟踪世界地面上我的OpenGL场景中的鼠标坐标,该场景被建模为高度图。目前没有硬件镶嵌等奇特的东西。请注意,此问题关于对象选择。

目前我正在做以下事情,由于回读操作,显然会降低性能:

  • 渲染世界(地面)
  • 回读鼠标坐标处的深度值
  • 渲染场景的其余部分
  • 交换缓冲区并渲染下一帧

回读是在两个渲染步骤之间,因为我想要地面的深度值,前面没有任何对象。使用以下命令完成:

GLfloat depth;
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);

我的应用程序将帧速率限制为每秒60帧。在没有回读操作的情况下渲染场景时,我的CPU使用率低于5%,但在进行回读时,它增加到大约75%,尽管我没有做很多渲染场景或更新任何游戏模型或者这样的事情。

临时解决方案是在鼠标下缓存像素的深度值,并且每隔5或10帧更新一次,这会导致CPU使用率回落到10%以下。但显然不能成为问题的最佳解决方案。

如何有效地实现拾取(不是对象拾取,因为我想要表面上的(浮点)坐标)?

我已经想过回读前缓冲区的深度值而不是后缓冲区,但是当谷歌搜索如何这样做时,我只发现人们抱怨glRead *方法是最好的避免。但是,如果没有读取某些东西(使用glRead *),我怎么能读取(选择)?

我很困惑。其他人如何实施拣选?


完全不同的方法是在软件中实施世界表面选择。从相机“深入”重建3D射线应该没什么大不了的,表示在目标像素处渲染的空间中的点。然后我可以实现一个交集算法来找到表面上的最前面的点。

1 个答案:

答案 0 :(得分:3)

您通常在CPU上实现它!在高度图坐标中查找拾取光线,并在高度图上执行简单的线条跟踪。这与画线非常相似。在您交叉的每个单元格中,测试您用于对其进行三角测量的三角形。

重要的是避免从GPU读取直到完成为止。由于您通常会提前几帧绘制绘图命令(GL会自动执行此操作),这意味着您也只会获得结果 - 或者在CPU停止运行之前停止CPU。但是,对于像这样的简单事情,不要这样做!