美文网首页
007-OpenGL综合练习

007-OpenGL综合练习

作者: 沉默Coder | 来源:发表于2020-07-19 16:01 被阅读0次

    学习OpenGL已经有一段时间,今天使用OpenGL来完成一个小例子,如下图


    例子

    首先我们将要完成的功能做一个拆解

    • 地面的绘制
    • 红色大球的绘制
    • 蓝色环绕小球的绘制
    • 其他静止小球的绘制

    完整代码

    #include "GLTools.h"
    #include "GLShaderManager.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLMatrixStack.h"
    #include "GLGeometryTransform.h"
    #include "StopWatch.h"
    
    #include <math.h>
    #include <stdio.h>
    
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    
    
    GLShaderManager     shaderManager;          // 着色器管理器
    GLMatrixStack       modelViewMatrix;        // 模型视图矩阵堆栈
    GLMatrixStack       projectionMatrix;       // 投影矩阵堆栈
    GLFrustum           viewFrustum;            // 视景体
    GLGeometryTransform transformPipeline;      // 几何图形变换管道
    
    GLTriangleBatch     torusBatch;             //大球
    GLTriangleBatch     sphereBatch;            //小球
    GLBatch             floorBatch;          //地板
    
    //角色帧 照相机角色帧
    GLFrame   cameraFrame;
    GLFrame  objectFrame;
    
    //**4、添加附加随机球
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    
    void SetupRC()
    {
        //1. 初始化
        glClearColor(0, 0, 0, 1);
        shaderManager.InitializeStockShaders();
        glEnable(GL_DEPTH_TEST);
        
        //3. 地板数据(物体坐标系)
        floorBatch.Begin(GL_LINES, 324);
        for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {
            floorBatch.Vertex3f(x, -0.55f, 20.0f);
            floorBatch.Vertex3f(x, -0.55f, -20.0f);
            
            floorBatch.Vertex3f(20.0f, -0.55f, x);
            floorBatch.Vertex3f(-20.0f, -0.55f, x);
        }
        floorBatch.End();
        
        //4. 设置一个球体(基于gltools模型)
        gltMakeSphere(torusBatch, 0.4f, 40, 80);
        
        //5. 绘制小球;
        gltMakeSphere(sphereBatch, 0.1f, 13, 26);
        //6. 随机位置放置小球球
        for (int i = 0; i < NUM_SPHERES; i++) {
            
            //y轴不变,X,Z产生随机值
            GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
            GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
            
            //在y方向,将球体设置为0.0的位置,这使得它们看起来是飘浮在眼睛的高度
            //对spheres数组中的每一个顶点,设置顶点数据
            spheres[i].SetOrigin(x, 0.0f, z);
        }
        
    }
    
    //进行调用以绘制场景
    void RenderScene(void)
    {
        //3.
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        //1. 颜色(地板,大球颜色,小球颜色)
        static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};
        static GLfloat vTorusColor[] = {1.0f,0.0f,0.0f,1.0f};
        static GLfloat vSpereColor[] = {0.0f,0.0f,1.0f,1.0f};
        
        
        //2. 动画
        static CStopWatch rotTimer;
        float yRot = rotTimer.GetElapsedSeconds()*60.0f;
        
        modelViewMatrix.PushMatrix();
        
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        modelViewMatrix.PushMatrix(mCamera);
        
        
        //4.地面绘制;
        shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
        floorBatch.Draw();
        
        
        //5. 设置点光源位置
        M3DVector4f vLightPos = {0,10,5,1};
        
        //6. 使得整个大球往里平移3.0
        modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
        
        //7. 大球
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot, 0, 1, 0);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
        torusBatch.Draw();
        modelViewMatrix.PopMatrix();
        
        //8. 小球
        for (int i = 0; i < NUM_SPHERES; i++) {
            modelViewMatrix.PushMatrix();
            modelViewMatrix.MultMatrix(spheres[i]);
            shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
            sphereBatch.Draw();
            modelViewMatrix.PopMatrix();
            
        }
        
        //9.让一个小球围着大球公转;
        modelViewMatrix.Rotate(yRot * -2.0f, 0, 1, 0);
        modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
        sphereBatch.Draw();
        
        
        modelViewMatrix.PopMatrix();
        modelViewMatrix.PopMatrix();
        glutSwapBuffers();
        glutPostRedisplay();
    }
    
    //屏幕更改大小或已初始化
    void ChangeSize(int nWidth, int nHeight)
    {
        //1. 设置视口
        glViewport(0, 0, nWidth, nHeight);
    
        //2. 创建投影矩阵
        viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //3. 变换管道设置2个矩阵堆栈(管理)
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    }
    
    void SpeacialKeys(int key,int x,int y){
        
        float linear = 0.1f;
        float angular = float(m3dDegToRad(5.0f));
        
        if (key == GLUT_KEY_UP) {
            cameraFrame.MoveForward(linear);
        }
        if (key == GLUT_KEY_DOWN) {
            cameraFrame.MoveForward(-linear);
        }
        
        if (key == GLUT_KEY_LEFT) {
            cameraFrame.RotateWorld(angular, 0, 1, 0);
        }
        if (key == GLUT_KEY_RIGHT) {
            cameraFrame.RotateWorld(-angular, 0, 1, 0);
        }
    
    }
    
    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(800,600);
        
        glutCreateWindow("OpenGL SphereWorld");
        
        glutReshapeFunc(ChangeSize);
        glutDisplayFunc(RenderScene);
        glutSpecialFunc(SpeacialKeys);
        
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
        
        SetupRC();
        glutMainLoop();    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:007-OpenGL综合练习

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