美文网首页
OpenGL 常用工具类与API介绍

OpenGL 常用工具类与API介绍

作者: Mr木子李 | 来源:发表于2021-10-21 14:19 被阅读0次

    #include "GLTools.h"

    常用工具类

    • GLTools.h 头文件包含了大部分GLTool中类似C语言的独立函数

    #include "GLMatrixStack.h"

    • 矩阵的工具类,可以利用GLMatrixStack 加载单元矩阵/矩阵/矩阵相乘/压栈/出栈/缩放/平移/旋转
      GLMatrixStack 变化管线使用矩阵堆栈
      GLMatrixStack 构造函数允许指定堆栈的最大深度、默认的堆栈深度为64.这个矩阵堆在初始化时已经在堆栈中包含了单位矩阵。
      GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
      通过调用顶部载入这个单位矩阵
      void GLMatrixStack::LoadIndentiy(void);
      在堆栈顶部载入任何矩阵
      void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);

    #include "GLFrame.h"

    • 矩阵的工具类,表示位置,通过设置vOrigin,vForwaed,vUp
      #include "GLFrustum.h"
    • 矩阵的工具类,用来快速设置正/透视投影矩阵,完成坐标从3D->2D 映射过程
      #include "GLBatch.h"
    • 三角形批次类,帮助类,利用它可以传输定点/光照/纹理/颜色数据到存储着色器中
      #include "GLGeometryTransform.h"
    • 变换管道类,用来快速在代码中传输视图矩阵/投影矩阵/视图投影变换矩阵等
      #include "GL/glut.h"
    • 在mac系统下 #include "glut/glut.h"
      在windows 和 Linux 上我们使用freeglut 的静态库版本并且需要添加一个宏

    重要的函数

    int main(int argc, char* argv[])
    
    • main 函数: 程序入口 OpenGL 是面向过程编程,所以你会发现利用OpenGL处理图形/图像都是链式形式,以及基于OpenGL封装的图像处理框架也是链式编程
    void SetupRC()
    
    • SetupRC 函数: 自定义函数,设置你需要渲染的图像的相关顶点数据/颜色数据等数据准备工作
    // 使用窗口维度设置视口和投影矩阵.
    void ChangeSize(int w, int h)
    
    • ChangeSize 函数: 自定义函数,通过glutReshapeFunc(函数名)注册为重塑函数,当屏幕大小发生变化/或者第一次创建窗口时,会调用该函数调整窗口大小/视口大小
    void RenderScene()
    
    • RenderScene 函数: 自定义函数,通过glutDisplayFunc(函数名)注册为显示渲染函数,当屏幕大小发生变化/或者开发者主动渲染会调用此函数,用来实现数据-> 渲染过程
    void SpecialKeys(int key, int x, int y)
    
    • SpecialKeys 函数: 特殊键位处理(上、下、左、右移动)

    例子

    /*
     课程名称:OpenGL 视觉班--第二次课
     案例名称:OpenGL demo1
     实现功能:
        点击屏幕,将固定位置上的顶点数据以6种不同形态展示!
     */
    
    
    #include "GLTools.h"    
    #include "GLMatrixStack.h"
    #include "GLFrame.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLGeometryTransform.h"
    
    #include <math.h>
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    
    /*
     GLMatrixStack 变化管线使用矩阵堆栈
     GLMatrixStack 构造函数允许指定堆栈的最大深度、默认的堆栈深度为64.这个矩阵堆在初始化时已经在堆栈中包含了单位矩阵。
     GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
     //通过调用顶部载入这个单位矩阵
     void GLMatrixStack::LoadIndentiy(void);
     //在堆栈顶部载入任何矩阵
     void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
     */
    // 各种需要的类
    GLShaderManager     shaderManager;
    GLMatrixStack       modelViewMatrix;
    GLMatrixStack       projectionMatrix;
    GLFrame             cameraFrame;
    GLFrame             objectFrame;
    //投影矩阵
    GLFrustum           viewFrustum;
    
    //容器类(7种不同的图元对应7种容器对象)
    GLBatch             pointBatch;
    GLBatch             lineBatch;
    GLBatch             lineStripBatch;
    GLBatch             lineLoopBatch;
    GLBatch             triangleBatch;
    GLBatch             triangleStripBatch;
    GLBatch             triangleFanBatch;
    
    //几何变换的管道
    GLGeometryTransform transformPipeline;
    
    GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
    GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    
    // 跟踪效果步骤
    int nStep = 0;
    
    void SetupRC()
    {
        // 灰色的背景
        glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
        shaderManager.InitializeStockShaders();
        glEnable(GL_DEPTH_TEST);
        //设置变换管线以使用两个矩阵堆栈
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        cameraFrame.MoveForward(-30.0f);
        
        /*
         常见函数:
         void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
          参数1:表示使用的图元
          参数2:顶点数
          参数3:纹理坐标(可选)
         //复制顶点坐标
         void GLBatch::CopyVertexData3f(GLFloat *vNorms);
         //结束,表示已经完成数据复制工作
         void GLBatch::End(void);
         */
        //定义一些点,三角形形状。
       
        GLfloat vCoast[9] = {
            3,3,0,0,3,0,3,0,0
            
        };
        
        //用点的形式
        pointBatch.Begin(GL_POINTS, 3);
        pointBatch.CopyVertexData3f(vCoast);
        pointBatch.End();
    
    }
    
    // 召唤场景
    void RenderScene()
    {
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
       
        //压栈
        modelViewMatrix.PushMatrix();
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        
        //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mCamera);
        
        M3DMatrix44f mObjectFrame;
        //只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据
        objectFrame.GetMatrix(mObjectFrame);
        
        //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mObjectFrame);
        
        /* GLShaderManager 中的Uniform 值——平面着色器
         参数1:平面着色器
         参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
         --transformPipeline.GetModelViewProjectionMatrix() 获取的
         GetMatrix函数就可以获得矩阵堆栈顶部的值
         参数3:颜色值(黑色)
         */
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
        
        switch(nStep) {
            case 0:
                //设置点的大小
                glPointSize(4.0f);
                pointBatch.Draw();
                glPointSize(1.0f);
                break;
        }
        
        //还原到以前的模型视图矩阵(单位矩阵)
        modelViewMatrix.PopMatrix();
        
        // 进行缓冲区交换
        glutSwapBuffers();
    }
    
    
    //特殊键位处理(上、下、左、右移动)
    void SpecialKeys(int key, int x, int y)
    {
        
        if(key == GLUT_KEY_UP)
            //围绕一个指定的X,Y,Z轴旋转。
            objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_DOWN)
            objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_LEFT)
            objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
        
        if(key == GLUT_KEY_RIGHT)
            objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
        
        glutPostRedisplay();
    }
    
    
    
    
    //根据空格次数。切换不同的“窗口名称”
    void KeyPressFunc(unsigned char key, int x, int y)
    {
        if(key == 32)
        {
            nStep++;
            
            if(nStep > 6)
                nStep = 0;
        }
        
        switch(nStep)
        {
            case 0:
                glutSetWindowTitle("GL_POINTS");
                break;
            case 1:
                glutSetWindowTitle("GL_LINES");
                break;
            case 2:
                glutSetWindowTitle("GL_LINE_STRIP");
                break;
            case 3:
                glutSetWindowTitle("GL_LINE_LOOP");
                break;
            case 4:
                glutSetWindowTitle("GL_TRIANGLES");
                break;
            case 5:
                glutSetWindowTitle("GL_TRIANGLE_STRIP");
                break;
            case 6:
                glutSetWindowTitle("GL_TRIANGLE_FAN");
                break;
        }
        
        glutPostRedisplay();
    }
    
    
    // 窗口已更改大小,或刚刚创建。无论哪种情况,我们都需要
    // 使用窗口维度设置视口和投影矩阵.
    void ChangeSize(int w, int h)
    {
        glViewport(0, 0, w, h);
        //创建投影矩阵,并将它载入投影矩阵堆栈中
        viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //调用顶部载入单元矩阵
        modelViewMatrix.LoadIdentity();
    }
    
    
    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        glutInit(&argc, argv);
        //申请一个颜色缓存区、深度缓存区、双缓存区、模板缓存区
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
        //设置window 的尺寸
        glutInitWindowSize(800, 600);
        //创建window的名称
        glutCreateWindow("GL_POINTS");
        //注册回调函数(改变尺寸)
        glutReshapeFunc(ChangeSize);
        //点击空格时,调用的函数
        glutKeyboardFunc(KeyPressFunc);
        //特殊键位函数(上下左右)
        glutSpecialFunc(SpecialKeys);
        //显示函数
        glutDisplayFunc(RenderScene);
        
        //判断一下是否能初始化glew库,确保项目能正常使用OpenGL 框架
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
        //绘制
        SetupRC();
        
        //runloop运行循环
        glutMainLoop();
        return 0;
    }
    
    

    相关文章

      网友评论

          本文标题:OpenGL 常用工具类与API介绍

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