web-dev-qa-db-ja.com

Android OpenGL ES glDrawArraysまたはglDrawElements?

最良の方法は何ですか:glDrawArraysを使用する場合、またはglDrawElementsを使用する場合?違いはありますか?

21
lacas

どちらの場合も、頂点データを含むいくつかのバッファをOpenGLに渡します。

glDrawArraysは基本的に、「以前に提供したデータを使用して、この連続した頂点の範囲を描画する」ことです。良い:

  • インデックスバッファを構築する必要はありません

悪い:

  • データをGL_TRIANGLESに整理すると、隣接する三角形の頂点データが重複します。これは明らかに無駄です。
  • GL_TRIANGLE_STRIPとGL_TRIANGLE_FANを使用してデータの重複を回避しようとする場合、それはそれほど効果的ではなく、各ストリップとファンに対してレンダリング呼び出しを行う必要があります。 OpenGL呼び出しは費用がかかるため、可能な限り避ける必要があります

GlDrawElementsを使用すると、描画する頂点のインデックスを含むバッファを渡します。

良い

  • 重複する頂点データはありません-異なる三角形の同じデータにインデックスを付けるだけです
  • GL_TRIANGLESを使用し、頂点キャッシュに依存して、同じデータを2回処理することを回避できます。ジオメトリデータを再編成したり、複数の呼び出しにレンダリングを分割したりする必要はありません。

悪い

  • インデックスバッファのメモリオーバーヘッド

GlDrawElementsを使用することをお勧めします

32
ryanm

パフォーマンスへの影響はおそらくiPhoneでも同様です。 iOS用OpenGL ESプログラミングガイド 三角ストリップを使用し、縮退した三角形を介して複数のストリップを結合することをお勧めします。

リンクには、コンセプトの素敵なイラストがあります。このようにして、いくつかの頂点を再利用しても、すべての描画を1つのステップで実行できます。

最高のパフォーマンスを得るには、重複する頂点ができるだけ少ないglDrawArraysを使用して、モデルを単一のインデックスなし三角ストリップとして送信する必要があります。モデルで多くの頂点を複製する必要がある場合(多くの頂点が三角ストリップに順番に表示されない三角形によって共有されているため、またはアプリケーションが多くの小さな三角形ストリップをマージしたため)、個別のインデックスバッファーを使用してglDrawElementsを呼び出すとパフォーマンスが向上する場合があります。代わりに。トレードオフがあります。インデックスのない三角ストリップは頂点全体を定期的に複製する必要がありますが、インデックスの付いた三角リストはインデックス用に追加のメモリを必要とし、頂点を検索するためのオーバーヘッドを追加します。最良の結果を得るには、インデックス付きとインデックスなしの両方の三角ストリップを使用してモデルをテストし、最もパフォーマンスの高いものを使用します。

可能な場合は、共通の頂点を共有する三角形が三角ストリップ内で互いに適度に近くに描画されるように、頂点データとインデックスデータを並べ替えます。グラフィックハードウェアは最近の頂点計算をキャッシュすることが多いため、参照の局所性により、ハードウェアが頂点を複数回計算することを回避できる場合があります。

欠点は、十分な長さのストリップを取得するために、メッシュを並べ替える前処理ステップがおそらく必要になることです。このためのNiceアルゴリズムをまだ思い付くことができなかったため、GL_TRIANGLESと比較してパフォーマンスやスペースの数値を示すことはできません。もちろん、これは描画したいメッシュにも大きく依存します。

6
Jörn Horstmann

受け入れられた答えは少し時代遅れです。 Jorn Horstmannの回答のドキュメントリンクをたどると、 iOS用OpenGL ESプログラミングガイド 、Appleは「degenerate-triangles」の使用方法を説明します"DrawElementsを使ってトリックし、それによって両方の長所を獲得します。

DrawArraysを使用することによるいくつかのインデックスのわずかな節約は、すべてのデータを1つのGL呼び出し、DrawElementsに結合することによって得られる節約の価値はありません。(DrawArraysを使用してすべてを組み合わせることができますが、その後「無駄な要素」は、インデックスよりもはるかに大きい頂点を無駄にし、レンダリング時間も長くなります。)

これは、ほとんどのモデルを最小数のストリップとしてレンダリングできるかどうか、またはモデルが複雑すぎるかどうかについて、すべてのモデルを慎重に検討する必要がないことも意味します。すべてを処理する1つの統一されたソリューション。 (ただし、送信されるデータを最小限に抑え、最近キャッシュされた頂点計算を再利用するGPUの可能性を最大化するために、可能な場合はストリップに整理するようにしてください。)

BEST:GL_TRIANGLE_STRIPを使用した単一のDrawElements呼び出しで、allデータ(各フレームで変化)が含まれています)。

1
ToolmakerSteve

実際には、三角ストリップを縮退して連続ストリップを作成できるため、glDrawArrayの使用中に三角ストリップを分割する必要はありません。

私はglDrawElementsとGL_TRIANGLESを使用してきましたが、代わりにGL_TRIANGLE_STRIPでglDrawArrayを使用することを考えています。このように、inidicesベクトルを作成する必要はありません。

上記の投稿の1つで言及された頂点キャッシュのことについてもっと知っている人はいますか? glDrawElements/GL_TRIANGLEとglDrawArray/GL_TRIANGLE_STRIPの間のパフォーマンスについて考えます。

1
Peter Larsson