美文网首页
OpenGL纹理案例-隧道

OpenGL纹理案例-隧道

作者: 逃避不面对 | 来源:发表于2020-07-27 14:16 被阅读0次

使用OpenGL常用的API,绘制一个简单的隧道模型并贴图。最终下过如下:

完成代码:

#include "GLTools.h"

#include "GLShaderManager.h"

#include "GLFrustum.h"

#include "GLBatch.h"

#include "GLFrame.h"

#include "GLMatrixStack.h"

#include "GLGeometryTransform.h"

#ifdef __APPLE__

#include <glut/glut.h>

#else

#define FREEGLUT_STATIC

#include <GL/glut.h>

#endif

GLShaderManager    shaderManager;          //着色器管理器

GLMatrixStack      modelViewMatrix;        //模型视图矩阵

GLMatrixStack      projectionMatrix;      //投影矩阵

GLFrustum          viewFrustum;            //视景体

GLGeometryTransform transformPipeline;      //几何变换管线

//4个批次容器类

GLBatch            floorBatch;//地面

GLBatch            ceilingBatch;//天花板

GLBatch            leftWallBatch;//左墙面

GLBatch            rightWallBatch;//右墙面

//深度初始值,-65。

GLfloat            viewZ = -60.0f;

// 纹理标识符号

#define TEXTURE_BRICK  0 //墙面

#define TEXTURE_FLOOR  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" };

//菜单栏选择

void ProcessMenu(int value)

{

    GLint i ;

    for (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:

                      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

                      break;

                  case 3:

                      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);

                      break;

                  case 4:

                      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

                      break;

                  case 5:

                      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 SetupRC()

{

    glClearColor(0, 0, 0, 1);

    shaderManager.InitializeStockShaders();

    GLbyte * byte;

    GLint i, width, height, iComponent;

    GLenum eFormat;

    glGenTextures(TEXTURE_COUNT, textures);

    for (i = 0; i<TEXTURE_COUNT; i++) {

        glBindTexture(GL_TEXTURE_2D, textures[i]);

        byte = gltReadTGABits(szTextureFiles[i], &width, &height, &iComponent, &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, iComponent, width, height, 0, eFormat, GL_UNSIGNED_BYTE, byte);

        glGenerateMipmap(GL_TEXTURE_2D);

        free(byte);

    }

    GLfloat z;

    floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);

    for (z = 60.0f; z >= 0.0f; z-= 10.0f) {

        floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

        floorBatch.Vertex3f(-10.0f, -10.0f, z);

        floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

        floorBatch.Vertex3f(10.0f, -10.0f, z);

        floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

        floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);

        floorBatch.MultiTexCoord2f(0, 0.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, 0.0f);

        ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);

        ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

        ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);

        ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

        ceilingBatch.Vertex3f(-10.0f, 10.0f, z);

        ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.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, 1.0f, 0.0f);

        leftWallBatch.Vertex3f(-10.0f, -10.0f, z);

        leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

        leftWallBatch.Vertex3f(-10.0f, 10.0f, z);

        leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

        leftWallBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);

        leftWallBatch.MultiTexCoord2f(0, 0.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, 1.0f, 0.0f);

        rightWallBatch.Vertex3f(10.0f, -10.0f, z);

        rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

        rightWallBatch.Vertex3f(10.0f, 10.0f, z);

        rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

        rightWallBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);

        rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);

        rightWallBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);

    }

    rightWallBatch.End();

}

//关闭渲染环境

void ShutdownRC(void)

{

    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 ChangeSize(int w, int h)

{

    if (h == 0) h = 1;

    glViewport(0, 0, w, h);

    viewFrustum.SetPerspective(80, float(w)/float(h), 1, 120);

    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

//调用,绘制场景

void RenderScene(void)

{

    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();

}

int main(int argc, char *argv[])

{

    gltSetWorkingDirectory(argv[0]);

    // 标准初始化

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

    glutInitWindowSize(800, 600);

    glutCreateWindow("Tunnel");

    glutReshapeFunc(ChangeSize);

    glutSpecialFunc(SpecialKeys);

    glutDisplayFunc(RenderScene);

    // 添加菜单入口,改变过滤器

    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));

        return 1;

    }

    // 启动循环,关闭纹理

    SetupRC();

    glutMainLoop();

    ShutdownRC();

    return 0;

}

纹理坐标对应关系如下:


总结:

1.读取的纹理可以翻转使用,正反面都可以用来填充。

2.绘制流程:指定生成纹理ID的数量和数组 —>绑定纹理ID—>读取.tga文件载入纹理 —>设置过滤方式和环绕 —> 设置纹理和顶点对应关系 —> 绑定相应的纹理并用对应的批次类绘制

3.修改纹理环绕过滤方式前,也需要绑定纹理ID

参考链接

相关文章

  • OpenGL 纹理隧道案例

    隧道示例程序使用了和纹理有关的内容,并在视觉上显示了不同的过滤器和贴图模式。 该示例程序在启动时加载3个纹理用于对...

  • OpenGL 纹理案例-隧道

    在学习了纹理之后,我们尝试着用纹理来实现一个类似于下图这样的隧道效果,并且让他可以通过键盘的上下键可以来进行前进和...

  • OpenGL纹理案例-隧道

    使用OpenGL常用的API,绘制一个简单的隧道模型并贴图。最终下过如下: 完成代码: #include "GLT...

  • OpenGL纹理案例-隧道

    OpenGL纹理案例-隧道 之前我写过一些关于纹理的一些基本API和API的方法参数的解释,现在我们来弄一个隧道案...

  • OpenGL纹理坐标&&隧道案例(二)

    一.隧道案例效果 二.纹理坐标 纹理坐标主要是把图形映射到OpenGL中去,图形中每个顶点关联到对应的纹理坐标下,...

  • OpenGL纹理MipMap和隧道案例

    开场白 本文介绍一下纹理的mip映射以及用一个隧道案例来展示不同mip过滤模式的效果。 MipMap简介一下 Mi...

  • 八:OpenGL纹理(中):隧道案例

    前言: 上节为大家介绍了一个金字塔的原型,接下来为大家来实现一个更加复杂的案例吧,本节为大家介绍一个“隧道穿行”,...

  • OpenGL:纹理隧道

    本案例主要目的多个纹理如何使用,加深对纹理的使用的理解。 整体的案例效果如图所示 下面接着说说隧道的绘制过程,整体...

  • 案例08:隧道

    OpenGL + OpenGL ES +Metal 系列文章汇总 本案例主要目的多个纹理如何使用,加深对纹理的使用...

  • 案例分析4:纹理隧道

    本案例主要目的多个纹理如何使用,加深对纹理的使用的理解。案例效果如下 对应代码地址纹理隧道。 下面接着说说隧道的绘...

网友评论

      本文标题:OpenGL纹理案例-隧道

      本文链接:https://www.haomeiwen.com/subject/itezlktx.html