3

私は OpenGL ES を初めて使用し、Wavefront Obj ファイルをロードして OpenGL で描画する必要がある iPad アプリを作成しています。私の質問は、Obj ファイル グループをレンダリングする最も効率的な方法についてです。

私が持っているものの背景を少し。Obj モデルのすべての解析/読み込みが機能しているため (ファイルの読み込みには GLM を使用しました)、面倒な作業は不要です。ベース プロジェクトでは、XCode で OpenGL ES ゲーム テンプレートを拡張し、シェーダーへのすべての呼び出しを削除しました。シェーダーに GLKit の BaseEffect を使用し、VAO と VBO を使用してすべての頂点データをロードしています。16 個のグループを持つモデルの場合、初期化時に各グループを VAO に分割します。各 VAO には、頂点データと法線 (インターリーブ) 用の VBO と、テクスチャ座標用の 2 つ目の VBO があります。各グループにはマテリアルがあります (場合によってはテクスチャもありますが、質問のためにマテリアルのみを想定しています)。

私のレンダリング ルーチン (以下の疑似コード) では、グループごとに作成したすべての VAO をループし、グループのマテリアルを BaseEffect に適用してから、DrawArrays を使用して描画しています (VBO を設定しているため、DrawElements は使用していません)。データはすでにインデックス順になっていますが、おそらくグラフィックス メモリほど効率的ではありません)。これは機能し、各モデルを異なるマテリアルで描画できますが、グループ数が増えると、レンダリング関数で各グループをループするのにより多くの時間を費やさなければならないため、フレームレートが低下します。モデル数が少ない場合はこれで問題ありませんが、アプリにモデルを追加していくと、フレーム レートが私のベースラインである 30 fps を大幅に下回ります。

for (groups in model)
{
    Bind VAO for this group

    Apply Material or Texture (if one exists) for this group using GLKBaseEffect

    Call PrepareToDraw for GLKBaseEffect

    DrawArrays passing it the vertex count for this group

    glBindVertexArray(0)   
}

明らかな答えは、モデルを単純化してグループを少なくすることですが、レンダリング ルーチンを改善して、同じことを可能にし、Draw 呼び出しを減らすことができるかどうかを知りたいです。詳細な obj ファイルが必要ですが、可能な限り最も効率的なレンダリングも必要です。

これは、ファイル内の各グループに複数のマテリアル/テクスチャを使用する必要がある obj ファイルを描画するための最良の方法ですか、または各グループをループして個別に描画せずにこれを行う方法はありますか? 各 obj モデルに DrawArrays/DrawElements への呼び出しを 1 つだけ持たせたいと思っていますが、これを行う方法がわかりませんし、オブジェクトに複数のマテリアル/テクスチャを適用します。私はこのコードを見て、「もっと良い方法があるはずだ」と考え続けていますが、それが何であるかはわかりません。あからさまに明らかなパズルのピースが欠けている場合、またはこれを最適化するために提供できる提案があれば、私は永遠に感謝します.

4

1 に答える 1

3

あなたはかなり正しい考えを持っていると思います。実際には一度に 1 つのテクスチャ セットまたは 1 つのシェーダーしかアクティブにできないため、その状態を使用するモデルの部分を描画し、状態を切り替えて、次のグループを描画する必要があります。

モデルを追加するとパフォーマンスが低下する場合は、同じ状態のすべてのグループを切り替えずに連続して描画するように、グループを並べ替えることができます。

したがって、モデルのコピーを 100 個描画していて、モデルに 3 つのグループ A、B、および C がある場合は、次のようにする代わりに:

foreach(model)
   set state A;
   glDrawArrays(A);
   set state B;
   glDrawArrays(B);
   set state C;
   glDrawArrays(C);

次のようにする必要があります。

sort models into groups;
foreach(group)
    set state
    foreach(instance of group)
         glDrawArrays

これにより、状態遷移 (シェーダーの切り替え、テクスチャ バインディングなど) の約 99% を節約できます。これにより、パフォーマンスが大幅に向上します。

于 2012-06-26T22:43:57.247 に答える