一、纹理绘制
这里简单的使用纹理来绘制一个通道的界面:
这个界面可以简单的分为四个部分:上下左右四个墙面。经过前面的学习知道每一个面其实都是由许多个三角形构成。
例如地板的绘制:
它就是由多个三角形组合成一个梯形图像。
按照上面的示例来看,一共需要三个纹理:天花板、地板、墙壁(左右墙壁纹理一致为同一个)
来创建三个宏定义、存放纹理的数组以及纹理文件名字的数组:
#define TEXTURE_BRICK 0 //墙面
#define TEXTURE_FLOOT 1 //地板
#define TEXTURE_CEILING 2 //天花板
#define TEXTURE_COUNT 3 //纹理个数
GLuint textures[TEXTURE_COUNT];//纹理数组
//文件tag名字数组
const char *szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
//4个批次容器类
GLBatch floorBatch;//地面
GLBatch ceilingBatch;//天花板
GLBatch leftWallBatch;//左墙面
GLBatch rightWallBatch;//右墙面
1.1、纹理相关设置
根据前文得知, 设置纹理步骤为:
- 生成纹理标记
- 加载纹理文件
- 设置纹理参数(过滤、环绕等)
- 纹理载入
这里由于需要三个纹理,直接使用for循环来生成相关纹理并进行设置:
//加载纹理
GLbyte *pBytes;
GLint iWidth, iHeigth, iComponents;
GLenum eFormat;
GLint iLoop;
//生成纹理标记
glGenTextures(TEXTURE_COUNT, textures);
//循环生成纹理数组参数
for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++) {
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
//加载TGA文件
pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeigth, &iComponents, &eFormat);
//纹理参数 -- 放大/缩小过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//放大过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//缩小过滤方式
//纹理参数 -- 环绕
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//纹理载入
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeigth, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
//纹理维度
glGenerateMipmap(GL_TEXTURE_2D);
free(pBytes);
}
1.2、顶点设置
这里需要生成4组顶点数据,分别在4个批次类上:
//设置几何图形顶点/纹理坐标(上.下.左.右)
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();
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();
1.3、纹理绘制
纹理绘制与前文图元绘制流程大致相似,但是这里也稍微有一些改变:
- 视图模型矩阵压栈
- 使用纹理替换矩阵着色器
- 绑定纹理
- 批次类绘制
这里左右纹理为同一个纹理,所以只需要绑定一次后进行左右的批次类绘制即可。
//调用,绘制场景
void RenderScene(void)
{
//用当前清除色,清除窗口
glClear(GL_COLOR_BUFFER_BIT);
//模型视图压栈
modelViewMatrix.PushMatrix();
//Z轴平移viewZ 距离
modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
//纹理替换矩阵着色器
/*
参数1:GLT_SHADER_TEXTURE_REPLACE(着色器标签)
参数2:模型视图投影矩阵
参数3:纹理层
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);
//绑定纹理
/*
参数1:纹理模式,GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
参数2:需要绑定的纹理
*/
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();
//pop
modelViewMatrix.PopMatrix();
//缓存区交换
glutSwapBuffers();
}
运行程序就可以得到想要开头看到的效果