0

我正在尝试使用 QGLWidget 实现类似 CoverFlow 的效果,问题是纹理加载过程。

我有一个用于从磁盘加载图像的工作线程(QThread),主线程检查新加载的图像,如果找到,则使用 bindTexture 将它们加载到 QGLContext 中。在绑定纹理时,主线程被阻塞,所以我有一个 fps 下降。

这样做的正确方法是什么?

4

2 回答 2

2

我发现 Qt4 中 bindTexture 的默认行为非常慢:

bindTexture(image,target,format,LinearFilteringBindOption | InvertedYBindOption | MipmapBindOption)

在绑定选项中仅使用 LinearFilteringBindOption 可以大大加快速度,这是我当前的调用:

bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption);

更多信息: 3800x2850 bmp 文件的加载时间从 2 秒减少到 34 毫秒

当然,如果你需要 mipmapping,这不是解决方案。在这种情况下,我认为要走的路是 Pixel Buffer Objects。

于 2012-09-27T15:10:32.287 回答
0

在主线程中绑定(单一QGLWidget解决方案):

  1. 决定最大纹理大小。例如,您可以根据最大可能的小部件大小来决定它。假设您知道小部件最多(大约)800x600 像素,并且可见的最大封面具有上下 30 像素的边距和 1:2 纵横比 -> 600-2*30 = 540 -> 封面的最大尺寸是270x540,例如存储在m_maxCoverSize.

  2. 在加载器线程中将传入的图像缩放到该大小。绑定更大的贴图是没有意义的,越大的贴图上传到显卡的时间就越长。用于QImage::scaled(m_maxCoverSize, Qt::KeepAspectRatio)缩放加载的图像并将其传递给主线程。

  3. 限制纹理的数量或花费在每帧绑定它们的更好时间。即记住你开始绑定纹理的时间(例如QTime bindStartTime;)和绑定每个纹理之后:

    if (bindStartTime.elapsed() > BIND_TIME_LIMIT) 中断;

BIND_TIME_LIMIT将取决于您要保持的帧速率。但是当然,如​​果绑定每个纹理需要的时间比BIND_TIME_LIMIT你没有解决任何问题要长得多。

尽管在较慢的机器/显卡上加载图像时,您仍可能会遇到帧率下降。其余的代码应该准备好接受它(例如使用实际时间来驱动动画)。


另一种解决方案在单独的线程中绑定(使用第二个 invisible QGLWidget,请参阅文档):

2.在线程中上传纹理。

在线程中进行纹理上传对于处理需要显示的大量图像的应用程序可能非常有用,例如照片库应用程序。这在 Qt 中通过现有的 bindTexture() API 得到支持。一个简单的方法是创建两个共享的 QGLWidgets。一个在主 GUI 线程中成为当前的,而另一个在纹理上传线程中成为当前的。上传线程中的小部件从不显示,它仅用于与主线程共享纹理。对于通过 bindTexture() 绑定的每个纹理,通知主线程以便它可以开始使用该纹理。

于 2012-09-27T11:07:09.797 回答