【问题标题】:glReadPixels() really slow, better solution to get OpenGL coordinates from mouse position?glReadPixels() 真的很慢,从鼠标位置获取 OpenGL 坐标的更好解决方案?
【发布时间】:2010-02-05 23:53:08
【问题描述】:

这是我用来获取鼠标在 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% 使用率那样使程序滞后......唯一的问题是当我在我的程序打开时使用其他程序时,然后使用它们就会滞后.

【问题讨论】:

    标签: c++ opengl glreadpixels


    【解决方案1】:

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

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

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

    【讨论】:

    • 我试过 glPushName() 方法,它甚至更慢。实际上我认为它不使用 CPU,但我的 GPU,我得到了 10fps 而不是 500fps...
    • 请注意,我不会像 3 个可能的对象那样选择,我有无限数量的可能对象...
    • 添加了另一个关于在 GL 中挑选以及如何处理的链接。希望你在那里找到有用的东西。
    • 为什么您需要在每帧中多次执行此操作?
    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 是的,我在有和没有 glReadPixels() 函数的情况下进行了测试,该函数是导致运行缓慢的原因。我不确定 CPU 使用率,可能只有我的 CPU 型号有这个问题。当我完全删除 glReadPixels() 调用时,我会更有效地工作 4 个角落,我不知道它是如何工作的,但它可以工作,哈哈。是的,我也在想我可以自己计算视野区域矩形,但我不知道从哪里开始,这似乎工作得很好。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      相关资源
      最近更新 更多