我想在建模为高度图的世界地面上的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光线应该没什么大不了的,它代表了在目标像素渲染的空间中的点。然后我可以实现一个交集算法来找到曲面上最前面的点。
您通常在CPU上实现它!在高度贴图坐标中找到拾取光线,并在高度贴图上进行简单的直线跟踪。这与划线非常相似。在你相交的每个单元格中,对照你用来对其进行三角测量的三角形进行测试。
重要的是要避免从GPU读取,直到它完成。由于您通常会提前几帧安排绘图命令(GL会自动执行此操作),这意味着您也只能在那时获得结果,或者暂停CPU,直到GPU赶上为止。但不要为了这样简单的事情而这么做!