美文网首页工作生活
OpenGL/OpenGL ES (三) —— 绘制甜甜圈

OpenGL/OpenGL ES (三) —— 绘制甜甜圈

作者: HookLee | 来源:发表于2019-07-03 15:03 被阅读0次

    OpenGL/OpenGL ES (一) —— 专业名词快速了解
    OpenGL/OpenGL ES (二) —— 渲染架构、图元、着色器、投影
    OpenGL/OpenGL ES (三) —— 绘制甜甜圈
    OpenGL/OpenGL ES (四) —— 纹理
    OpenGL/OpenGL ES (五) —— 纹理翻转策略
    OpenGL/OpenGL ES (六) —— 立方体旋转
    OpenGL/OpenGL ES (七) —— 初探
    OpenGL/OpenGL ES (八) —— 如何加载一张图片
    OpenGL/OpenGL ES (九) —— 光照

    前言

    先看下最终效果主要学习目标是正背面剔除和深度测试。

    甜甜圈.png

    第一步

    先看下main函数中相对应的调用顺序,和相对应的初始化。

    int main(int argc, char* argv[])
    {
       gltSetWorkingDirectory(argv[0]);
       
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
       glutInitWindowSize(800, 600);
       glutCreateWindow("Geometry Test Program");
       glutReshapeFunc(ChangeSize);
       glutSpecialFunc(SpecialKeys);
       glutDisplayFunc(RenderScene);
    
       GLenum err = glewInit();
       if (GLEW_OK != err) {
           fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
           return 1;
       }
       
       SetupRC();
       
       glutMainLoop();
       return 0;
    }
    
    

    第二步

    ChangeSize方法中设置视口,设置透视投影模式,把透视投影矩阵加载到透视矩阵堆栈中

    
    //窗口改变
    void ChangeSize(int w, int h)
    {
        //1.防止h变为0
        if(h == 0)
            h = 1;
        
        //2.设置视口窗口尺寸
        glViewport(0, 0, w, h);
        
        //3.setPerspective函数的参数是一个从顶点方向看去的视场角度(用角度值表示)
        // 设置透视模式,初始化其透视矩阵
        viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
        
        //4.把透视投影矩阵加载到透视矩阵堆栈中
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //5.初始化渲染管线
        transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);
    }
    
    
    

    第三步

    键位设置,通过不同的键位对其进行设置,控制Camera的移动,从而改变视口并且重新刷新显示。

    void SpecialKeys(int key, int x, int y)
    {
        //1.判断方向
        if(key == GLUT_KEY_UP)
            //2.根据方向调整观察者位置
            viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_DOWN)
            viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_LEFT)
            viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);
        
        if(key == GLUT_KEY_RIGHT)
            viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);
        
        //3.重新刷新
        glutPostRedisplay();
    }
    
    

    第四步

    渲染场景

    void RenderScene(void)
    {
        //清除窗口和深度缓冲区
     
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
          //开启背面剔除
            glEnable(GL_CULL_FACE);
            glFrontFace(GL_CCW);
            glCullFace(GL_BACK);
    
            //开启深度测试
            glEnable(GL_DEPTH_TEST);
        
        //把摄像机矩阵压入模型矩阵中
        modelViewMatix.PushMatrix(viewFrame);
        
        GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
        
        //使用平面着色器
        //参数1:平面着色器
        //参数2:模型视图投影矩阵
        //参数3:颜色
        //shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed);
        
        //使用默认光源着色器
        //通过光源、阴影效果跟提现立体效果
        //参数1:GLT_SHADER_DEFAULT_LIGHT 默认光源着色器
        //参数2:模型视图矩阵
        //参数3:投影矩阵
        //参数4:基本颜色值
        shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);
        
        //绘制
        torusBatch.Draw();
    
        //出栈
        modelViewMatix.PopMatrix();
        
        
        glutSwapBuffers();
    }
    

    第五步

    绘制甜甜圈

    void SetupRC()
    {
        // 设置背景颜色
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f );
        
        //初始化着色器管理器
        shaderManager.InitializeStockShaders();
        
        //将相机向后移动7个单元:肉眼到物体之间的距离
        viewFrame.MoveForward(7.0);
        
        //创建一个甜甜圈
        //void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
        //参数1:GLTriangleBatch 容器帮助类
        //参数2:外边缘半径
        //参数3:内边缘半径
        //参数4、5:主半径和从半径的细分单元数量
       
        gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
       //点的大小
        glPointSize(4.0f);
    }
    

    相关文章

      网友评论

        本文标题:OpenGL/OpenGL ES (三) —— 绘制甜甜圈

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