我正在尝试使用QGLWidget实现类似CoverFlow的效果,问题是纹理加载过程。
我有一个工作程序(QThread)用于从磁盘加载图像,主线程检查新加载的图像,如果找到则使用bindTexture将它们加载到QGLContext中。当纹理被绑定时,主线程被阻塞,所以我有一个fps下降。
这样做的正确方法是什么?
答案 0 :(得分:2)
我发现Qt4中bindTexture的默认行为非常慢:
bindTexture(image,target,format,LinearFilteringBindOption | InvertedYBindOption | MipmapBindOption)
在绑定选项中仅使用LinearFilteringBindOption可以加速很多事情,这是我目前的电话:
bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption);
更多信息here:3800x2850 bmp文件的加载时间从2秒减少到34毫秒
当然,如果你需要mipmapping,这不是解决方案。在这种情况下,我认为可行的方法是Pixel Buffer Objects。
答案 1 :(得分:0)
主线程中的绑定(单QGLWidget
解决方案):
决定最大纹理尺寸。例如,您可以根据最大可能的窗口小部件大小来决定它。假设您知道窗口小部件最多(大约)800x600像素,并且可见的最大封面上下30像素边距和1:2宽高比 - > 600-2 * 30 = 540 - >封面的最大尺寸为270x540,例如存储在m_maxCoverSize
。
在传感器线程中将传入图像缩放到该大小。绑定较大的纹理没有意义,它越大,上传到图形卡所需的时间越长。使用QImage::scaled(m_maxCoverSize, Qt::KeepAspectRatio)
缩放加载的图像并将其传递给主线程。
限制每帧纹理的数量或更好的时间。即记住你开始绑定纹理的时间(例如QTime bindStartTime
;)并在绑定每个纹理后执行:
if(bindStartTime.elapsed()> BIND_TIME_LIMIT) 打破;
BIND_TIME_LIMIT
取决于您想要保留的帧率。但是,当然如果绑定每个纹理需要比BIND_TIME_LIMIT
更长的时间,那么你还没有解决任何问题。
在较慢的机器/图形卡上加载图像时,您可能仍会遇到帧率下降。其余代码应该准备好与它一起使用(例如使用实际时间来驱动动画)。
替代解决方案是在单独的线程中绑定(使用第二个不可见的QGLWidget
,请参阅documentation):
2.
纹理在线程中上传。在线程中执行纹理上传对于处理需要显示的大量图像的应用程序非常有用,例如照片库应用程序。 Qt通过现有的bindTexture()API支持此功能。一种简单的方法是创建两个共享QGLWidgets。一个在主GUI线程中变为当前,而另一个在纹理上载线程中变为当前。上传线程中的小部件从不显示,仅用于与主线程共享纹理。对于通过bindTexture()绑定的每个纹理,通知主线程,以便它可以开始使用纹理。