QGLWidgetを使用してCoverFlowのようなエフェクトを実装しようとしていますが、問題はテクスチャの読み込みプロセスです。
ディスクから画像をロードするためのワーカー(QThread)があり、メインスレッドは新しくロードされた画像をチェックし、見つかった場合は、bindTextureを使用してQGLContextにロードします。テクスチャがバインドされている間、メインスレッドがブロックされているため、fpsが低下します。
これを行う正しい方法は何ですか?
Qt4 の bindTexture のデフォルトの動作が非常に遅いことがわかりました。
bindTexture(image,target,format,LinearFilteringBindOption | InvertedYBindOption | MipmapBindOption)
バインディングオプションで LinearFilteringBindOption のみを使用すると、処理が大幅に高速化されます。これが私の現在の呼び出しです。
bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption);
詳細はこちら: 3800x2850 の bmp ファイルの読み込み時間が 2 秒から 34 ミリ秒に短縮されました
もちろん、ミップマッピングが必要な場合、これは解決策ではありません。この場合は、Pixel Buffer Objects を使用するとよいと思います。
メインスレッドでのバインド(単一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
場合は、何も解決していません。
低速のマシンやグラフィック カードを使用している場合でも、画像の読み込み中にフレームレートが低下することがあります。コードの残りの部分は、それに対応できるように準備する必要があります (たとえば、実際の時間を使用してアニメーションを駆動するなど)。
別の解決策は、別のスレッドでバインドすることです(2 番目の invisible を使用します。ドキュメントQGLWidget
を参照してください)。
2.
スレッドでのテクスチャのアップロード。スレッドでテクスチャのアップロードを行うことは、たとえばフォト ギャラリー アプリケーションのように、表示する必要がある大量の画像を処理するアプリケーションにとって非常に便利です。これは、既存の bindTexture() API を通じて Qt でサポートされています。これを行う簡単な方法は、2 つの共有 QGLWidget を作成することです。1 つはメイン GUI スレッドで最新になり、もう 1 つはテクスチャ アップロード スレッドで最新になります。アップロード スレッドのウィジェットは表示されません。メイン スレッドとテクスチャを共有するためにのみ使用されます。bindTexture() によってバインドされたテクスチャごとに、メイン スレッドに通知して、テクスチャの使用を開始できるようにします。