前回はOpenGLのテクスチャのapiを紹介しましたが、今回はトンネルのケースを使ってテクスチャを適用してみます。効果は次のようになります:
テクスチャの読み込み
今回は3つのテクスチャが使われているので、forループを使って順番にテクスチャをバインドしてロードします。
//テクスチャオブジェクトを割り当てる
glGenTextures(TEXTURE_COUNT, textures);
for (iLoop=0; iLoop<TEXTURE_COUNT; iLoop++) {
//テクスチャオブジェクトをバインドする
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
//tgaファイルを読み込む
pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeigth, &iComponents, &eFormat);
//テクスチャの読み込み、フィルター、ラッピングモードの設定
//GL_TEXTURE_MAG_FILTER(ズームフィルター),GL_NEAREST(最近傍フィルター)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//GL_TEXTURE_MIN_FILTER(ズームフィルター),GL_NEAREST(最近傍フィルター)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//GL_TEXTURE_WRAP_S(s軸サラウンド),GL_CLAMP_TO_EDGE(サラウンドモードでは、範囲外のテクスチャ座標は、法的なテクスチャユニットの最後の行または列に沿ってサンプリングされる)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//GL_TEXTURE_WRAP_T(t軸サラウンド)、GL_CLAMP_TO_EDGE(サラウンドモードでは、範囲外のテクスチャ座標は、法的なテクスチャユニットの最後の行または列に沿ってサンプリングされる)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
//テクスチャを読み込む
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iHeigth, iHeigth, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
//テクスチャオブジェクトのミップマップ一式を生成する glGenerateMipmap
glGenerateMipmap(GL_TEXTURE_2D);
//元のテクスチャデータを解放し、テクスチャオリジナルデータをもう必要としない
free(pBytes);
}
座標の決定
床の座標を例にします。床の頂点の座標は、GL_TRIANGLE_STRIPで三角形の形で描画され、2つの三角形は正方形を形成することができ、対応するテクスチャ座標は下図のように決定されます。
//ジオメトリの頂点を設定する
GLfloat z, x=10, y=10;
floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
//フロアzはトンネルの深さを示す
for (z=60; z>=0; z-=10) {
floorBatch.MultiTexCoord2f(0, 0.0, 0.0);
floorBatch.Vertex3f(-x, -y, z);
floorBatch.MultiTexCoord2f(0, 1.0, 0);
floorBatch.Vertex3f(x, -y, z);
floorBatch.MultiTexCoord2f(0, 0, 1.0);
floorBatch.Vertex3f(-x, -y, z-10);
floorBatch.MultiTexCoord2f(0, 1.0, 1.0);
floorBatch.Vertex3f(x, -y, z-10);
}
floorBatch.End();
残りの座標は、上記の設定を参照して決定することができます。
描画
描画は比較的簡単で、まず対応するテクスチャオブジェクトをバインドします。
modelViewMatrix.PushMatrix();
modelViewMatrix.Translate(0, 0, viewZ);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
floorBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
rightBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
ceilingBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
コードを実行すれば、望みの効果が得られます。
レンズの動き
上記は静的な効果しか表示できず、動かすことはできないので、特殊なキーメソッドにレスポンスを追加します。カメラを動かす最終的な効果は、上記の動画の効果と同じになります。
//矢印キーに反応してビューポートを前後に動かす
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP) {
viewZ += 0.5f;
}
if (key == GLUT_KEY_DOWN) {
viewZ -= 0.5f;
}
glutPostRedisplay();
}
いくつかの効果を比較
最後に、右クリックリストを追加して、異なるパラメータを設定し、異なるパラメータ設定の異なる効果を比較することもできます。メニューエントリを追加します:
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("GL_NEAREST", 0);
glutAddMenuEntry("GL_LINEAR", 1);
glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST", 2);
glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
glutAddMenuEntry("Anisotropic Filter", 6);
glutAddMenuEntry("Anisotropic Off", 7);
glutAttachMenu(GLUT_RIGHT_BUTTON);
イベント処理:
//メニューバーの選択
void ProcessMenu(int value)
{
GLuint iLoop;
for (iLoop = 0; iLoop<TEXTURE_COUNT; iLoop++) {
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
switch (value) {
case 0:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
break;
case 1:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
break;
case 2:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
break;
case 3:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
break;
case 4:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
case 5:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
case 6:
GLfloat fLargest;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
default:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
break;
}
}
glutPostRedisplay();
}





