zoukankan      html  css  js  c++  java
  • OpenGL代码学习(22)--绘制通道

    注意:需要在配置好OpenGL的编程环境中运行下列代码,环境配置文章可参考:

    OpenGL在Mac项目上的配置

    下面的代码,直接放置在main.cpp文件中即可:

    #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;
    // 视景体
    GLFrustum viewFrustum;
    // 变换管线,以及它管理的2个矩阵堆栈
    GLGeometryTransform transformPipeline;
    GLMatrixStack modelViewMatrix;
    GLMatrixStack projectionMatrix;
    
    // 4个数据批次
    GLBatch floorBatch;
    GLBatch ceilingBatch;
    GLBatch leftWallBatch;
    GLBatch rightWallBatch;
    
    // 用于控制观察者向前和向后
    GLfloat viewZ = -65.0f;
    
    // 宏定义,地板、天花板、墙分别对应的纹理标识数组索引
    #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" };
    
    // 点击右键菜单选项回调
    void ProcessMenu(int value) {
        // 循环遍历所有纹理数据
        for(GLint iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++) {
            // 绑定当前纹理为该索引对应的纹理数据
            glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
            
            // 设置该纹理数据的缩小过滤器
            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;
            }
        }
        // 触发渲染
        glutPostRedisplay();
    }
    
    // 加载所有的纹理数据
    void LoadAllTextureData() {
        GLbyte *pBytes;
        GLint iWidth, iHeight, 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, &iHeight, &iComponents, &eFormat);
            
            // 设置纹理数据缩小、放大过滤器
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            
            // 设置纹理数据(s, t)环绕模式
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            
            // 加载纹理数据到2维纹理缓冲区
            glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
            
            // 2维纹理缓冲区开启 Mip 贴图
            glGenerateMipmap(GL_TEXTURE_2D);
            
            // 释放纹理数据
            free(pBytes);
        }
    }
    
    // 初始化地板数据
    void SetupFloorBatch() {
        GLfloat 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();
    }
    
    // 初始化天花板数据
    void SetupCeilingBatch() {
        GLfloat z;
        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();
    }
    
    // 初始化左右墙数据
    void SetupWallBatch() {
        // 左墙
        GLfloat z;
        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();
    }
    
    // 程序初始化渲染环境
    void SetupRC() {
        // 设置窗口背景为黑色
        glClearColor(0.0f, 0.0f, 0.0f,1.0f);
        
        // 初始化着色器
        shaderManager.InitializeStockShaders();
        
        // 加载所有纹理数据
        LoadAllTextureData();
    
        // 初始化地板
        SetupFloorBatch();
        // 初始化天花板
        SetupCeilingBatch();
        // 初始化墙
        SetupWallBatch();
    }
    
    // 程序释放资源
    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 RenderScene(void) {
        // 清除缓冲区内容
        glClear(GL_COLOR_BUFFER_BIT);
        
        // 压入单位矩阵
        modelViewMatrix.PushMatrix();
        // 模型视图向Z轴平移
        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();
    }
    
    // 窗口大小变化回调方法
    void ChangeSize(int width, int height) {
        // 防止除数为0
        if(height == 0)
            height = 1;
        
        // 设置视口
        glViewport(0, 0, width, height);
        // 计算窗口宽高比
        GLfloat fAspect = (GLfloat)width / (GLfloat)height;
        // 设置投影矩阵
        viewFrustum.SetPerspective(80.0f, fAspect, 1.0, 120.0);
        // 投影矩阵堆栈保持投影矩阵
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        // 设置变换管线的投影矩阵堆栈和模型视图矩阵堆栈
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        
    }
    
    // 程序入口
    int main(int argc, char *argv[]) {
        // 设置 Mac OS 工作目录路径
        gltSetWorkingDirectory(argv[0]);
        
        // GLUT 初始化
        glutInit(&argc, argv);
        
        // 设置 GLUT 渲染模式
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
        
        // 创建窗口
        glutInitWindowSize(800, 720);
        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);
        // 设置右键菜单弹出
        glutAttachMenu(GLUT_RIGHT_BUTTON);
        
        // GLEW 驱动程序初始化
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "GLEW Error: %s
    ", glewGetErrorString(err));
            return 1;
        }
        
        // 程序初始化渲染环境
        SetupRC();
        
        // 运行循环
        glutMainLoop();
        
        // 程序释放资源
        ShutdownRC();
        
        return 0;
    }

    效果如下:

  • 相关阅读:
    详细聊聊k8s deployment的滚动更新(一)
    更新k8s镜像版本的三种方式
    深入理解docker信号机制以及dumb-init的使用
    10分钟教你理解反射
    nodejs的交互式解释器模式常用命令
    nrm的安装和使用
    复杂sql语句之单字段分类count计数和多字段count计数
    navicat连接mysql出现2059
    mongodb常规操作语句
    System.Web.NullPointerException
  • 原文地址:https://www.cnblogs.com/cchHers/p/14726862.html
Copyright © 2011-2022 走看看