各glDraw *は描画呼び出しです。
1つのglDrawArraysは1つの描画呼び出しです。
1つのglDrawElementsは1つの描画呼び出しです。
(描画呼び出し数に関する限り)使用する頂点またはインデックスの数は関係ありません。1つのglDraw *は1つの描画呼び出しです。
四角形のリストまたは三角形のリストはいずれかを1回呼び出すだけで描画できるため、四角形(使用するGLバージョンで四角形が削除されていないと想定)または三角形を描画する単純なケースは、これらを比較する良い例ではありません。また、インデックス作成の追加のオーバーヘッドがないため、glDrawArraysはより効率的に表示されます。
もう少し複雑なケースを考えてみましょう。ただし、より現実的なシナリオを代表するものです。複数の三角形のストリップとファンで構成されるモデルがあるとします。
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
この例では、glDrawArraysを使用すると、モデルに対して合計6つの描画呼び出しが行われます。ただし、ストリップとファンはどちらもインデックス付きの三角形に簡単に変換できるため、インデックスを追加すると次のようになります。
glDrawElements (GL_TRIANGLES, .....);
これは、モデル全体の1つの描画呼び出しです。
glDrawArraysに対するglDrawElementsの利点は、それを測定する単純な方法である単なるメモリ節約以上のものです。インデックスは通常、頂点よりも小さいので(したがって、多くのインデックスがバランスしていても、インデックスは小さくなるため)、頂点を再利用できるメモリ節約の可能性がありますが、他の利点は次のとおりです。
ドローコール数の削減。各描画呼び出しでは、状態の検証、設定などからオーバーヘッドが発生し、このオーバーヘッドの多くはCPU側で発生します。描画呼び出しの数を減らすことにより、このオーバーヘッドの多くを回避します。
頂点の再利用。これは単なるメモリ節約以上のものです。GPUにはハードウェアの頂点キャッシュがあり、最近変換された頂点を保存できます。同じ頂点が再び入ってきて、それがキャッシュにある場合、再度変換する必要はなく、キャッシュから再利用できます。ハードウェアはインデックスを比較してキャッシュをチェックするため、OpenGL用語では、キャッシュを使用する唯一の方法はglDrawElementsを使用することです。
特定の質問に答えるために:
glDrawElementsはどのように描画呼び出しを保存できますか?使用する例では、そうではありません。それぞれに1つの描画呼び出しがあります。上記で説明したように、この例は2つを比較するには非常に悪い例です。
glDrawElementsを使用するとどのようにスペースを節約できますか?インデックスは頂点よりも小さいからです。16ビットインデックスは2バイト、位置/色/ texcoord頂点は24バイトです。6つの頂点は144バイト、4つの頂点と6つのインデックスは108バイトです。
2つの三角形から正方形を描く場合...?一つずつ。glDraw *呼び出しは1つの描画呼び出しであり、使用される頂点またはインデックスの数はこの測定には関係ありません。しかし、改めて強調しなければなりません。これは、2つを比較する非常に悪い例です。
最後に、少し複雑にすることは重要ですが、三角形の付いたglDrawElementsはデスクトップGPUでは最適なパスですが、モバイルでは非常に異なる場合があります。一部のモバイルGPUはGL_TRIANGLE_STRIPを備えたglDrawArraysを好む場合があり(この場合、縮退した三角形を追加してプリミティブを連結します)、プリミティブの再起動やマルチ描画などのより高度なトピックについても触れていません。