このプログラムは、OpenGL における「テクスチャマッピング (Texture Mapping)」の基礎を学ぶための、学生向けのサンプルプログラムです。本プログラムは、以下のブログ記事のサンプルプログラムです。
本プログラムでは、シャドウマッピングを用いた影付け処理を実装しています。また、アルファテストを用いて影と日向の部分を別々にレンダリングすることで、自然な陰影を表現しています。さらに、おまけとしてアキュムレーションバッファを用いてソフトシャドウを実装した main_accum.cpp も含まれています。
このプログラムは CMake を用いてビルドを構成しています。各プラットフォームごとの手順は以下の通りです。なお、プログラムをビルドするためのバイナリディレクトリは、バージョン管理ファイル(.gitignore)の設定に合わせて build という名前にします。
(なお、ソフトシャドウを実装した main_accum.cpp を試す場合は、CMakeLists.txt 内の main.cpp の記述を main_accum.cpp に書き換えてからビルドを行ってください。)
-
コマンドプロンプトまたは PowerShell を開き、このプロジェクトのディレクトリに移動します。
-
以下のコマンドを実行してビルドディレクトリを作成し、CMake で構成を行います。
mkdir build cd build cmake .. -G "Visual Studio 17 2022"
-
生成された build フォルダ内の texture23.sln を Visual Studio で開きます。
-
ソリューションエクスプローラーで texture23 プロジェクトを右クリックし、「スタートアップ プロジェクトに設定」を選択します。
-
「ローカル Windows デバッガー」をクリックするか、F5 キーを押してビルドおよび実行します。
-
ターミナルを開き、このプロジェクトのディレクトリに移動します。
-
以下のコマンドを実行してビルドディレクトリを作成し、Xcode 用のプロジェクトを生成します。
mkdir build cd build cmake .. -G Xcode -
生成された build/texture23.xcodeproj を Xcode で開きます。
-
左上のスキーム選択(再生ボタンの横)が texture23 になっていることを確認します。
-
「Run」ボタン(再生ボタン)をクリックするか、Command + R を押してビルドおよび実行します。
-
ターミナルを開き、このプロジェクトのディレクトリに移動します。
-
必要なパッケージ(freeglut3-dev や pkg-config など)がインストールされていることを確認し、以下のコマンドでビルドします。
mkdir build cd build cmake .. make
各OSとも、ビルド後に生成されるバイナリディレクトリ (build) やそのサブフォルダから起動します。(※ CMake の設定により、Windows や Xcode では Debug などのフォルダ下に実行ファイルが置かれることがあります)
-
Windows
Visual Studio 上で「ローカル Windows デバッガー」をクリックして実行するか、またはコマンドプロンプトから以下のコマンドで起動します。
cd build\Debug texture23.exe -
macOS
Xcode 上で左上の「Run(再生ボタン)」をクリックするのが楽です。これにより texture23.app アプリケーションバンドルとして自動的に実行されます。アプリケーションバンドルを直接起動するなら、Finder から build/Debug/texture23.app をダブルクリックするか、ターミナルから open build/Debug/texture23.app を実行します (この場合はエラーメッセージ等が表示されません)。
-
Ubuntu Linux
ターミナルから以下のコマンドで実行ファイル(バイナリ)を直接起動します。
cd build ./texture23
-
マウスの左ボタンでドラッグ
空間全体または物体を回転させることができます。オブジェクトの形状に応じて、自分自身に落ちる影(セルフシャドウ)を含め、シャドウマッピングによる影が動的にレンダリングされている様子が確認できます。
-
キーボードの q, Q または ESC キー
プログラムを終了します。
プログラムのソースコード(主に main.cpp および main_accum.cpp)をもとに、このプログラム内で行われている処理手順を解説します。このプログラムでは、デプステクスチャを用いたシャドウマッピング法により影付け処理を実現しています。
-
デプステクスチャの割り当て
テクスチャとして奥行き値を保持するデプステクスチャを用いるため、
glTexImage2D()のtargetとformatにGL_DEPTH_COMPONENTを指定し、必要なサイズのメモリを確保します。 -
比較モードとテクスチャ座標の設定
テクスチャ座標の R成分 とテクスチャの値を比較するように設定し(
GL_COMPARE_R_TO_TEXTURE)、その結果をアルファ値(GL_ALPHA)として得るようにします(USE_ALPHA_TEST有効時)。また、テクスチャ座標は視点座標系における物体の座標値を用いるよう、GL_EYE_LINEARで自動生成の設定を行います。
デプステクスチャは、光源位置から見たシーンをレンダリングして作成します。
-
視点とビューポートの設定
ビューポートをテクスチャのサイズに設定し、透視変換行列を単位行列に初期化した上で、光源位置を視点としてシーンが視野に収まるようにモデルビュー変換行列を設定します。このときのモデルビュー変換行列は、後でテクスチャ変換行列として使用するため保存しておきます。
-
デプスバッファへの描画とテクスチャへの転送
デプスバッファの内容だけを取得するため、フレームバッファへの書き込みや陰影付けは無効にします。影の領域が光源に対する背面のポリゴンから始まるように
glCullFace(GL_FRONT)を設定してシーンを描画します。その後、glCopyTexSubImage2D()でデプスバッファの内容をテクスチャメモリに直接コピーし、デプステクスチャを生成します。
視点位置を元に戻し、通常の描画設定でシーンのレンダリングを行います。
ここではアルファテストを利用して影と日向の部分を分けてレンダリングします。まず、影の部分としてシーン全体を描画します。このとき、影の中に不自然なハイライトが生じないように光源の明るさ(鏡面反射成分など)を落とした設定(lightdim、lightblk)で scene() を描画します。
次に、日向の部分だけを重ねて描画します。
-
テクスチャ変換行列の設定
自動生成されたテクスチャ座標値(ワールド座標系での座標値)を、光源位置から見たスクリーン座標系に変換するため、テクスチャ行列スタックで
glMultMatrixd()などを使い変換行列を構築します。これにより、光源から見た座標がテクスチャ空間の [0, 1] の範囲に収まるように変換されます。 -
アルファテストによる重ね描き
テクスチャマッピングとテクスチャ座標の自動生成を有効にした後、アルファテスト(
glEnable(GL_ALPHA_TEST))を有効にし、デプステクスチャの比較結果が真(日向)となる部分のみを描画対象とします。このとき、glDepthFunc(GL_LEQUAL)と設定することで、先ほど描画した影のシーンの上に日向の部分をピッタリと重ね合わせて描画し、自然な陰影表現を完成させます。
おまけとして添付されている main_accum.cpp では、シャドウマッピングの境界を滑らかにするソフトシャドウ(Soft Shadow)を実装しています。
ここでは、光源の位置(samplepos)を乱数で少しずつずらしながら、前述の第1ステップ〜第3ステップの描画を SAMPLES 回(10回)繰り返します。それぞれのレンダリング結果は glAccum() を用いてアキュムレーションバッファに積算され、最終的に合成された画像が画面に表示されることで、境界がぼやけた柔らかい影が表現されます。
