OpenGLプログラミング/Motion Blur


はじめに
[編集]カラーバッファ、デプスバッファ、ステンシルバッファとは別に、ほとんどのグラフィックスカードには、アキュムレーションバッファといわれるオフスクリーンのフレームバッファが用意されています。 これらは基本的に、1色につき16ビット以上の精度を持つカラーバッファです。 しかし、アキュムレーションバッファに直接描画することはできません。 その代わりに、アキュムレーションバッファ全体を一度に処理する演算がいくつかあります。
glAccum(GL_LOAD, value)- ノーマルカラーバッファの内容をコピーして、
valueで乗算し、アキュムレーションバッファへ。 glAccum(GL_RETURN, value)- アキュムレーションバッファの内容をコピーし、
valueで乗算し、カラーバッファへ。 glAccum(GL_ACCUM, value)- ノーマルカラーバッファの内容を加算し、
valueで乗算し、アキュムレーションバッファへ。 glAccum(GL_ADD, value)- アキュムレーションバッファ内のすべてのピクセルに
valueを加算する。
l glAccum(GL_MULT, value): アキュムレーションバッファ内のすべてのピクセルに valueを乗算する。
すべての場合において、 valueは浮動小数点数(GLfloat)です。
これらの関数を使うと、複数のフレームの(重み付けされた)和や平均を簡単に計算することができます。
このチュートリアルでは、この関数を使って、ほとんどのOpenGLプログラムにモーションブラーを簡単に追加する方法を紹介します。
モーションブラー
[編集]モーションブラーは、オブジェクトが(カメラに対して)非常に速く動いたり、カメラの露光時間が非常に長くなったりして、露光中に一部の物体が半ピクセル以上動いてしまい、それが不鮮明に見えることで発生します。 モーションブラーは通常、好ましいものではありませんが、実際のカメラでは避けるのが難しい場合があります。 なぜなら、露光時間はシーン内の光の量に大きく依存するからです。 光量が少なければ露光時間が長くなり、ブレの影響が強くなります。 屋外でビデオカメラを使って撮影した映像と、室内で同じカメラを使って撮影した映像の「感じ」が違うのは、このためです。
モーションブラーの再現
[編集]アキュムレーションバッファを使ったモーションブラー効果は、実はとても簡単に作ることができます。
- 通常のOpenGLアプリケーションの動作はこのようになっています
for (;;) { do_time_evolution(timestep); draw_scene(); glSwapBuffers(); wait_until_next(timestep); }
ここで、関数 do_time_evolution() は、シーン内の移動するオブジェクトの座標や、カメラ自体の動きの更新を行います。
シーンが描画された後、glSwapBuffers()によって画面に表示されますが、オプションとしてフレームレートを制限するためにしばらく待ちます。
- モーションブラーを追加するには、より小さなタイムステップでシーンを複数回描画し、その平均値のみを表示することができます
int n = <number of frames to accumulate> int i = 0; for (;;) { do_time_evolution(timestep / n); draw_scene(); if (i == 0) glAccum(GL_LOAD, 1.0 / n); else glAccum(GL_ACCUM, 1.0 / n); i++; if (i >= n) { i = 0; glAccum(GL_RETURN, 1.0); glSwapBuffers(); wait_until_next(timestep); } }
多くのフレームを蓄積することで最高の効果が得られますが、GPUの能力によってすぐに制限されてしまいます。
蓄積するフレーム数を設定できるようにするか、1回のtimestepでレンダリングできるフレーム数を自動的に決定するようにするのがよいでしょう。
練習問題
[編集]- これまでのチュートリアルのどれかにモーションブラーを追加してみましょう。より面白いのは、mini-portalとglescraftで、シーンの中を歩き回れるようになっています。
- シーンに後処理効果を加える場合、モーションブラーを適用する前と後のどちらにすべきでしょうか?
- GPUがアキュムレーションバッファを提供しない場合、テクスチャにレンダリングすることで
glAccum()の機能を再現できますか?