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\n", glewGetErrorString(err));
        return 1;
    }
    
    // 初始化设置
    SetupRC();
    
    // 进入调用循环
    glutMainLoop();
    
    return 0;
}

部分效果图如下:

 

 

 

 

 

 

 

posted @ 2021-05-01 22:44  码出境界  阅读(456)  评论(0编辑  收藏  举报