Normal.
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()の機能を再現できますか?

b:en:OpenGL Programming/Motion Blur