2

我想在世界地表上跟踪我的 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 射线应该没什么大不了的,它表示在目标像素处渲染的空间点。然后我可以实现一个相交算法来找到表面上最前面的点。

4

1 回答 1

3

您通常在 CPU 上实现它!在高度图坐标中找到您的拾取射线,并在高度图上进行简单的线跟踪。这与画线非常相似。在您相交的每个单元格中,针对您用来对其进行三角剖分的三角形进行测试。

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

于 2012-09-17T16:28:21.567 回答