SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

openGLでアキュームレーション・バッファを使ったモーション・ブラー


opneGLで,accumration bufferを使ったモーションブラーのサンプルです.
アキュームレーション・バッファの使い方のサンプルは,日本語ではあまり見かけなかったので,自分の備忘録も兼ねて書いておこうと思います.


で,サンプルとして,この間作ったスクリーンセーバーの一部をglutで動くようにしたので,そのソースと一緒に公開します.
http://www.geocities.jp/sourcechord/tips/accum.html

アキュームレーション・バッファとは

一度レンダリングした結果を格納しておくバッファの事です.
たとえば,視点の位置を少しづつずらしながら,何度もレンダリングした結果の平均値を取ることで被写界深度を表現したり,
ここで説明するように,モーション・ブラーをかけたり,といったことに使えます.
ちなみに,アキュームレーション・バッファでは各ピクセルの値を0〜1の浮動小数の値で保存するようです.で,その際に何bitので記録するかは環境によって変わってくるとのことです.

アキュームレーション・バッファに関係する関数の説明

アキュームレーション・バッファの初期化

・glClearAccum(0.0, 0.0, 0.0, 0.0);
アキュームレーション・バッファをクリアする色を決める
・glClear(GL_ACCUM_BUFFER_BIT);
glClearAccum()で指定した色で,アキュームレーション・バッファをクリアする.
(glutを使っている場合は,↓コチラも)
・glutInitDisplayMode(GLUT_DOUBLE | GLUT_ACCUM | GLUT_RGBA);
glutInitDisplayMode関数でGLUT_ACCUMを指定する.

アキュームレーション・バッファに格納

描画する関数の中でいかの命令を実行
・glAccum(GL_LOAD, x);
今画面に表示されている内容で,アキュームレーションバッファを上書きする.
その際今画面に表示されている値にxをかけたものが格納される.
・glAccum(GL_ACCUM, x);
今画面に表示されている内容を,アキュームレーション・バッファに加算する.
その際今画面に表示されている値にxをかけたものが格納される.
(被写界深度の表現や,アンチエイリアシングのためにスーパーサンプリングをするような場合に使う)
・glAccum(GL_ADD, x);
アキュームレーション・バッファの全ピクセルに,xを加える.
全体を明るくしたりするような場合に.
・glAccum(GL_MULT, x);
アキュームレーション・バッファの全ピクセルに,xをかける.

アキュームレーション・バッファの内容を描画

・glAccum(GL_RETURN, x);
アキュームレーション・バッファの内容を画面に描画
その際,xをかけた値で描画される.

モーション・ブラー

実際に,プログラムでモーションブラーを使うときには.

  • 初期化関数の中で,glClearAccum()・glClear(GL_ACCUM_BUFFER_BIT)の関数を実行して
  • 描画関数の中で
    1. glAccum(GL_RETURN, 1.0);//アキュームレーション・バッファの内容を描画
    2. 描画内容を記述
    3. glAccum(GL_LOAD, x); //xで残像の強さを制御

といった感じでできます.



ただ,ここまで説明してからこんな事言うのもなんですが・・
openGLのアキュームレーション・バッファへの対応はあまりよろしくないようです.
性能のいいグラボを積んでいれば高速にうごくのですが,
オンボードなどの場合はアキュームレーション・バッファに書き込むより,
メモリ上に自分でレンダリング結果を格納して,テクスチャとして描画した方が高速な場合が多いようです.


実際,自分のパソコン(グラフィックはオンボードのもの)で試した場合には以下のような症状がでました.
・小さめのウインドウのときはいいが,高解像度でフルスクリーンにすると,動きが極端に遅くなる.
(もちろん,アキュームレーション・バッファを使っていないときにはそんな症状はありません)
・GL_ACCUMEで加算し続けて,バッファの値が1.0を超すとおかしな色になる.(1.0でクリッピングしてくれてないみたい.)
ちなみにグラボを積んだパソコンでは,このような症状はでなかったので,環境によってだいぶ違ってくるようです.