「 FramebufferObject 」一覧

OpenGLでMSAA


以前にDirectX11でMSAAというタイトルでテクスチャに対するMSAAをやってみましたが今回はそれのOpenGL版をやってみたいと思います。結果はこんな感じです。画像を切った貼ったしたので、ねつ造と言われてしまうかも・・・。

ogl-msaa-result

必要になるGL拡張

最近のOpenGL対応ボードならば問題ないと思いますが、OpenGL 2.1対応とか言われているボードでは下記の拡張が存在するか確認が必要です。

  • GL_EXT_framebuffer_blit
  • GL_EXT_framebuffer_multisample

これが NVの拡張であってもとりあえず使えるには使えると思います。

手順

まず、FBOが2つ必要になります。内訳としては次のような感じです。

  • MSAA描画するFramebufferObject(fbo)を作成する.
  • MSAA処理されたテクスチャを得るためのfboを作成する

描画時の流れはこんな感じです。

  1. MSAAのFBOをバインドして描画を行う
  2. MSAAのFBOから通常FBOへBlitFramebuffer
  3. 通常FBOの中にアタッチされているテクスチャを使用

このBlitFramebufferという処理がDirectXでいうところの Resolve関数になるかなと思います。
この処理によって通常のテクスチャとしてMSAAがかかった描画結果を使用することができます。
DirectX時はテクスチャに対して Resolve 出来ましたが GLではそれが直テクスチャ指定できないので一度FBOを作る必要があるようです。

プログラムコード

まずMSAAのFBOを作るところです。
MSAAの場合はテクスチャをアタッチするのではなくレンダーバッファをMSAA用のものを作成し、それを使用するようにします。

Resolve先のFBOを作成します。

描画の時の Resolve関連はこんな感じになります。

注意点など

glBlitFramebufferのバッファフラグは OR 結合で複数指定は出来ないようなので注意しましょう。
MSAAの動作確認時には、小さいテクスチャに対して描画してそれを拡大して貼るのがおすすめです。また、元々は水平垂直のポリゴンを回転させて斜めになるようにして描画したものを使用するとMSAAのかかり具合の確認がしやすいです。

確認の際にはテクスチャフィルタをポイントサンプルとなるようにしておくことや、ドットバイドットの表示をしておくことも忘れがち&やっちゃいがちなので注意しましょう。
(現にDX11のときにはうまくできたのに、GL版実装中で自分が↑をやっちゃいました)


OpenGLでのテクスチャレンダリングパフォーマンスについて


OpenGLでテクスチャレンダリングをする場合には、いくつかの方法が考えられます。

  • FBO(FramebufferObject)をレンダリングごとに用意
  • FBOを1つ作っておいて、その中に書き込み先となるテクスチャを再セット
  • pbufferを使う

最後のやつは、かなりレガシーな古いコードとなりそうなので、
最近の環境であればFBOを使うことにしておいた方がいいと思う。
それでも上記のような2ケースがあるので、どちらがいいか検討してみたいと思う。

ちなみにFBOはiPhone環境でも使えるようで、
OpenGL ES 2.0世代な環境ならば標準的に使えるのかもしれない。
それならますますFBOで良さそうってもんです。

Next-Generation Rendering with OpenGL
“http://origin-developer.nvidia.com/object/gdc_2005_presentations.html”

上記のURLからGDC2005での発表資料をゲットできる。
今となっては6年前の資料だからどこまで信用して良いかわからない。
(6年も立てばGPUのアーキテクチャやドライバも相当進化するし)。

実験

100枚のレンダー先となるテクスチャを用意し、
それぞれにFBOを用意するタイプ(TYPE1)と、FBOは1つでバインドするテクスチャを交換していくタイプ(TYPE2)の2ケースで速度を計測してみました。

環境は、Windows7 SP1で、AMD RADEON 6850 を使用しています。
コンパイラはVisualStudio 2010 Pro です。
計測はリリースビルドで行っています。

種別 速度
TYPE1 4~5 ms
TYPE2 5~6 ms

微妙な差ですが、それぞれFBOを用意してあげる方がより高速な結果となりました。

AMD製なので資料の主張と異なる結果が出てくるかと思っていましたが、同じ結論を得ることが出来て一安心です。

まとめ

テクスチャレンダリングの際にはテクスチャごとに専用FBOを用意してあげるほうがよい。


レンダーバッファとレンダーテクスチャ


Framebuffer Objectで設定するレンダーバッファとレンダーテクスチャについて。どこかの記載で、レンダーバッファのほうがレンダーテクスチャよりも
高速に動く余地があるということが書いてあった。
これは以前の日記でも書いたとおり。ここでFBOにはレンダーテクスチャとレンダーバッファとそれぞれ設定するための関数が用意されているが、
同時に設定したらどんなことが起こるのかが疑問であった。
レンダーバッファとレンダーテクスチャ、両方が同時に使えるのだろうか?

実験

今回は、以前のデプステクスチャ、デプスレンダーバッファのコードがあったのでこれを利用して試してみました。

  1. レンダーテクスチャを用意
  2. レンダーバッファを用意
  3. framebuffer objectを用意
    1. カラーに関してはレンダーテクスチャをセット
    2. デプスについてはこの時点ではセットせず

この後、メインループに入ったところで
何らかのボタン押下により、レンダーバッファをアタッチ、もしくは、レンダーテクスチャをアタッチさせる。
このとき、Fboの状態取得関数を用いてどのようになっているかを調査する

ちなみに今回、デプスのアタッチなので正常にアタッチ状態は
画面の描画が正常であることを前提にして取得できる値を確認した。

結果

Case 1:レンダーテクスチャをアタッチして、レンダーバッファをアタッチ

このとき、状態は以下のように遷移した。

Case 2:レンダーバッファをアタッチして、レンダーテクスチャをアタッチ

このときは以下のように遷移した。

まとめ

実験の結果から、アタッチできるのはレンダーバッファかテクスチャかどちらか1方であることがわかった。
すでにアタッチされている場合、それは解除され新しく設定したほうが、
対象先の有効なアタッチ先となる。

個人的にはレンダーテクスチャのアタッチだけでいい気もする。
パフォーマンスもそんなに損なわれないのであれば、あるいは許容できる範囲なら、
Renderbufferを使用せず、RenderTextureだけで実装した方が
シンプルにまとまっていい感じになるような、そう思います。


FramebufferObject挙動違い -その3-


今回は今までの総合しての解決編になります。
デプスとステンシルを1つのテクスチャでOKとし、
さらにNVIDIAとAMDと双方で問題なく動く、という解法になります。

実装コード

やはりテクスチャの作成がポイントでした。

内部フォーマットに D24S8の指定を行い、
ピクセルフォーマットとして、GL_DEPTH_STENCIL_EXTを設定
これに対応する型として GL_UNSIGNED_INT_24_8_EXT を設定

この組み合わせがすべてを解決してくれました。

このデプステクスチャがうまくいったので、
書いた値をファイルに書き出してみました。
こんな感じに記録されており、何らかの値がかかれているのがわかります。
値はちょっとわからないですが、形状からおおむね正しくデプステクスチャに書き込んでいるものと推測できます。

取得する際にはこんな感じで。

GL_DEPTH_STENCIL_EXT GL_UNSIGNED_INT_24_8_EXT
GL_DEPTH_COMPONENT GL_UNSIGNED_INT

組み合わせを間違えるとうまく値がとれません。
デプス確認するだけなら、下段の書き出し方法のほうが見やすいかも。


FramebufferObject挙動違い -その2-


AMD製グラフィックボード時でも正常動作できる組み合わせを発見しました。テクスチャの生成時がポイントです。

解決方法(AMDオンリー)

これを従来通りにFramebufferObjectにデプス用としてアタッチしてあげると、
正常に動作することができました。

問題点

このコード、AMD製カード搭載時はうまくいくのですが、
NVIDIA製カード搭載時にはうまく動作しないのです。

解決方法

前述の方法を発展させて、NVIDIA/AMD双方で動く設定を以下に示します。
やはりテクスチャの作成がポイントです。

このコードを見て、「あぁNVIDIAはデプス D24以上しか対応してなかった」と思い出しました。
D16とかNVIDIAでは使えないんですよね。

懸念点

この方法だとStencil使いたくなったときに、もう1枚テクスチャが必要に。
さてさて、どうするか。
packed depth stencilの拡張が何かあったけど、これがテクスチャで使えたりしないだろうか。
要調査と言うことで。