2020年7月15日から2020年7月26日まで、影のレンダリングの処理を書いていました。影の演出方法には2通りの方法があります。

影の演出方法

  1. シャドウマッピング
  2. シャドウヴォリューム

シャドウマッピング

光源からの深度を使います。深度は視錯体のnear plane(目のある場所に近い平面)からの距離です。3dの物体をレンダリングする時、ライブラリは深度を保持し続けます。この深度を使用して、あるポリゴンに由来するピクセルが別のポリゴンに由来するピクセルに上書きされるかどうかを判定します。この手法は、1つのシーンを生成するのに、2回レンダリングを行います。

シャドウヴォリューム

影をレンダリングする為にシャドウヴォリュームという3dの物体を生成します。シャドウヴォリュームは、元の3dの物体があって、その物体を光源から、光の進む方向に物体を引き伸ばして生成します。この方法は、1つのシーンを生成するのに4回のレンダリングをお行います。

シャドウマッピングの使用

結局、処理が早いと思える、シャドウマッピングを使用して、影を演出することにしました。

シャドウマッピングのアルゴリズム

以下に示す手順でシャドウマッピングを行います。

  1. 光源からの視点での影用オフスクリーンバッファを生成。
  2. シーンを影用オフスクリーンにレンダリング。
  3. 深度をオフスクリーンに書き込む。
  4. 標準のスクリーンに目からの視点でレンダリング。
  5. レンダリングのピクセルの影深度を影用オフスクリーンバッファから読む。
  6. もし、表示しようとしているピクセルの深度が、影深度より大きいなら、そのピクセルを暗くする。

深度バッファの生成

室内光源というよりは、太陽光源をもでるとして使用しました。太陽からの光線はほぼ並行と考えることができます。一つの物体によって生み出される影の大きさは、その影が映り込んでいる物体の遠さには依存せず同じ大きさの影になります。この種の影を計算するには、遠近投影ではなく直投影を使用します。直投影のマトリックス表現は以下のようになります。

$$ \begin{equation} P = \left(\matrix{2\over{ right - left } & 0 & 0 & {-(right + left)}\over{right - left} \cr 0 & 2 \over{top - bottom} &0 & {-(top + bottom)}\over{top - bottom}\cr 0 & 0 & -2\over{far - near} & {-(far + near)} \over { far - near }\cr 0 & 0 & 0 & 1}\right) \end{equation} $$

6面の境界領域を6つのパラメータに渡すします。6面の境界の値は、ゲーム内で起こりうる全ての頂点座標から計算することができます。以下のパラメータについては悩む必要はないです。

$$ (left, right, bottom, top) = (x\_{min}, x\_{max}, y\_{min}, y\_{max}) $$

nearとfar

残りの2つのパラメータ(nearとfar)については、しばらく考えました。深度については、ともにマイナスの値が計算されていました。以下のような値です。

$$ (-0.0034, -3.5) $$

数の大きさのソートによると、以下のようになります。

$$ \begin{equation} (z_{min}, z_{max}) = (-3.5, -0.0034) \label{eq:numodr0} \end{equation} $$
原点からの距離によるソートを行うと以下のようになります。
$$ \begin{equation} (z_{min}, z_{max}) = (-0.0034, -3.5) \label{eq:disorder0} \end{equation} $$

Open-GLの仕様を読んで\eqref{eq:disorder0}を選択する必要がありました。\(P(3,3)\)の符号に注意すると、パラメータは、負符号で計算されています。先に挙げた6面体の深度zが\([-1, 1]\)の範囲に入るようにするには、次のようにパラメータを与えます。

$$ (near, far) = (- z_{min}, - z_{max}) $$

Open-GL ウィンドウシステム座標

なぜ、値を\([-1, 1]\)の範囲で渡す必要があるかというと、Open-GLの箇所に記載のある仕様によります。頂点から生成される座標は、\([-1, 1]\)でクリップされるのです。

レンダリング結果

以下が、影つきのシーンです。

影付きゲーム

いくつかの画素でエイリアシングがおきています。これについては、またの機会に修正したいと思います。