繪制一個隧道
定義繪制批次類
GLShaderManager shaderManager; //著色器管理器
GLMatrixStack modelViewMatrix; //模型視圖矩陣
GLMatrixStack projectionMatrix; //投影矩陣
GLFrustum viewFrustum; //視景體
GLGeometryTransform transformPipeline; //幾何變換管線
//4個批次容器類
GLBatch floorBatch;//地面
GLBatch ceilingBatch;//天花板
GLBatch leftWallBatch;//左墻面
GLBatch rightWallBatch;//右墻面
//深度初始值,-65。
GLfloat viewZ = -65.0f;
// 紋理標識符號
#define TEXTURE_BRICK 0 //墻面
#define TEXTURE_FLOOR 1 //地板
#define TEXTURE_CEILING 2 //紋理天花板
#define TEXTURE_COUNT 3 //紋理個數(shù)
GLuint textures[TEXTURE_COUNT];//紋理標記數(shù)組
//文件tag名字數(shù)組
const char *szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
初始化

floor.png

ceiling.png

leftWall.png

rightWall.png
//在這個函數(shù)里能夠在渲染環(huán)境中進行任何需要的初始化,它這里的設(shè)置并初始化紋理對象
void SetupRC()
{
GLbyte *pBytes;
GLint iWidth,iHeight,iComponents;
GLenum eFormat;
GLint iLoop;
//背景
glClearColor(0.0f, 0.0f, 0.0f,1.0f);
shaderManager.InitializeStockShaders();
//1.加載紋理
/*
glGenTextures (GLsizei n, GLuint *textures)
參數(shù)1:n,紋理數(shù)量
參數(shù)2:textures,紋理對象標識數(shù)組
*/
glGenTextures(TEXTURE_COUNT, textures);
for (iLoop =0; iLoop < TEXTURE_COUNT; iLoop++) {
//2.綁定紋理
/*
glBindTexture (GLenum target, GLuint texture);
參數(shù)1:target,使用的紋理類型GL_TEXTURE_1D\GL_TEXTURE_2D\GL_TEXTURE_3D
參數(shù)2:texture,紋理的標記
*/
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
//3.加載tga文件
/*
GLbyte *gltReadTGABits(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat, GLbyte *pData);
參數(shù)1:szFileName 紋理文件的名稱
參數(shù)2:iWidth 獲取紋理文件的寬度
參數(shù)3:iHeight獲取紋理文件的高度
參數(shù)4:iComponents獲取紋理文件的組件
參數(shù)5:eFormat獲取紋理文件的格式
返回值:指向圖像數(shù)據(jù)的指針
*/
pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponents, &eFormat);
//放大過濾器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//縮小過濾器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//環(huán)繞方式--S
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//環(huán)繞方式--T
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//載入紋理
/*
glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
參數(shù)1:target,使用的紋理類型GL_TEXTURE_1D\GL_TEXTURE_2D\GL_TEXTURE_3D
參數(shù)2:level ,Mip貼圖的層次
參數(shù)3:internalformat,紋理單元的顏色組成方式(從讀取像素圖中獲得)
參數(shù)4:width
參數(shù)5:height
參數(shù)6:border
參數(shù)7:format
參數(shù)8:type,像素數(shù)據(jù)的數(shù)據(jù)類型-GL_UNSIGNED_BYTE
參數(shù)9:pixels,指向紋理圖像數(shù)據(jù)的指針
*/
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
//生成MIP圖層
/*
參數(shù)1:GL_TEXTURE_1D\GL_TEXTURE_2D\GL_TEXTURE_3D
*/
glGenerateMipmap(GL_TEXTURE_2D);
free(pBytes);
}
//建立立體圖像!!!
GLfloat z;
/*
void Begin(GLenum primitive, GLuint nVerts, GLuint nTextureUnits = 0);
參數(shù)1:繪圖模式
參數(shù)2:頂點個數(shù)
參數(shù)3:紋理,默認等于0
*/
floorBatch.Begin(GL_TRIANGLE_STRIP, 28,1);//共繪制了7個四邊形, 共28個頂點
//參考圖 - floor.png
for (z = 60.0f; z >= 0.0f; z -= 10.0f) {
//指定頂點對應(yīng)紋理的坐標
floorBatch.MultiTexCoord2f(0, 0, 0);
//指定左下角頂點
floorBatch.Vertex3f(-10.0f, -10.0f, z);
//指定右下角頂點以及紋理坐標
floorBatch.MultiTexCoord2f(0, 1, 0);
floorBatch.Vertex3f(10.0f, -10.0f, z);
//指定頂點對應(yīng)紋理的坐標
floorBatch.MultiTexCoord2f(0, 0, 1.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z-10.0f);
//指定頂點對應(yīng)紋理的坐標
floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z-10.0f);
}
floorBatch.End();
//參考圖- ceiling.png
ceilingBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for(z = 60.0f; z >= 0.0f; z -=10.0f)
{
ceilingBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
ceilingBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
ceilingBatch.Vertex3f(-10.0f, 10.0f, z);
ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
ceilingBatch.Vertex3f(10.0f, 10.0f, z);
}
ceilingBatch.End();
//參考圖 - leftWall.png
leftWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for(z = 60.0f; z >= 0.0f; z -=10.0f)
{
leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
leftWallBatch.Vertex3f(-10.0f, -10.0f, z);
leftWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
leftWallBatch.Vertex3f(-10.0f, 10.0f, z);
leftWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
leftWallBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
leftWallBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
}
leftWallBatch.End();
//參考圖 - rightWall.png
rightWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for(z = 60.0f; z >= 0.0f; z -=10.0f)
{
rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
rightWallBatch.Vertex3f(10.0f, -10.0f, z);
rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
rightWallBatch.Vertex3f(10.0f, 10.0f, z);
rightWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
rightWallBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
rightWallBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
}
rightWallBatch.End();
}
窗口設(shè)置
//改變視景體和視口,在改變窗口大小或初始化窗口調(diào)用
void ChangeSize(int w, int h)
{
if (h == 0) {
h = 1;
}
glViewport(0, 0, w, h);
//透視投影縱橫比
GLfloat fAspect;
fAspect = (GLfloat)w / (GLfloat)h;
//設(shè)置透視投影
viewFrustum.SetPerspective(80.0f, fAspect, 1.0, 120.0);
//獲取到投影矩陣
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//通過變換管線來管理投影矩陣堆棧
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
調(diào)用,繪制場景
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
modelViewMatrix.PushMatrix();
modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
//紋理替換矩陣著色器
/*
參數(shù)1:GLT_SHADER_TEXTURE_REPLACE
參數(shù)2:模型視圖矩陣 & 投影矩陣
參數(shù)3:紋理層次
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
//地板
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
floorBatch.Draw();
//天花板
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
ceilingBatch.Draw();
//左右墻壁
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();
rightWallBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
}
效果圖

image.png