球の世界の場合に基づいています:テクスチャとイメージ表示の追加に基づいて小さなボールの回転の大きなボールの回転は、図に示すような効果を達成するために、遊びやより面白い:
ケース実現のフローチャート:
関数の説明
メイン関数の分析
SetupRC
この関数は、主に頂点やテクスチャなどのデータを初期化するためのものです。
loadTGATexture
主な処理としては、以下のようにメモリからTGAファイルを読み込み、2Dテクスチャデータとして読み込みます:
drawSomething
RenderScene
ケースコード:
ヘッダーファイルの導入
#include "GLTools.h"
#include "GLShaderManager.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLMatrixStack.h"
#include "GLGeometryTransform.h"
#include "StopWatch.h"
#include <math.h>
#include <stdio.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
グローバル変数の宣言
//**追加のランダムボールを追加する
#define NUM_SPHERES 50
GLFrame spheres[NUM_SPHERES];
GLShaderManager shaderManager; // シェーダマネージャ
GLMatrixStack modelViewMatrix; // モデルビュー行列
GLMatrixStack projectionMatrix; // 投影行列
GLFrustum viewFrustum; //
GLGeometryTransform transformPipeline; // ジオメトリ変換パイプライン
GLTriangleBatch torusBatch; // フラワーブラケットバッチ
GLBatch floorBatch; // フロアバッチ
//**メトリック球のバッチを定義する**
GLTriangleBatch sphereBatch; //球バッチ
//**キャラクターフレーム カメラキャラクターフレーム
GLFrame cameraFrame;
//**テクスチャを追加する
//テクスチャマーカーの配列
GLuint uiTextures[3];
実装機能
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) {
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;
//1.テクスチャデータを読み込む
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if(pBits == NULL)
return false;
//テクスチャパラメータを設定する
//パラメータ1:テクスチャの寸法
//パラメータ2:S / T座標のモードを設定する。
//パラメータ3:wrapMode。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
//パラメータ1:テクスチャの寸法
//パラメータ2:リニアフィルタ
//パラメータ3:wrapMode。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
//3.テクスチャをロードする
//パラメータ1:テクスチャの寸法
//パラメータ2:ミップマッピングレベル
//パラメータ3:テクスチャユニットに格納されているカラーコンポーネント - ユニバーサル圧縮テクスチャフォーマットGLに内部パラメータnComponentsを変更した_COMPRESSED_RGB
//パラメータ4:テクスチャ幅をロードする
//パラメータ5:テクスチャの高さをロードする
//パラメータ6:ロードされたテクスチャの深さ
//パラメータ7:ピクセルデータ(GL)のデータ型_UNSIGNED_BYTE,(各色成分は、8ビットの符号なし整数である)
//パラメータ8:テクスチャイメージデータへのポインタ。
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits);
//使用後にpBitsを解放する
free(pBits);
//Mipマップは、minFilterが次の4つのモードに等しい場合にのみ生成することができる
//GL_NEAREST_MIPMAP_NEAREST非常に良いパフォーマンスと非常に低いちらつき。
//GL_LINEAR_MIPMAP_NEAREST多くの場合、ゲームを高速化するために使用される、それは高品質の線形フィルタを使用する
//GL_LINEAR_MIPMAP_LINEAR _NEAREST_MIPMAP_LINEAR フィルタは、Mipレイヤー間のフィルタトレースを除去するために、Mipレイヤー間でいくつかの追加補間を実行する。
//GL_LINEAR_MIPMAP_LINEAR トリリニアMipマッピング。最高の精度でテクスチャフィルタリングの黄金律。
if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
//4.ロードMipは、テクスチャは、すべてのMip層を生成する。
//パラメータ:GL_TEXTURE_1DGL_TEXTURE_2DGL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
void SetupRC() {
//1.カラーバッファにクリア画面の色を設定する
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//2.シェーダマネージャを初期化する
shaderManager.InitializeStockShaders();
//3.深さテスト/バックサイドカリングを有効にする
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
//4.大きな球体を設定する
gltMakeSphere(torusBatch, 0.4f, 40, 80);
//5.球体を設定する
gltMakeSphere(sphereBatch, 0.1f, 26, 13);
//6.床の頂点データを設定する&床のテクスチャ
GLfloat texSize = 10.0f;
floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-20.f, -0.41f, 20.0f);
floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
floorBatch.Vertex3f(20.0f, -0.41f, 20.f);
floorBatch.MultiTexCoord2f(0, texSize, texSize);
floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
floorBatch.End();
//7.ランダム球の頂点座標データ
for (int i = 0; i < NUM_SPHERES; i++) {
//y軸は変更せず、X,Zはランダムな値を生成する。
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
//Y方向に、球を0に設定する。.0これにより、目の高さに浮いているように見える。
//球の配列内の各頂点について、頂点データを設定する
spheres[i].SetOrigin(x, 0.0f, z);
}
//8.テクスチャオブジェクトに名前を付ける
glGenTextures(3, uiTextures);
//9.2DテクスチャとしてTGAファイルをロードする。
//パラメータ1:テクスチャファイル名
// &パラメータ3:縮小する必要がある&ズームフィルタ
//パラメータ4:テクスチャ座標サラウンドモード
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
}
//テクスチャを削除する
void ShutdownRC(void) {
glDeleteTextures(3, uiTextures);
}
// 画面のサイズ変更または初期化
void ChangeSize(int nWidth, int nHeight) {
//1.ビューポートを設定する
glViewport(0, 0, nWidth, nHeight);
//2.投影法を設定する
viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
//3.投影行列スタックに投影行列をロードする,
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
modelViewMatrix.LoadIdentity();
//4.パイプラインに投影行列スタックとモデルビュー行列オブジェクトを設定する
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
void drawSomething(GLfloat yRot)
{
//1.光源の位置を定義する&拡散色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
//2.ホバリング球体を描画する
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
for(int i = 0; i < NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
//3.大きな球体を描く
modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
torusBatch.Draw();
modelViewMatrix.PopMatrix();
//4.回転する球を描く(回転)
modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
//シーンを描画する呼び出しを行う
void RenderScene(void)
{
//1.床の色の値
static GLfloat vFloorColor[] = { 1.0f, 1.0f, 0.0f, 0.75f};
//2.時間ベースのアニメーション
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
//3.カラーバッファと深度バッファをクリアする
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//4.スタックに押す
modelViewMatrix.PushMatrix();
//5.オブザーバ行列を設定する
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
//6.スタック
modelViewMatrix.PushMatrix();
//7.---反射を追加する
//Y軸を反転させる
modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
//ミラーワールドは、一定の距離だけY軸周りに平行移動される。
modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
//8.前面として時計回りを指定する
glFrontFace(GL_CW);
//9.地面以外のものを描く
drawSomething(yRot);
//10.フロント反時計回りに戻す
glFrontFace(GL_CCW);
//11.ミラーを描画し、行列を復元する
modelViewMatrix.PopMatrix();
//12.ブレンド関数を有効にする
glEnable(GL_BLEND);
//13. glBlendFuncカラー混合式を指定する。
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//14.地面のテクスチャをバインドする
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
/*15.
テクスチャ調整シェーダ
パラメータ1:GLT_SHADER_TEXTURE_MODULATE
パラメータ2:モデルビューの投影行列
パラメータ3:色
パラメータ4:テクスチャユニット
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor,
0);
//shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
//描画を開始する
floorBatch.Draw();
//ブレンドをキャンセルする
glDisable(GL_BLEND);
//16.地面以外のものを描く
drawSomething(yRot);
//17.描画後、行列を復元する
modelViewMatrix.PopMatrix();
//18.バッファを交換する
glutSwapBuffers();
//19.再レンダリングに提出する
glutPostRedisplay();
}
//**3.矢印キーに応答するようにカメラのフレームを移動する。
void SpeacialKeys(int key,int x,int y)
{
float linear = 0.1f;
float angular = float(m3dDegToRad(5.0f));
if (key == GLUT_KEY_UP) {
//MoveForward
cameraFrame.MoveForward(linear);
}
if (key == GLUT_KEY_DOWN) {
cameraFrame.MoveForward(-linear);
}
if (key == GLUT_KEY_LEFT) {
//RotateWorld
cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
}
if (key == GLUT_KEY_RIGHT) {
cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
}
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800,600);
glutCreateWindow("OpenGL SphereWorld");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpeacialKeys);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s
", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}
添付デモアドレス:
08-OpenGL-Sphere Worlds





