このプログラムは、OpenGL における「テクスチャマッピング (Texture Mapping)」の基礎を学ぶための、学生向けのサンプルプログラムです。本プログラムは、以下のブログ記事の解説に沿って学習を進めるための雛形として提供されています。
今回は次の立方体の6面のそれぞれにキューブマッピングに使ったテクスチャをマッピングしたプログラムを修正して、その立方体の中心に視点を移動し、立方体の内側を眺めてみます。
このプログラムは CMake を用いてビルドを構成しています。各プラットフォームごとの手順は以下の通りです。なお、プログラムをビルドするためのバイナリディレクトリは、バージョン管理ファイル(.gitignore)の設定に合わせて build という名前にします。
-
コマンドプロンプトまたは PowerShell を開き、このプロジェクトのディレクトリに移動します。
-
以下のコマンドを実行してビルドディレクトリを作成し、CMake で構成を行います。
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022"-
生成された build フォルダ内の texture12.sln を Visual Studio で開きます。
-
ソリューションエクスプローラーで texture12 プロジェクトを右クリックし、「スタートアップ プロジェクトに設定」を選択します。
-
「ローカル Windows デバッガー」をクリックするか、F5 キーを押してビルドおよび実行します。
-
ターミナルを開き、このプロジェクトのディレクトリに移動します。
-
以下のコマンドを実行してビルドディレクトリを作成し、Xcode 用のプロジェクトを生成します。
mkdir build
cd build
cmake .. -G Xcode-
生成された build/texture12.xcodeproj を Xcode で開きます。
-
左上のスキーム選択(再生ボタンの横)が texture12 になっていることを確認します。
-
「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
texture12.exe- macOS
Xcode 上で左上の「Run(再生ボタン)」をクリックするのが楽です。これにより texture12.app アプリケーションバンドルとして自動的に実行されます。アプリケーションバンドルを直接起動するなら、Finder から build/Debug/texture12.app をダブルクリックするか、ターミナルから open build/Debug/texture12.app を実行します (この場合はエラーメッセージ等が表示されません)。
- Ubuntu Linux
ターミナルから以下のコマンドで実行ファイル(バイナリ)を直接起動します。
cd build
./texture12-
マウスの左ボタンでドラッグ: 視点を回転(実際には箱の方を回転)させ、部屋(箱)の内部を見回すことができます。マウスの動きに合わせて周囲の壁、天井、床(テクスチャ)が移動します。
-
キーボードの q, Q または ESC キー: プログラムを終了します。
プログラムのソースコード(主に main.cpp と box.cpp)をもとに、このプログラム内で行われている処理手順を解説します。このプログラムは、複数のテクスチャ画像を個別に読み込み、立方体の各面に切り分けてマッピングした上で、視点を立方体の内部に配置して「部屋の中心からあたりを見回す」処理を実装しています。
-
テクスチャ領域の確保:
glTexImage2D()関数を使って、幅 1024、高さ 128 のテクスチャ領域を OpenGL に登録します。引数に渡す配列textureには有効な画像データを含めず、単に空のテクスチャメモリを確保する目的で使用しています。 -
画像の読み込みとテクスチャの部分的な置き換え:
続いて、部屋の各面(壁、天井、床など)に貼り付ける 6 つの画像ファイル (
room2ny.rawなど) を順番に読み込みます。各画像は 128×128 ピクセルのサイズです。 読み込んだ画像はglTexSubImage2D()を使って、先に確保した 1024×128 のテクスチャ領域の一部として転送します。このとき、X軸方向のオフセット(xoffset)をi * 128とすることで、6枚の画像を横に並べて1つの大きなテクスチャを構成しています。これにより、あらかじめ結合された画像を用意しなくても、プログラム上で動的にテクスチャをまとめることができます。 -
カリングの無効化:
通常の描画では、ポリゴンの裏側(視点から見えない面)は描画を省略するカリング処理が行われますが、今回は箱の「内側」を見るため、
init()関数内でglDisable(GL_CULL_FACE)を呼び出し、裏面も描画されるように設定しています。
実際に部屋(立方体)を描画している部分です。glBegin( GL_QUADS ) から glEnd() の間で、6つの面(四角形)を描画しています。glVertex3dv()(頂点座標の指定)を呼び出す直前に、glTexCoord2dv() を使ってテクスチャ座標を指定しています。
main.cpp で構成したテクスチャは、6枚の画像が横に結合された状態になっています。そのため、各面に異なるテクスチャを表示させるために、面ごとに 1/8(0.125)ずつの幅でテクスチャ座標を切り分けて割り当てています。
/* 頂点のテクスチャ座標 */
static const GLdouble texcoord[][4][2] = {
{ { 0.0, 1.0 }, { 0.125, 1.0 }, { 0.125, 0.0 }, { 0.0, 0.0 } },
{ { 0.125, 1.0 }, { 0.25, 1.0 }, { 0.25, 0.0 }, { 0.125, 0.0 } },
/* ... 他の4面も同様に 0.125 ずつずらす ... */
};このように部分的な座標を割り当てることで、1つのテクスチャを複数の面に分割してマッピングすることができます。
-
部屋としての大きな箱の描画:
scene()関数内でbox(50.0, 50.0, 50.0)と呼び出しており、非常に大きな立方体を描画しています。これにより、視点が箱の内部に収まるようになります。 -
視点の移動を行わない設定:
display()関数内では、以前のプログラムで行っていた「視点の移動(物体の奥への移動)」の処理であるglTranslated(0.0, 0.0, -5.0)がコメントアウトされています(#if 0ブロック内)。この結果、視点は常に原点(0, 0, 0)、すなわち部屋(立方体)の中心に留まります。 -
周囲を見回す操作:
display()関数内では、GL_MODELVIEWモードでトラックボール処理の回転行列 (trackballRotation()) を現在のモデルビュー行列に掛け合わせています。 視点が原点にある状態で、周囲の大きな箱全体をマウスドラッグで回転させることで、結果的に「部屋の中心で視点を回転させて、あたりを見回す」という視覚効果を実現しています。
