我想在我的OpenGL场景中跟踪被建模为高度图的世界地面上的鼠标坐标。目前没有像硬件镶嵌那样的花哨的东西。请注意,这个问题是不是约对象采摘。如何在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射线应该没什么大不了的,它代表在目标像素处呈现的空间中的点。然后我可以实现一个交集算法来找到曲面上最前面的点。
当这个想法第一次出现在我的脑海里时,它听起来是“错误的方式”。但是,当越来越多地了解GPU性能时,特别是考虑命令队列时,在CPU上执行操作确实听起来像是“正确的方式”。其他人确认这一点真的很有帮助。谢谢。 – leemes
但是,是否有可能有效地读取当前处于GPU中的深度缓冲区,而不是当执行当前正在队列中的命令时将存在的值?如果这还不算太旧,那么使用旧的深度值也是一种解决方案。 – leemes
是的,那是可能的。或者更准确地说,您可以提前安排阅读时间并检查完成时间。阅读同步和像素缓冲区对象 – ltjax