美文网首页
01、OpenGL代码示例

01、OpenGL代码示例

作者: 小番茄爸爸呀 | 来源:发表于2019-05-17 17:43 被阅读0次

    需求

    在屏幕上画三个点(立体的),按上下左右能进行立体的变换

    初始化工作

    /*
     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;//投影设置
    //容器类
    GLBatch             pointBatch;
    
    //几何变换的管道
    GLGeometryTransform transformPipeline;
    
    GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
    GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    

    main函数程序入口

    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        //初始化GLUT库,这个函数只是传递命令参数并且初始化glut库
        glutInit(&argc, argv);
        /*
         初始化双缓冲窗口,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指
         双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区
         
         --GLUT_DOUBLE`:双缓存窗口,是指绘图命令实际上是离屏缓存区执行的,然后迅速转换成窗口视图,这种方式,经常用来生成动画效果;
         --GLUT_DEPTH`:标志将一个深度缓存区分配为显示的一部分,因此我们能够执行深度测试;
         --GLUT_STENCIL`:确保我们也会有一个可用的模板缓存区。
         深度、模板测试后面会细致讲到
         */
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
        //设置window 的尺寸
        glutInitWindowSize(800, 600);
        //创建window的名称
        glutCreateWindow("GL_POINTS");
        /*
         GLUT 内部运行一个本地消息循环,拦截适当的消息。然后调用我们不同时间注册的回调函数。我们一共注册2个回调函数:
         1)为窗口改变大小而设置的一个回调函数
         2)包含OpenGL 渲染的回调函数
         */
        //注册回调函数(改变尺寸)
        //1、渲染的时候会掉一次 2、改变尺寸的时候会调一次
        glutReshapeFunc(ChangeSize);
        //特殊键位函数(上下左右)
        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;
    }
    

    初始化一些配置和数据

    void SetupRC()
    {
        // 灰色的背景
        glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
        //着色器管理器初始化
        shaderManager.InitializeStockShaders();
        //打开深度测试
        glEnable(GL_DEPTH_TEST);
        //设置变换管线以使用两个矩阵堆栈
        //这个时候模型 视图矩阵 和 投影矩阵 没有值,因为没有初始化进行赋值操作
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        //初始化摄像机坐标
        cameraFrame.MoveForward(-15.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();
    }
    

    ChangeSize尺寸改变

    // 窗口已更改大小,或刚刚创建。无论哪种情况,我们都需要
    // 使用窗口维度设置视口和投影矩阵.
    // 因为每当尺寸发生变化的时候,对应的投影矩阵也要发生变化,所以要在这个函数里面设置投影矩阵
    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();
    }
    

    渲染函数Render

    // 召唤场景
    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);
        
        //开始画点
        glPointSize(4.0f);
        pointBatch.Draw();
        glPointSize(1.0f);
        
        //还原到以前的模型视图矩阵(单位矩阵)
        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();
    }
    

    相关文章

      网友评论

          本文标题:01、OpenGL代码示例

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