这个案例主要是用多个纹理去绘制一个隧道
效果如下图:

相关的函数介绍:
- setUpRC:初始化渲染环境,生成纹理对象,设置顶点及纹理坐标
- changeSize:当视口的大小改变时,此函数会被回调,只要用来重设视口大小,以及设置投影方式
- SpecialKeys:当键盘被点击后,会回调此方法
- shutDownRC:删除纹理,绘制结束后没需要将纹理删除,否则纹理数据会存在缓冲区,对其他绘制造成干扰
- RenderScene:绘制方法,使用对应的着色器绘制纹理
setUpRC
设置背景颜色,以及初始化着色器管理类
//设置背景颜色为黑色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//初始化着色器管理类
shaderManager.InitializeStockShaders();
生成纹理标记并设置纹理参数(过滤方式,环绕方式)
GLbyte * pBytes;
GLint iWidth,iHeight,iComponets;
GLenum eFormet;
GLint iLoop;
//3.生成纹理标记,执行结束后 textures 会填充为纹理id
/** 分配纹理对象 glGenTextures
参数1:纹理对象的数量
参数2:纹理对象标识数组
*/
glGenTextures(TEXTURE_COUNT, textures);
//循环设置纹理参数,因为有三个纹理,所以这里采用循环去设置
for(iLoop = 0;iLoop < TEXTURE_COUNT;iLoop++)
{
//绑定纹理对象
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
//加载tga文件,加载完成后 iWidth,iHeight,iComponets 等参数都会被填充为本tga文件的属性
pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponets, &eFormet);
//设置纹理放大缩小时的过滤方式为邻近过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//设置纹理在s轴的环绕方式为 GL_CLAMP_TO_EDGE
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//设置纹理在T轴的环绕方式为 GL_CLAMP_TO_EDGE
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/**载入纹理 glTexImage2D
参数1:纹理维度,GL_TEXTURE_2D
参数2:mip贴图层次
参数3:纹理单元存储的颜色成分(从读取像素图中获得)
参数4:加载纹理宽度
参数5:加载纹理的高度
参数6:加载纹理的深度
参数7:像素数据的数据类型,GL_UNSIGNED_BYTE无符号整型
参数8:指向纹理图像数据的指针
*/
glTexImage2D(GL_TEXTURE_2D, 0, iComponets, iWidth, iHeight, 0, eFormet, GL_UNSIGNED_BYTE, pBytes);
/**为纹理对象生成一组完整的mipmap glGenerateMipmap
参数1:纹理维度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
*/
glGenerateMipmap(GL_TEXTURE_2D);
//释放原始纹理数据,不在需要纹理原始数据了
free(pBytes);
}
设置纹理的映射关系,这里有三个纹理,四个面
//纹理当前的z坐标
GLfloat z;
/*
GLTools库中的容器类,GBatch,
void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
参数1:图元枚举值
参数2:顶点数
参数3:1组或者2组纹理坐标
*/
floorBatch.Begin(GL_TRIANGLE_STRIP, 28,1);
for(z = 60;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();
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();
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();
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();
changeSize
void changeSize(int width,int height)
{
if(height == 0)
height = 1;
//重新设置视口大小
glViewport(0, 0, width, height);
GLfloat factor = (GLfloat)width/(GLfloat)height;
viewFrustum.SetPerspective(80.0f, factor, 1.0, 120.0);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}
SpecialKeys
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();
}
shutDownRC
void shutDownRC()
{
//删除纹理,本次绘制结束后,需要删除纹理,否则会影响其他绘制
glDeleteTextures(TEXTURE_COUNT, textures);
}
RenderScene
void RenderScene()
{
//清除颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
//模型视图矩阵压栈
modelViewMatrix.PushMatrix();
//z轴平移viewZ距离
modelViewMatrix.Translate(0.0f, 0.0f, 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_CEILING]);
ceilingBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();
rightWallBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
}
完整代码在这里:OpenGL Tunel
网友评论