複数のラインセグメントのマージ
-
20-09-2019 - |
質問
私のプログラムでは、Pyopengl(Pythonです)をPSYCOで使用しています。
レンダリングの各フレームでレンダリングする必要がある約21,000本のラインセグメントがあります(ユーザーがズームインしていない限り、ラインセグメントがculされ、カードに送られていません)。これは現在、各フレームを完了するために約1.5秒かかります。それだけでは十分ではないので、明確なラインセグメントの数を減らす方法を検討しています。
複数のラインセグメントを1つの大きなラインに統合できる場合があると思いますが、正直なところ、これからどこから始めればよいかさえわかりません。各ラインの開始点とエンドポイントが保存されているので、物事を助けるかもしれません。スタートアップで必要な限り時間をとることができることに注意してください。また、メモリの使用はそれほど懸念事項ではありません。
どんなアイデアも大歓迎です。
解決
ほぼ確実に、パフォーマンスを殺しているすべての即時モード関数呼び出しのオーバーヘッドです。私は次のことをします。
使用しないでください GL_LINE_STRIPS
, 、の単一のリストを使用します GL_LINES
代わりに、一度にレンダリングできるように。
使用する glDrawArrays
即時モードのレンダリングの代わりに:
float* coordinates = {....}; //x and y coordinate pairs for all line segments
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(float), coordinates);
glDrawArrays(GL_LINES, 0, 2 * linecount);
glDisableClientState(GL_VERTEX_ARRAY);
(パフォーマンスをさらに向上させるために、頂点バッファーオブジェクトと呼ばれるものに頂点バッファーを保存できますが、これは最初は問題ありません)
最後に、1行ごとに選別している場合、スキップしてすべての行をGPUに送信する方が速いでしょう。
他のヒント
20Kセグメントはそれほど多くありません。また、フレームごとに10〜100行をマージできる場合、幸運になるので、この最適化によるスピードアップは無視できます。モデルを何度も作成するため、レンダリングプロセスはおそらく遅いです。使用する glNewList()
カードのGLレンダリングリストにすべてのレンダリングコマンドを保存してから、発行するだけです glCallList()
単一のコマンドでレンダリングします。
2つの線セグメントを1つにマージし、セグメントのすべてのペアをテストし、エラーが特定のしきい値を下回っている場合にマージするためのエラーメトリックを定義できます。
1つの例は、このアルゴリズムです。
- 2つのラインセグメントAとBで互いに遠く離れた2つのポイントから新しいラインセグメントxを構築します。
- AとBのすべてのポイントのXまでの最小距離を見つけます
- エラーをそれらの最小距離の最大値として割り当てます。
- エラーがしきい値を下回っている場合は、AとBをxに置き換えます。
これは最良のアルゴリズムではありませんが、実装するのは簡単です。
編集1
これを実装する前に、ディスプレイリストまたは頂点バッファオブジェクトレンダリングを必ず試してみてください。