zoukankan      html  css  js  c++  java
  • OpenGL代码学习(8)--画一个圆环 花托

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

    OpenGL在Mac项目上的配置

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

    #include "GLTools.h"
    #include "GLMatrixStack.h"
    #include "GLFrame.h"
    #include "GLFrustum.h"
    #include "GLGeometryTransform.h"
    #include <math.h>
    #include <GLUT/GLUT.h>
    
    GLShaderManager shaderManager;
    GLTriangleBatch torusBatch;
    GLGeometryTransform transformPipeline;
    GLMatrixStack modelViewMatrix;
    GLMatrixStack projectionMatrix;
    GLFrame viewFrame;
    GLFrustum viewFrustum;
    
    // 是否开启正方面剔除
    int iCull = 0;
    
    // 是否开始深度测试
    int iDepth = 0;
    
    // 点击菜单选项
    void ProcessMenu(int value) {
        switch (value) {
            case 1:
                // 开关深度测试
                iDepth = !iDepth;
                break;
            case 2:
                // 开关正反面剔除
                iCull = !iCull;
            case 3:
                // 开关多边形-面模式
                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                break;
            case 4:
                // 开关多边形-线模式
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            case 5:
                // 开关多边形点模式
                glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
                break;
        }
        // 触发渲染
        glutPostRedisplay();
    }
    
    // 渲染画面
    void RenderScene(void) {
        // 清楚一个或一组特定的缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // 判断是否开启正反面剔除
        if (iCull) {
            glEnable(GL_CULL_FACE);
        } else {
            glDisable(GL_CULL_FACE);
        }
        
        // 判断是否开启深度测试
        if (iDepth) {
            glEnable(GL_DEPTH_TEST);
        } else {
            glDisable(GL_DEPTH_TEST);
        }
        
        // 保存当前的模型视图矩阵
        modelViewMatrix.PushMatrix(viewFrame);
        
        // 这里使用默认光源进行着色,可以看到阴影
        GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
        shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);
        
        // 画花托
        torusBatch.Draw();
        
        // 还原以前的模型视图矩阵
        modelViewMatrix.PopMatrix();
        
        // 将在后台缓冲区进行渲染,然后在结束时交换到前台
        glutSwapBuffers();
    }
    
    // 为程序做一次性的设置
    void SetupRC() {
        // 设置窗口背景颜色
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
        
        // 初始化着色器管理器
        shaderManager.InitializeStockShaders();
        
        // 设置变换管线以使用两个矩阵堆栈
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        
        // 移动物体的位置,值越大物体越远,值越小物体越近
        viewFrame.MoveForward(6.0f);
        
        // 创建一个花托批次,参数依次是:批次、外半径、内半径、片段数、堆叠数(在计算机中圆是正多边形,顶点数越多越像真正的圆)
        gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
        
        // 设置默认点大小
        glPointSize(4.0f);
    }
    
    // 特殊按键(功能键或者方向键)监听
    void SpecialKeys(int key, int x, int y) {
        // 上下左右按键,3D旋转
        /*
         RotateWorld(float fAngle, float x, float y, float z)
         fAngle:旋转弧度,x、y、z:以哪个坐标系轴旋转
         m3dDegToRad:角度 转 弧度
         */
        switch (key) {
            case GLUT_KEY_UP:
                viewFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
                break;
            case GLUT_KEY_DOWN:
                viewFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
                break;
            case GLUT_KEY_LEFT:
                viewFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
                break;
            case GLUT_KEY_RIGHT:
                viewFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
                break;
        }
        // 出发渲染
        glutPostRedisplay();
    }
    
    // 窗口大小改变时接受新的宽度和高度,其中0,0代表窗口中视口的左下角坐标,w,h代表像素
    void ChangeSize(int width, int height) {
        // 防止下面除法的除数为0导致的闪退
        if (height == 0) {
            height = 1;
        }
        // 设置视图窗口位置
        glViewport(0, 0, width, height);
        
        // 创建投影矩阵,并将它载入到投影矩阵堆栈中
        viewFrustum.SetPerspective(35.0f, float(width) / float(height), 1.0f, 500.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    }
    
    // 程序入口
    int main(int argc, char *argv[]) {
        // 设置当前工作目录,针对Mac OS X
        gltSetWorkingDirectory(argv[0]);
        
        // 初始化GLUT库
        glutInit(&argc, argv);
        
        /*
         初始化渲染模式,其中标志GLUT_BOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区
         */
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
        
        // 初始化窗口大小
        glutInitWindowSize(800, 720);
        
        // 创建窗口
        glutCreateWindow("Geometry Test Program");
        
        // 注册回调函数
        glutReshapeFunc(ChangeSize);
        glutDisplayFunc(RenderScene);
        glutSpecialFunc(SpecialKeys);
        
        // 创建菜单,绑定一个响应方法
        glutCreateMenu(ProcessMenu);
        
        // 为菜单添加选项
        glutAddMenuEntry("Toggle depth test", 1);
        glutAddMenuEntry("Toggle cull backface", 2);
        glutAddMenuEntry("Set Fill Mode", 3);
        glutAddMenuEntry("Set Line Mode", 4);
        glutAddMenuEntry("Set Point Mode", 5);
        
        // 右键弹出菜单
        glutAttachMenu(GLUT_RIGHT_BUTTON);
        
        // 确保驱动程序的初始化中没有出现任何问题
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "glew erroe:%s
    ", glewGetErrorString(err));
            return 1;
        }
        
        // 初始化设置
        SetupRC();
        
        // 进入调用循环
        glutMainLoop();
        
        return 0;
    }

    部分效果图如下:

     

  • 相关阅读:
    软件乘法实现
    矩阵连乘求解优化
    { 控件动态创建的堆与栈 }
    digital clock based C
    C++初探
    C语言语法教程-链表
    EF Core 实现读写分离的最佳方案
    Windows Terminal 安装及美化
    .netcore centos环境搭建实战
    AutoMapper.RegExtension 介绍
  • 原文地址:https://www.cnblogs.com/cchHers/p/14724982.html
Copyright © 2011-2022 走看看