美文网首页
案例2、 OpenGL隧道

案例2、 OpenGL隧道

作者: ChenL | 来源:发表于2020-07-22 15:08 被阅读0次

main:初始化入口
SetupRC:初始化背景色、着色器,生成纹理,并设置顶点及纹理坐标
ChangeSize:改变视景体和视口,在改变窗口大小或初始化窗口调用
RenderScene:清理缓存、绑定纹理并绘制隧道
ShutdownRC:关闭渲染环境
SpecialKeys:根据上下键位,记录前后移动的深度值,并重新渲染
ProcessMenu:根据选择的菜单选项,for循环更换所有纹理的过滤方式,并重新渲染

main函数
  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();
SetupRC函数

.初始化
.生成纹理
.设置隧道数据


1.png

生成纹理标记

    参数1:纹理对象的数量
    参数2:纹理对象标识数组
    glGenTextures(TEXTURE_COUNT, textures);

设置纹理参数

由于使用了多个纹理,每个纹理都需要设置参数,使用for循环
bind --> readTGA --> texParameter --> texImage --> generateMip --> free
1、绑定纹理对象
2、读取TGA纹理文件
3、设置纹理环绕方式和过滤方式
4、载入纹理
5、生成Mip贴图(当过滤方式与Mip无关时,可以设置,也可以不设置,如果使用与Mip相关的过滤方式,就必须设置)
参数1:纹理维度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
-- glGenerateMipmap
6、释放纹理对象空间的指针

for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
    {
        /**绑定纹理对象 glBindTexture
         参数1:纹理模式,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
         参数2:需要绑定的纹理对象
         */
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
        
        /**加载tga文件
         参数1:纹理文件名称
         参数2:文件宽度变量地址
         参数3:文件高度变量地址
         参数4:文件组件变量地址
         参数5:文件格式变量地址
         返回值:pBytes,指向图像数据的指针
         */
        
        pBytes = gltReadTGABits(szTextureFiles[iLoop],&iWidth, &iHeight,
                                &iComponents, &eFormat);
        
        //加载纹理、设置过滤器和包装模式
        //GL_TEXTURE_MAG_FILTER(放大过滤器,GL_NEAREST(最邻近过滤)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //GL_TEXTURE_MIN_FILTER(缩小过滤器),GL_NEAREST(最邻近过滤)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        //GL_TEXTURE_WRAP_S(s轴环绕),GL_CLAMP_TO_EDGE(环绕模式强制对范围之外的纹理坐标沿着合法的纹理单元的最后一行或一列进行采样)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        //GL_TEXTURE_WRAP_T(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, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
        
        /**为纹理对象生成一组完整的mipmap glGenerateMipmap
         参数1:纹理维度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
         */
        glGenerateMipmap(GL_TEXTURE_2D);
        
        //释放原始纹理数据,不在需要纹理原始数据了
        free(pBytes);
    }

设置隧道数据

参数1:图元枚举值
参数2:顶点数
参数3:1组或者2组纹理坐标
void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);

6-10.png
floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    //参考6-10图
    //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();
RenderScene函数
2.png

1、清除颜色缓存

    glClear(GL_COLOR_BUFFER_BIT);

2、push压栈:为了不影响矩阵的初始状态,方便后续恢复矩阵

modelViewMatrix.PushMatrix();

3、视图模型矩阵平移:因为初始化是是在原点,需要往-z轴平移一定的矩阵,方便观察,且与矩阵栈顶相乘,将其结果覆盖栈顶矩阵

modelViewMatrix.Translate(0.0f, 0.0f, viewZ);

4、使用纹理替换矩阵着色器:最后一个参数是指纹理的level,默认为0

shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);

5、绑定纹理:由于地面、天花板、左右墙分别使用不同的纹理,所以需要分别绑定并绘制

/*
     参数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();

6、pop出栈:恢复矩阵的初始状态

modelViewMatrix.PopMatrix();

7、交换缓冲区

glutSwapBuffers();
SpecialKeys函数

函数功能比较简单,主要就是根据上下键位,记录移动的深度值,并重新渲染

ProcessMenu函数
3.png

相关文章

  • 案例2、 OpenGL隧道

    main:初始化入口SetupRC:初始化背景色、着色器,生成纹理,并设置顶点及纹理坐标ChangeSize:改变...

  • OpenGL隧道案例

    首先我们来看效果,通过点击鼠标的前后,我们就像走在一个一个隧道一样。 顶点、纹理设置 我们可以将隧道拆分成3个部分...

  • OpenGL 案例:隧道

    隧道整体的案例最终效果如下图所示 隧道的绘制过程,整体的流程如下图 主要涉及的函数 main函数、ChangeSi...

  • OpenGL案例 -- 隧道

    整体流程 SetupRC:初始化背景色、着色器,生成纹理、设置顶点和坐标 RenderScene:绘制场景,绑定纹...

  • OpenGL 纹理隧道案例

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

  • OpenGL--隧道案例

    效果图如下: 案例分析 设置纹理坐标使用批次类的MultiTexCoord2f,其中第一个参数是指图层,即纹理的l...

  • OpenGL 纹理案例-隧道

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

  • OpenGL纹理案例-隧道

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

  • OpenGL隧道案例分析

    1.效果图 此案例绘制了隧道的上下左右四个墙壁,并且加入了纹理,通过键盘上下键来控制观察者位置。效果图如下: 2.代码块

  • OpenGL纹理案例-隧道

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

网友评论

      本文标题:案例2、 OpenGL隧道

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