如何使用OpenGL绘制如下的隧道效果???

#include "GLTools.h"
#include <GLUT/GLUT.h>
#include "GLShaderManager.h"
#include "GLFrustum.h"
#include "GLMatrixStack.h"
#include "GLGeometryTransform.h"
#define TEXTURE_BRICK 0//墙面
#define TEXTURE_FLOOR 1//地板
#define TEXTURE_CEILING 2 //天花板
#define TEXTURE_COUNT 3 //纹理数量
GLuint textures[TEXTURE_COUNT];//纹理标记数组
//投影方式
GLFrustum viewFrustum;
//投影矩阵
GLMatrixStack projectionMatrix;
//变换管道
GLGeometryTransform transformPipeline;
//模型视图矩阵
GLMatrixStack modelViewMatrix;
//深度初始值
GLfloat viewZ = -65.0f;
//固定着色器管理者
GLShaderManager shaderManager;
GLBatch floorBatch;//地面
GLBatch ceilingBatch;//天花板
GLBatch leftWallBatch;//左墙面
GLBatch rightWallBatch;//右墙面
const char *szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
void ChangeSize(int w,int h){
//设置窗口大小
glViewport(0, 0, w, h);
GLfloat fAspect = (GLfloat)w/(GLfloat)h;
//设置投影方式
viewFrustum.SetPerspective(80.0f, fAspect, 1.0f, 120.0f);
//将投影方式载入投影矩阵
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//将模型视图矩阵和投影矩阵载入变换管道
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
void RenderScene(){
glClear(GL_COLOR_BUFFER_BIT);
//模型视图压栈
modelViewMatrix.PushMatrix();
//z轴平移一定距离
modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
//纹理替换矩阵着色器
/*
参数一:GLT_SHADER_TEXTURE_REPLACE着色器类型
参数二:模型视图投影矩阵
参数三:纹理层
*/ 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();
}
void SetupRC(){
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
//分配纹理对象
glGenTextures(TEXTURE_COUNT, textures);
//定义一些变量,来接收纹理数据信息
GLbyte *pBytes;
GLint iWidth,iHeight,iComponents;
GLenum eFormat;
GLint iLoop;
for (iLoop = 0; iLoop<TEXTURE_COUNT; iLoop++) {
//绑定纹理
/*
参数一:纹理模式GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D,
参数二:需要绑定的纹理对象
*/
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
//加载tga文件
/*
参数一:文件名称
参数二:接收图片的宽
参数三:接收图片的高
参数四:接收图片组件
参数五:接收文件格式
返回值:pBytes指向图像数据的指针
*/
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_LINEAR);
//设置环绕方式
///S(X)轴方向采用拉伸边缘的环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//T(Y)轴方向采用拉伸边缘的环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//载入纹理
/*
参数一:纹理模式
参数二:mip贴图层次
参数三:纹理颜色
参数四:宽度
参数五:高度
参数六:深度
参数七:像素的数据类型,一般用GL_UNSIGNED_BYTE,表示无符号整型
参数八:指向纹理数据的指针
*/
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
//生成纹理贴图
glGenerateMipmap(GL_TEXTURE_2D);
//释放
free(pBytes);
}
//设置顶点数据
GLfloat z;//z表示深度
/*
参数一:图元装配方式
参数二:顶点数
参数三:纹理坐标
*/
floorBatch.Begin(GL_TRIANGLE_STRIP, 28,1);
for (z = 60.0f; z>=0.0f; z -= 10.0f) {
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
}
floorBatch.End();
//参考PPT图6-11
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();
//参考PPT图6-12
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();
//参考PPT图6-13
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();
}
void shutdownRC(){
glDeleteTextures(TEXTURE_COUNT, textures);
}
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();
}
void ProcessMenu(int value){
for (int i=0; i<TEXTURE_COUNT; i++) {
//绑定纹理
glBindTexture(GL_TEXTURE_2D, textures[i]);
//设置纹理参数
switch (value) {
case 0:
{
//缩小,邻近过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
break;
case 1:
{
//缩小,线性过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
break;
case 2:
{
//缩小,选择最邻近的Mip层,并执行最邻近过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
break;
case 3:
{
//缩小,在Mip层之间执行线性插补,并执行邻近过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
}
break;
case 4:
{
//缩小,选择最邻近Mip层,并执行线性过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
}
break;
case 5:
{
//缩小,在Mip层之间执行线性插补,并执行线性过滤,又称为三线性过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
break;
case 6:
{
//设置各向异性过滤
GLfloat fLargest;
//获取各向异性过滤的最大数量
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
//设置纹理参数
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
}
break;
case 7:
{
//设置各向同性过滤,数量为1.0表示各向同性采样
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
break;
default:
break;
}
}
//
glutPostRedisplay();
}
int main(int argc, char *argv[]){
gltSetWorkingDirectory(argv[0]);
//
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
//
glutInitWindowSize(800, 600);
glutCreateWindow("Tunnel");
//
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
//添加菜单入口
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);
//
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error:%s\n",glewGetErrorString(err));
}
SetupRC();
glutMainLoop();
//删除纹理
shutdownRC();
return 0;
}