OpenGLで、GUIのために即時モードと保持モードを「組み合わせる」ことは悪い考えですか?


8

3DシーンglDrawArrays(...)を使用して描画していて、2Dオーバーレイのようなシンプルなものをレンダリングしたいとします。保持モードで2Dレンダラーをセットアップする代わりに、そのようなものに即時モードを使用することは悪い考えでしょうか?

例:

void Draw()
{
    // Draw the 3D scene:
    // *does stuff*
    glDrawArrays(...);
    // *some other stuff*

    // Setup a quad with immediate mode (for something like a vignette overlay)
    glBegin(GL_QUADS);
    glTexCoord2f(...); glVertex2f(...);
    glEnd();
}

Minecraftはこれを行います。OpenGLのバージョンを(<3.1または互換性プロファイルに)制限することと、GUIの速度を低下させることを除いて、問題なく動作します。
user253751 2018年

Minecraftには、頂点配列を使用してイミディエイトモードをシミュレートする独自の関数セットもあります。作成するのは難しくありません。彼らがGUIに使用しているかどうかはまだわかりません。
user253751 2018年

回答:


7

それが無意味である限り、それは悪い考えです。オルソ射影行列(いずれにせよ行う必要がある)を除いて、まだ設定していないことはありません。

移植性は問題ではありませんが、おそらく問題ではありません。IHVは近い将来、即時モードのサポートを中止することを非常に躊躇しているようです(コアプロファイルでも「正常に動作する」ように思われます)。したがって、即時モードはずっと前に消滅していたはずですが、おそらく永久にとどまります。パフォーマンスは別の話です。シーンの複雑さの0.1%を占めてCPU時間の15-20%を消費するものを本当に望んでいますか?GL呼び出しは、DXなどと比較して比較的軽量ですが、無料ではありません-15-20%リアルパイプラインの停止によるフレーム時間?あなたはあなたの時間予算でそれを買う余裕さえありますか?ほとんどのゲームはできません。

そして、もちろん、癖です。気まぐれです。イミディエイトモードの明らかな美しさは、いくつかの四角形をすばやく描画するような操作を(一見すると)簡単かつ簡単に行えることです。実際には、即時モードは後部のそのような苦痛である可能性があります、それはそれほど明白でない落とし穴でいっぱいです。
一方、DrawQuad呼び出されたときに頂点座標とインデックスをメモリバッファーに追加し、カウンターをインクリメントする小さな5-LOC関数を記述するだけで、簡単に(そして私に尋ねればより簡単です!)驚いたことに、glDrawArrays/Elements次のフレームは何も変更しない限り、次のフレームをそのまま使用して描画し、再利用できます(ユーザーランドコピーだけでなく、GPUコピー!)。
即時モードでは、他に方法はなく、毎回バッファを割り当ててPCIe転送を行う必要があります。または、同等のレイテンシ(GPUがバスを介してメインメモリを読み取るなど)。ドライバーは、データが以前のフレームとまったく同じままであることをおそらく知る(または想定する)ことができません。

GPUへのデータの取得は高速ですが、待ち時間長くなります。バス転送自体が複雑で待ち時間の長いプロトコル(複数のプロトコルレイヤー、パケット化、確認応答など)であるだけでなく、すべてのGPUが同時に転送して描画することさえできない場合、または可能であれば、別のことをしている間、いつでも自由に切り替えたり、新しい操作を開始したりできない場合があります。次のように読んでください:むやみに転送しないでください。


「まだ行っていない「設定」するものは何もありません」バッチレンダリング?
HolyBlackCat 2018年

2
IHVは即時モードを落とすことをためらっていますが、コアプロファイルを要求しない限り、より高いOpenGLバージョンをサポートしないLinuxのビデオドライバーもあります。これは特に、インテルHDグラフィックス(intelドライバー)を意味しますが、オープンソースドライバー(nouveauおよびamdgpuそれぞれ)を使用する場合、NVidiaおよびAMDチップも意味します。同様に、MacOSでは、OpenGL> 2.1との互換性プロファイルもありません。
ルスラン

@HolyBlackCat:どういう意味かわかりませんか?OPは、に基づく3Dパイプラインが機能していると述べていglDrawArraysます。したがってglDrawElements、(バッファーに頂点を書き込んだ後)GUIのすべてのクワッドを描画するために(または配列のいずれか)をさらに呼び出すために必要な設定がすべてあります。関数がロードされ、バッファを割り当てるためのフレームワークなどがあります。GUIのバッチ処理に関して特別なことはありません。GUIテクスチャをバインドして(バインドされたままにするのに十分なTUが残っている場合はバインドしないでください)、オルソ行列を設定して、追加の描画呼び出しを1回実行します。どのようにバッチ処理を改善しますか?
デイモン

(もちろん、私は即時モードが悪いことには同意します。)はっきりしていなければ申し訳ありません。上記の頂点バッファーを埋めるプロセスを意味します。簡単ですが、イミディエイトモードを使用するよりも少し作業が多くなります。
HolyBlackCat 2018年

12

私は個人的には2つの理由でそれが悪いとだけ思っています:

  1. それは非常に古く、非推奨です。そして、
  2. OpenGLを使用した最新の描画方法よりもはるかに低速です。

しかし、問題が解決し、パフォーマンスが問題にならない場合、およびプログラムで非推奨のOpenGL関数を使用することが問題ではない場合は、実行できると思います。TONSとTONSのGUIを使用するのは遅くなりますが、それほど多くない場合は、繰り返します。

しかし、これを理解してください。結局のところ、OpenGLは同じことをしています。画面に描画します。イミディエイトモードは、多くの処理が行われている場合は、はるかに遅くなります。だから、あなたはあなたが考えているタスクに最も役立つものを選ぶべきです。これがあなたを助けることを願っています!


1

もう1つの欠点は、コードの移植性が低下することです。OpenGL ESなど、特定のOpenGLバリアントはイミディエイトモードをまったくサポートしていません。(そして、タブレットなどのより大口径のAndroidベースのデバイスはより多くの牽引力を得るので、それは重要になる可能性があります)


0

GUI関連の作業では、即時モードの使用は完全に不要です。

簡単なGUIアイテムを作成するために、ボタンとしましょう:

  1. 四角形/三角形のストリップメッシュが必要です。
  2. メッシュのテクスチャ
  3. 正射影変換

このようにして、ライティングの考慮事項を無視する単純なパススルーシェーダーを作成し、GUIアイテムをピクセルスケールまたはウィンドウの一部の割合にスケーリングしてから、描画のためのペインターアルゴリズムを実行します。

このようにして、保持モードのすべてのパフォーマンス上の利点を備えた完全なUIシステムを実行できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.