glReadPixels()真的很慢,更好的解决方案从鼠标位置获取OpenGL坐标?

时间:2010-02-05 23:53:09

标签: c++ opengl glreadpixels

这是我用来在3d场景中获取鼠标位置的代码:

void GetOGLPos(int x, int y, GLdouble &pX, GLdouble &pY, GLdouble &pZ){
 GLint viewport[4];
 GLdouble modelview[16];
 GLdouble projection[16];
 GLfloat winX, winY, winZ;

 glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
 glGetDoublev(GL_PROJECTION_MATRIX, projection);
 glGetIntegerv(GL_VIEWPORT, viewport);

 winX = (float)x;
 winY = (float)viewport[3]-(float)y;
 glReadPixels(x, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

 gluUnProject(winX, winY, winZ, modelview, projection, viewport, &pX, &pY, &pZ);
}

但是我注意到了一件坏事...每帧1-2次调用该功能会使CPU占用率达到100%,3次或更多次调用200%CPU占用率(我有4个核心,1-2个呼叫= 25%,3或者更多的电话= 50%,我认为它不能超过50%......)

还有其他方法可以有效地做到这一点吗?我每帧都使用4次调用该函数,所以我知道应该为场景渲染哪些区域(我从每个屏幕角落拍摄)。

另外我用它来知道我用鼠标指向哪个地方,所以我需要实时,但我想减少使用CPU,因为即使只有1次调用也会使单核系统的使用率达到100%。< / p>

编辑

我尝试过glPushName()方法,但它的速度更慢,在我的GPU中比在CPU中更慢。当我在程序中不使用单个glReadPixels()调用时,我的CPU使用率仅为0-1%。奇怪的是,我的CPU使用率很高,但它不会使程序滞后,就像你预期的那样100%使用...当我的程序打开时,只有当我使用其他程序时出现问题,那么使用它们的时间很长

3 个答案:

答案 0 :(得分:1)

您似乎尝试在OpenGL中进行选择。

查看本教程,它应该比您的方法具有更少的性能损失: http://gpwiki.org/index.php/OpenGL:Tutorials:Picking

这个地方提到了在OpenGL中采摘的其他方式: http://www.opengl.org/resources/faq/technical/selection.htm

答案 1 :(得分:0)

您是否完全确定导致问题的单一功能?您是否尝试过分析工具来确认?并不是说我想怀疑你,我只是希望你在经历调试或更改代码的大部分问题之前确定。

我很惊讶OpenGL调用(读取一个像素,不少于)占用 CPU 时间。如果有的话,我认为它会显示0 CPU使用率但帧速率较慢。但是,我对OpenGL的了解不足以怀疑它有什么问题。我觉得这似乎不直观。

A forum post关于glReadPixels的性能表明某些显卡(特别是旧显卡)在将数据从GPU移动到CPU时效率非常低。您是否可以在另一台计算机上运行您的代码,看看它是否只是您的视频卡?这将是最好的开始方式,特别是如果你有一张ATI卡并在朋友的NVIDIA卡上运行,反之亦然。

帖子还提到数据类型可能会有所不同。我不认为这有什么大不同,但谁知道。

您可能会尝试另外一件事:如果您连续四次调用该函数,则会有三个额外的不必要的调用来读取当前矩阵。考虑通过参数取代矩阵。但是,我怀疑glGetDoublev / glGetIntegerv真的花了很多时间。

根据您正在做的事情,您可能想要阅读有关截头剔除的信息。这听起来就像你想要通过获得屏幕的四个角落。您自己实现数学而不是使用glUnProject可能更便宜。

答案 2 :(得分:0)

即使您尝试使用PBO,glReadPixels也会使用CPU转换从帧缓冲区读取的数据。例如,如果您尝试通过PBO读取颜色数据,则仅当您将参数设置为GL_BGRA时,函数才会进行转换并立即返回。否则,如果将参数设置为GL_RGBA,则CPU使用率将被占用。 我也试图从framebuffer读取深度数据,但glReadPixels肯定会转换数据无论param设置