2

最近、新しいOpenGLバージョンへの変更を発見したので、FreeType2を使用してしばらく前に作成した小さなC++OpenGLフォントライブラリを書き直すことを計画しています。私のコードはイミディエイトモードを使用しており、glLineStippleなどの一部の関数呼び出しは現在非推奨になっていると確信しています。

コードが可能な場合はVBOを使用したり、他に何も利用できない場合は即時モードにフォールバックしたりするなど、さまざまなOpenGLバージョンをサポートしたいと思います。どうすればいいのかわかりませんが。Afaik、実行時に作成された有効なOpenGLコンテキストが必要なため、コンパイル時のチェックを行うことはできません。これまでのところ、私は次の提案を思いついた(他のスレッド/サイトからのインスピレーションを得て):

  • GLEWを使用して、描画関数の実行時チェックを行い、関数サポート(glLineStippleなど)をチェックします。

  • コンパイル時に指定できるいくつかの#defineおよびその他のプリプロセッサディレクティブを使用して、さまざまなOpenGLバージョンで動作するさまざまなバージョンをコンパイルします。

  • さまざまなOpenGLバージョンをサポートするさまざまなバージョンをコンパイルし、それぞれを個別のダウンロードとして提供します

  • システム上のOpenGLバージョンをチェックし(可能な場合/信頼できる場合)、ユーザーのバージョンのOpenGLに適合するようにソースに適切な変更を加えるスクリプト(Python / Perl)を使用してライブラリを出荷します。

  • 新しいOpenGLバージョンのみを対象とし、以下のもののサポートを削除します

とにかくGLEWを使用して、拡張機能を簡単にロードするつもりです。

フォローアップ: あなたの非常に有益な回答に基づいて、私は古いコードに基づいて数行を作成しようとしました。これがスニペットです(テスト/終了なし)。configヘッダーで適切な関数ポインターを宣言し、ライブラリが初期化されるときに、適切な関数ポインターを取得しようとします。VBOが失敗した場合(ポインターがnullの場合)、ディスプレイリスト(3.0で非推奨)にフォールバックし、最後に頂点配列にフォールバックします。fxの場合は、(多分?)利用可能なARB拡張機能も確認する必要があります。VBOの読み込みに失敗しますか、それとも作業が多すぎますか?これは確かなアプローチでしょうか?コメントは大歓迎です:)

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
    #define OFL_WINDOWS
    // other stuff...
    #ifndef OFL_USES_GLEW
        // Check which extensions are supported
    #else
        // Declare vertex buffer object extension function pointers
        PFNGLGENBUFFERSPROC          glGenBuffers          = NULL;
        PFNGLBINDBUFFERPROC          glBindBuffer          = NULL;
        PFNGLBUFFERDATAPROC          glBufferData          = NULL;
        PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
        PFNGLDELETEBUFFERSPROC       glDeleteBuffers       = NULL;
        PFNGLMULTIDRAWELEMENTSPROC   glMultiDrawElements   = NULL;
        PFNGLBUFFERSUBDATAPROC       glBufferSubData       = NULL;
        PFNGLMAPBUFFERPROC           glMapBuffer           = NULL;
        PFNGLUNMAPBUFFERPROC         glUnmapBuffer         = NULL;
    #endif
#elif some_other_system

初期化関数:

#ifdef OFL_WINDOWS
    bool loaded = true;

    // Attempt to load vertex buffer obejct extensions
    loaded = ((glGenBuffers          = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers"))                   != NULL && loaded);
    loaded = ((glBindBuffer          = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer"))                   != NULL && loaded);
    loaded = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer")) != NULL && loaded);
    loaded = ((glDeleteBuffers       = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers"))             != NULL && loaded);
    loaded = ((glMultiDrawElements   = (PFNGLMULTIDRAWELEMENTSPROC)wglGetProcAddress("glMultiDrawElements"))     != NULL && loaded);
    loaded = ((glBufferSubData       = (PFNGLBUFFERSUBDATAPROC)wglGetProcAddress("glBufferSubData"))             != NULL && loaded);
    loaded = ((glMapBuffer           = (PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer"))                     != NULL && loaded);
    loaded = ((glUnmapBuffer         = (PFNGLUNMAPBUFFERPROC)wglGetProcAddress("glUnmapBuffer"))                 != NULL && loaded);

     if (!loaded)
        std::cout << "OFL: Current OpenGL context does not support vertex buffer objects" << std::endl;
    else {
        #define OFL_USES_VBOS
        std::cout << "OFL: Loaded vertex buffer object extensions successfully"
        return true;
    }

    if (glMajorVersion => 3.f) {
        std::cout << "OFL: Using vertex arrays" << std::endl;
        #define OFL_USES_VERTEX_ARRAYS
    } else {
        // Display lists were deprecated in 3.0 (although still available through ARB extensions)
        std::cout << "OFL: Using display lists"
        #define OFL_USES_DISPLAY_LISTS
    }
#elif some_other_system
4

2 に答える 2

5

まず第一に、それはどこでもサポートされているため、安全です。 Vertex Arraysを使用するようにフォントレンダラーを書き直してください。これは VA から VBO への小さな一歩にすぎませんが、VA はあらゆる場所でサポートされています。拡張関数の小さなセットのみが必要です。GLEWに依存しないように、手動でロードするのが理にかなっていたのかもしれません。それを静的にリンクすることは、非常にやり過ぎでした。

次に、関数ポインターを介して参照できるラッパー関数に呼び出しを配置し​​、そのようにレンダー パスを切り替えることができます。たとえば、関数「stipple_it」などを追加すると、内部的に glLineStipple が呼び出されるか、適切なフラグメント シェーダーがビルドおよび設定されます。

glVertexPointer と glVertexAttribPointer についても同様です。

于 2012-05-29T12:19:44.910 に答える
3

すべてのチェックを手動で行いたい場合、Android/iOS は OpenGL ES のみをサポートし、ランタイム チェックが異なるため、いくつかの #defines から逃れることはできません。

(個人的な経験から) さまざまなハードウェア ベンダーのさまざまなドライバーには多くの注意事項があるため (もちろん、OpenGL 1.0 を超えるものについては)、ランタイム チェックもほとんど避けられません。

ATI/nVidia のほとんどのビデオカード、さらには Intel でさえ、GL ES 2.0 とほぼ同等の OpenGL 2.0+ のいくつかのバージョンをサポートしているため、「新しい OpenGL バージョンのみを対象とし、それ以下のサポートをドロップする」は実行可能なオプションです。

GLEW は、GL 拡張機能の取得を容易にする良い方法です。それでも、組み込みプラットフォームでの GL ES には問題があります。

ロード手順は次のとおりです。

  1. win32/linux では、関数ポインタが NULL でないことを確認し、GL の ExtensionString を使用して、この具体的なハードウェアで何がサポートされているかを確認します。

  2. iOS/Android/MacOSX の「読み込み」は、ポインタを格納するだけか、「何もしない」ことさえあります。Android は別の獣です。ここには静的ポインターがありますが、拡張機能を確認する必要があります。これらのチェックの後でも、「動作中」と報告されているものについては確信が持てない場合があります (「noname」Android デバイスまたは単純な gfx ハードウェアについて話している)。したがって、ビデオカードの名前に基づいて独自の (!) チェックを追加します。

  3. OSX/iOS OpenGL の実装は「問題なく動作」します。したがって、10.5 で実行している場合は GL2.1 になります。10.6 - 2.1 + 3.1/3.2 のようにするいくつかの拡張機能。10.7 - 3.2 コアプロファイル。Mac 用の GL4.0 はまだありません。これは主に 3.2 の進化版です。

私の個人的な意見に興味があるなら、私は主に「すべてを再発明する」陣営の出身であり、何年にもわたって自動生成された拡張ローダーを使用してきました。

最も重要なことは、正しい方向に進んでいることです。VBO/VA/Shaders/NoFFP に書き直すと、パフォーマンスが大幅に向上します。

于 2012-05-29T12:20:09.083 に答える