5

这是我用来在 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% 使用单核系统。

编辑

我已经尝试过 glPushName() 方法,但它甚至更慢,在我的 GPU 中比在 CPU 中更慢。此外,当我在程序中不使用单个 glReadPixels() 调用时,我的 CPU 使用率只有 0-1%。奇怪的是我得到了很高的 CPU 使用率,但它并没有像你期望的 100% 使用率那样使程序滞后......唯一的问题是当我在我的程序打开时使用其他程序时,然后使用它们就会滞后.

4

3 回答 3

1

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

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

这个地方提到了在 OpenGL 中进行挑选的其他方法: http ://www.opengl.org/resources/faq/technical/selection.htm

于 2010-02-05T23:56:46.183 回答
0

您绝对确定是导致问题的那个单一功能吗?您是否尝试过分析工具来确认?并不是我想怀疑你,我只是想让你在经历调试或更改大量代码的麻烦之前确定。

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

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

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

您还可以尝试一件事:如果您连续四次调用该函数,您将有三组额外的不必要的调用来读取当前矩阵。考虑改为通过参数获取矩阵。但是,我怀疑 glGetDoublev/glGetIntegerv 真的需要很多时间。

根据您正在做的事情,您可能还想阅读有关截锥体剔除的信息。这听起来像是您通过获取屏幕的四个角来尝试做的事情。您自己实现数学而不是使用 glUnProject 可能会更便宜。

于 2010-03-05T19:33:30.443 回答
0

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

于 2013-01-18T09:49:34.900 回答