OpenGL 纹理隧道案例

2020-07-23  本文已影响0人  _涼城

隧道示例程序使用了和纹理有关的内容,并在视觉上显示了不同的过滤器和贴图模式。

该示例程序在启动时加载3个纹理用于对一个隧道进行渲染。

声明变量与定义宏

首先为3个纹理对象创建标识符。textures数组将包含3个整数,通过宏TEXTURE_BRICKTEXTURE_FLOORTEXTURE_CEILING访问,以及数量宏TEXTURE_COUNT,并且创建一个名称数组szTextureFiles

// 纹理标识符号
#define TEXTURE_BRICK   0 //墙面
#define TEXTURE_FLOOR   1 //地板
#define TEXTURE_CEILING 2 //纹理天花板
#define TEXTURE_COUNT   3 //纹理个数
GLuint textures[TEXTURE_COUNT];
const char *szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
初始化纹理对象

纹理对象是在SetupRC函数中配置的

glGenTextures(TEXTURE_COUNT,textures);

然后是一个简单循环,依次绑定每一个纹理对象,并设置纹理对象的参数。

GLbyte *pBytes;
GLint iWidth,iHeight,iComponents;
GLenum eFormat;
GLint iLoop;

for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++) {
    glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

    pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponents, &eFormat);
    //纹理参数-邻近过滤
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    //环绕方式
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
    //载入纹理
    glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
    //生成Mip贴图
    glGenerateMipmap(GL_TEXTURE_2D);
    //释放
    free(pBytes);
}
设置顶点数据

隧道地板顶点设置

GLfloat z;
//隧道顶点设置
floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
//Z表示深度,隧道的深度
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();
渲染纹理
渲染是在RenderScene函数中完成的。

清空颜色、模型视图矩阵Z轴平移、着色器

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix();
modelViewMatrix.Translate(0, 0, 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();
键盘控制移动

通过修改平移z轴坐标控制前进、后退。

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();
}
切换过滤器
创建过滤器切换菜单
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);
切换过滤器处理
void ProcessMenu(int value)
{
    GLint iLoop;

    for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
    {
        /**绑定纹理 glBindTexture
         参数1:GL_TEXTURE_2D
         参数2:需要绑定的纹理对象
         */
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

        /**配置纹理参数 glTexParameteri
         参数1:纹理模式
         参数2:纹理参数
         参数3:特定纹理参数

         */
        switch(value)
        {
            case 0:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_NEAREST(最邻近过滤)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                break;

            case 1:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_LINEAR(线性过滤)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                break;

            case 2:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_NEAREST_MIPMAP_NEAREST(选择最邻近的Mip层,并执行最邻近过滤)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
                break;

            case 3:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_NEAREST_MIPMAP_LINEAR(在Mip层之间执行线性插补,并执行最邻近过滤)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
                break;

            case 4:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_NEAREST_MIPMAP_LINEAR(选择最邻近Mip层,并执行线性过滤)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
                break;

            case 5:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_LINEAR_MIPMAP_LINEAR(在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;

        }
    }

    //触发重画
    glutPostRedisplay();
}
删除纹理标识符
//关闭渲染环境
void ShutdownRC(void)
{
    //删除纹理
    glDeleteTextures(TEXTURE_COUNT, textures);
}
上一篇 下一篇

猜你喜欢

热点阅读