3

これは、opengl でマルチサンプリング (アンチエイリアシング用) を行う最初の試みです。基本的に、画面に背景を描画し (アンチエイリアスを適用しないでください)、続いてアンチエイリアスを適用する頂点を描画します。私がこれまでに行ったこと:

//create the framebuffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

//Generate color buffer:
glGenRenderbuffers(1, &cb);
glBindRenderbuffer(GL_RENDERBUFFER, cb);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, x_size, y_size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cb);

//Generate depth buffer:
glGenRenderbuffers(1, &db);
glBindRenderbuffer(GL_RENDERBUFFER, db);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT, x_size, y_size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, db);

...

glBindFramebuffer(GL_FRAMEBUFFER, 0);
//draw background ... ...

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//draw things that should get anti-aliased ... ...

//finally:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, x_size, y_size, 0, 0, x_size, y_size, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);

問題は、 glBlitFramebuffer(...) を呼び出すと、背景全体が黒くなり、アンチエイリアスされた頂点だけが表示されることです。

助言がありますか?

4

1 に答える 1

11

通常、画像の透明度を考慮しながら、既存のレンダリングの上に新しい画像/テクスチャをレンダリングする場合は、ブレンドが最も明白なオプションです。マルチサンプリングされたフレームバッファへのレンダリングを透明度のある画像として見ると、まさにその状況です。

この場合、ブレンドの使用を通常よりも困難にするいくつかの課題があります。まず、glBlitFramebuffer()ブレンディングを適用しません。仕様から:

ブリット操作はフラグメント パイプラインをバイパスします。ブリットに影響を与える唯一のフラグメント操作は、ピクセル所有権テストとシザー テストです。

マルチサンプリングを使用しない場合、これはかなり簡単に克服できます。を使用する代わりにglBlitFramebuffer()、画面サイズのテクスチャ付きクワッドを描画してブリットを実行します。現在、すべてのフラグメント操作が実行されているため、ブレンドを使用できます。

ただし、コンテンツがマルチサンプリングされているため、「テクスチャ付きクワッドの描画」の部分はより複雑になります。いくつかのオプションが思い浮かびます。

背景を FBO にレンダリングする

プライマリ フレームバッファの代わりに、マルチサンプリングされた FBO に背景をレンダリングできます。その後、glBlitFramebuffer()今とまったく同じように使用できます。

「でも、背景にアンチエイリアスをかけたくない!」と思うかもしれません。それは本当に問題ではありません。背景の描画中にマルチサンプリングを無効にするだけです。

glDisable(GL_MULTISAMPLE);

それはあなたが望むものをあなたに与えるべきだと思います。もしそうなら、それは断然最も簡単なオプションです。

マルチサンプル テクスチャ

OpenGL 3.2 以降では、マルチサンプル テクスチャがサポートされています。このために、FBO のカラー バッファとしてレンダ バッファの代わりにテクスチャを使用します。テクスチャは次のもので割り当てられます。

glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8,
                         xsize, ysize, GL_FALSE);

ここですべてをカバーすることはできません他の側面があります。このオプションを調べたい場合は、仕様または他のソースのすべての詳細を読むことができます。たとえば、シェーダー コードでのテクスチャのサンプリングは、異なるサンプラー タイプと、一度に 1 つのサンプルしか読み取れないサンプリング関数を使用して、異なる方法で動作します。

二段階ブリッティング

マルチサンプル コンテンツを解決するために のハイブリッドを使用しglBlitFramebuffer()、コンテンツをデフォルトのフレームバッファにブレンドするために「手動」ブリットを使用できます。

  1. カラー アタッチメントが通常のマルチサンプル テクスチャではない 2 番目の FBO を作成します。
  2. glBlitFramebuffer()最初の FBO のマルチサンプリングされたレンダバッファから 2 番目の FBO のテクスチャにコピーするために使用します。
  3. ブレンディングを設定して有効にします。
  4. 2 番目の FBO に添付されていたテクスチャを使用して、画面サイズのクワッドを描画します。

これはややぎこちなく、パフォーマンスにとって望ましくない余分なコピーが必要ですが、かなり簡単です。

背景を最後にレンダリングする

このために、現在行っていることとまったく同じように、マルチサンプリングされた FBO コンテンツをデフォルトのフレームバッファにコピーしますglBlitFramebuffer()。ただし、これを最初に行い、その後で背景をレンダリングします。

背景が他のコンテンツの前に置かれるため、これはうまくいかないと思うかもしれません。

しかし、ここで再びブレンディングの出番です。他のコンテンツの上にコンテンツをブレンドすることは、ブレンドを使用する最も一般的な方法ですが、既存のコンテンツの背後にあるものをレンダリングするためにも使用できます。これを行うには、いくつかのことが必要です。

  • アルファ プレーンを持つフレーム バッファ。どのようにリクエストするかは、OpenGL セットアップに使用するウィンドウ システム/ツールキットによって異なります。これは通常、深度バッファー、ステンシル バッファー (必要な場合) などを要求する同じ領域にあります。多くの場合、アルファ プレーンの数として指定され、通常は 8 に設定されます。
  • 正しいブレンド機能。前面から背面へのブレンドには、通常、次を使用します。

    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
    

    これにより、以前に何もレンダリングされなかった場所 (つまり、宛先のアルファが 0) に新しいレンダリングが追加され、既にレンダリングされていた場所 (つまり、宛先アルファが 1) には以前のレンダリングが変更されません。

    レンダリングに部分的な透明度が含まれる場合、ブレンディングのセットアップは少し複雑になる可能性があります。

これはやや複雑に見えるかもしれませんが、ブレンド関数がどのように機能するかを理解すれば、非常に直感的です。そして、それは全体的な問題に対する全体的にエレガントで効率的なソリューションだと思います.

于 2015-10-02T04:59:30.907 に答える