今回は4章の”Viewing”を読んでいくことにします。主な内容はピンホールカメラ,薄レンズカメラ,モーションブラーです。
そういえば,レイトレ合宿ではみんなでピンホールカメラを自作して,フィルムを現像して,きちん画が写るかなんてのもやったことがありますね。さて,脱線話はそれぐれいにして読んだ内容をまとめてみることにします。
もっとも単純に画像を取得するデバイスとしてピンホールカメラを作ることができます。ピンホールカメラは長い露出時間を必要とし,ピンホールが大きいと画像がぼやけるので,実生活で使われるのは稀です。代わりに大きな穴(開口部)が使われレンズが備え付けられます。フィルム上の1点における色は,コーンの方向から集められます。薄レンズ近似を用いてこれらのレンズに基づくカメラのうちの1つをシミュレートしてみます。
ピンホールカメラモデルを実装してみます。カメラの前側に仮想的なフィルム平面を生成し,ピンホール背後にあるフィルムを忘れることにします。これを行うためには,空間の外にフィルムを射影する設定が必要となります(図 1参照)。
距離\(s\)の選択は任意とし,大きくなれば矩形も大きくなり,画像も大きくなります。多くのレンダラーでは簡潔さのため\(s = 1\)が設定されていますが,あとでレンズを持つカメラを考えるので可変の\(s\)を使用することにします。
カメラを実装するために,図 2に示すようなビュー座標系に沿った矩形を選定します。
ビュー座標系は\(uvw\)座標における原点として定義される中心\({\mathbf e}\)を持ち,\({\mathbf{uvw}}\)基底に沿っています。\(uvw\)座標における,矩形の対角は\((u_0, v_0)\)と\((u_1, v_1)\)で与えられます。点\({\mathbf c}\)は矩形の左下側で,ベクトル\({\mathbf a}\)と\({\mathbf b}\)は矩形の下部と矩形の左側に沿って存在しています。これらは
\begin{eqnarray}
{\mathbf a} &=& (u_1 - u_0) {\mathbf u} \\ {\mathbf b} &=& (v_1 - v_0) {\mathbf v} \tag{1} \\ {\mathbf c} &=& u_0 {\mathbf u} + v_0 {\mathbf v} - s {\mathbf w} \end{eqnarray}
となります。注意してほしいのは注視方向上で真ん中である必要がないということです。矩形は負の\({\mathbf w}\)方向にあります。これはなぜかというと右手座標系にしたいからです。
スクリーン上の点\({\mathbf s}\)は
\begin{eqnarray} {\mathbf s} = {\mathbf c} + a {\mathbf a} + b {\mathbf b} \tag{2} \end{eqnarray}
となり,このとき\({\mathbf e}\)から\({\mathbf s}\)へのレイは
\begin{eqnarray} {\mathbf e} + t ({\mathbf s} - {\mathbf e}) \tag{3} \end{eqnarray}
となります。
ピクセル座標\((x, y)\)から\((a, b)\)へ行くためには,\([-0.5, n_x - 0.5]\)から\([0, 1]\)へ,そして\([-0.5, n_y - 0.5]\)から\([0, 1]\)へと対応付けをします。
\begin{eqnarray} a &=& \frac{x + 0.5}{n_x} \tag{4} \\ b &=& \frac{y + 0.5}{n_y} \tag{5} \end{eqnarray}
\(n_x\)は横方向のピクセル数で,\(n_y\)は縦方向のピクセル数になります。
設定すべき変数は次の通り:
この情報から\({\mathbf e}\)が原点で\(uvw\)フレームに沿った,次の基底ベクトルを構築します。
\begin{eqnarray} {\mathbf w} &=& - \frac{\mathbf g}{ \| {\mathbf g} \| } \\ {\mathbf u} &=& \frac{ {\mathbf v}_{\mathrm{up}} \times {\mathbf w} }{ \| {\mathbf v}_{\mathrm{up}} \times {\mathbf w} \| } \tag{6} \\ {\mathbf v} &=& {\mathbf w} \times {\mathbf u} \end{eqnarray}
これは汎用的なビュー座標系で,パラメータ設定を行う際に注意が必要であることに留意してください。注視方向の中心に位置するビュー矩形が欲しい場合は,\(u_0 = -u_1\)と\(v_0 = -v_1\)に設定します。正方形のピクセルが欲しい場合は
\begin{eqnarray} \frac{u_1 - u_0}{v_1 - v_0} = \frac{n_x}{n_y} \tag{7} \end{eqnarray}
を設定します。\(s\)を長くすると,同じ画像を得るためにウィンドウの横幅と縦幅が大きくなります。\(v_1 - v_0\)の比が\(2s\)になると,“垂直画角”の半分の正接(tangent)になります。
ピンホールカメラはすべてのものが完全に焦点があった画像を生成します。被写界深度は,焦点が合っていないオブジェクトがいくつかあり,ここでは薄レンズカメラモデルを使用して画像を生成します。このモデルはレイトレーサー上での実装が容易です。
薄レンズカメラはピンホールを円盤形状の”薄レンズ”に置き換え,ある理想的な挙動を持つものとします。カメラがレンズから距離\(s\)における点にフォーカスされた場合に,その点からのすべての光はレンズ背後の距離\(i\)の点にフォーカスされます。これらの2点はレンズ中心を通る線分に沿って存在します。距離\(i\)と\(s\)は次の薄レンズの法則に従います。
\begin{eqnarray} \frac{1}{s} + \frac{1}{i} = \frac{1}{f} \tag{8} \end{eqnarray}
ここで,\(f\)はカメラの焦点距離です。普通のカメラにおいて,\(f\)は数センチメートルで,\(s\)は\(f\)より小さくなりません。
単にフォーカスする効果が欲しい場合,また実際のカメラの仕様に一致する必要が無い場合は,オブジェクトが完全にフォーカスする場所における\(s\)とレンズの半径\(R\)を指定するだけで良いです。ピンホールカメラからの変更は\(s\)が任意ではなくなったことだけです。レイの原点\({\mathbf q}\)は中央に位置する\({\mathbf e}\)における\(uv\)平面上の半径\(R\)のディスクからランダムに選択します。ランダム点の選択はレンズからの距離\(s\)におけるオブジェクトには効果を及ぼしません。距離\(s\)におけるオブジェクトは焦点が合い,\(s\)よりも近いオブジェクトまたは離れたオブジェクトはブラーがかります。
現実のカメラに似せるためには,フィルムサイズ\((W, H)\)と,焦点距離\(f\)を指定します。露出を得るためのフィルムサイズは実際のフィルムの物理サイズです。なので,\(H\)はおおよそ\(35[\mathrm {nm}]\)フィルムのスプロケット間の距離になります。レンズの開口を指定するためには,単に半径\(R\)を指定すればよいのですが,\(f\)ナンバー,\(N = f /(2R)\)を使用するのが慣例です。これらの変数を与えると
\begin{eqnarray} \frac{ u_1 }{ W / 2} = \frac{ v_1 }{ H /2 } = \frac{ s }{ i } \tag{9} \end{eqnarray}
を得ます。ここで
\begin{eqnarray} i = \frac{sf}{s - f} \tag{10} \end{eqnarray}
より,
\begin{eqnarray} (u_1, v_1) = (-u_0, -v_0) = \left( \frac{W}{2} \frac{(s - f)}{f}, \frac{H}{2} \frac{(s-f)}{f} \right) \tag{11} \end{eqnarray}
となります。
典型的な\(35[\mathrm {nm}]\)カメラとレンズでは,\(f = 50 [\mathrm{mm}]\),\(W = 36[\mathrm{mm}]\),\(H = 24 [\mathrm {mm}]\)となります。
カメラで写真を撮るとき,シャッターはわずかな時間だけ開いています。撮影している被写体がシャッタースピードに比べて早く動いているとどうなるでしょうか?フィルム平面上の点はシャッターが開いている時間の一部分については被写体を見ることができ,残りの時間は背後の背景が見えます。これはモーションブラーを引き起こします。モーションブラーは動きのあるオブジェクトの現実的なフレームを作成するだけなく,アニメーションについても重要です。
オブジェクトの位置を時間の関数として定義し,ランダムな時間の値を各レイに対して関連付けることで,マルチサンプリングのレイトレーサー内でこの効果をシミュレートできます。
カメラのシャッターが開いて,閉じるまでの\(T_{\mathrm open}\)と\(T_{\mathrm close}\)の間でレイの時間は一様にランダムになります。
薄レンズモデルにモーションブラー効果を付け加えてみます。実装方法の1つとして,書籍ではレンズに対して2Dサンプリングする実装を紹介しています。
実装コードを,Githubにまとめておきました。
今回はビューイングについて理解を深めました。書籍の方にはサンプルシーンの実装コードがないため,実際に実装をしてモーションブラーをすぐに試せないのが残念ですね。