我們先來看看具體效果
運(yùn)行效果
setupRC
函數(shù)
該函數(shù)主要是數(shù)據(jù)初始化,包括頂點(diǎn)纫溃、紋理等腰涧。
// 初始化
glClearColor(0.0, 0.0, 0.0, 1.0);
shaderManager.InitializeStockShaders();
// 開啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// 大球數(shù)據(jù)
gltMakeSphere(toursBatch, 0.4, 40, 80);
// 小球數(shù)據(jù)
gltMakeSphere(sphereBatch, 0.1, 26, 13);
//6.設(shè)置地板頂點(diǎn)數(shù)據(jù)&地板紋理(4個(gè)頂點(diǎn))
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();
//6. 隨機(jī)位置放置小球球
for (int i = 0; i < NUM_SPHERES; i++) {
//y軸不變,X,Z產(chǎn)生隨機(jī)值
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
//在y方向紊浩,將球體設(shè)置為0.0的位置窖铡,這使得它們看起來是飄浮在眼睛的高度
//對(duì)spheres數(shù)組中的每一個(gè)頂點(diǎn),設(shè)置頂點(diǎn)數(shù)據(jù)
spheres[i].SetOrigin(x, 0.0f, z);
}
// 分配紋理對(duì)象
glGenTextures(3, uiTextures);
// 綁定紋理
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);
由于使用了3種紋理坊谁,因此傳入的紋理個(gè)數(shù)為3费彼,并傳入紋理數(shù)組
glGenTextures(3, uiTextures);
loadTGATexture
函數(shù)
主要是將TGA文件從內(nèi)存中讀取出來,加載為2D紋理數(shù)據(jù)口芍。
大致步驟:
- 讀取紋理 -- gltReadTGABits
- 設(shè)置紋理參數(shù)(S和T的環(huán)繞模式箍铲、放大/縮小的過濾方式) -- glTexParameteri
- 載入紋理 -- glTexImage2D
- 釋放
- 加載Mip
// 讀取TGA紋理數(shù)據(jù)
bool loadTGATexture(const char *fileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) {
GLbyte *pBits;
int nWidth;
int nHeight;
int nComponents;
GLenum eFormat;
// 讀取紋理數(shù)據(jù)
pBits = gltReadTGABits(fileName, &nWidth, &nHeight, &nComponents, &eFormat);
if (pBits == NULL) {
return false;
}
// 設(shè)置紋理參數(shù)
// 參數(shù)1:紋理維度
// 參數(shù)2:為S/T坐標(biāo)設(shè)置模式
// 參數(shù)3:環(huán)繞模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
// 參數(shù)1:紋理維度
// 參數(shù)2:線性過濾
// 參數(shù)3:環(huán)繞模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
// 載入紋理
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
// 釋放
free(pBits);
//
if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST) {
glGenerateMipmap(GL_TEXTURE_2D);
}
return true;
}
renderScene
函數(shù)
主要是做繪制的工作。
流程如下:
image.png
// 繪制
void renderScene() {
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds() * 60.0;
// 清除顏色緩沖區(qū)和深度緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 壓棧
modelViewMatrix.PushMatrix();
// 觀察者
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
// 綁定地面紋理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
// 畫地板
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor, 0);
floorBatch.Draw();
drawSomething(yRot);
modelViewMatrix.PopMatrix(); // 出棧
glutSwapBuffers();
glutPostRedisplay();
}
drawSomething
函數(shù)
主要是對(duì)大球鬓椭,小球繪制的封裝虹钮。
包含以下4部分操作:
- 初始化:光源位置和漫反射顏色
- 繪制多個(gè)靜態(tài)小球
- 繪制大球
- 繪制公轉(zhuǎn)小球
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};
// 繪制懸浮小球
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();
}
// 繪制大球
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);
toursBatch.Draw();
modelViewMatrix.PopMatrix();
// 繪制公轉(zhuǎn)小球(公轉(zhuǎn)自轉(zhuǎn))
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();
}