OpenGL 球体世界

一、类似公自转

二、核心代码

//图形渲染

void RenderScene()
{
    //清楚缓存区:颜色缓存区、深度缓存区、模版缓存区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
    //设置颜色:地板、甜甜圈、球体
    GLfloat vFloorColor[] = {0.0f, 1.0f, 0.0f, 1.0f};
    GLfloat vTorusColor[] = {1.0f, 0.0f, 0.0f, 1.0f};
    GLfloat vSphereColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
    
    //基于当前时间动画:当前时间*60s
    static CStopWatch rotTime;
    float yRot = rotTime.GetElapsedSeconds()*60.0f;
    
    //获取观察者矩阵并入栈
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.PushMatrix(mCamera);
    
    //设置光源矩阵
    M3DVector4f vLightPos = {0.0f, 10.0f, 5.0f, 1.0f};
    M3DVector4f vLightEyePos;
    //将光源矩阵和观察者矩阵相乘的结果放在vLightEyePos中
    m3dTransformVector4(vLightEyePos, vLightPos, mCamera);
    
    //使用管线控制器,平面着色器进行渲染
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor);
    floorBatch.Draw();
    
    //在模型视图矩阵堆栈中绘制以下图形:先压栈,绘制完毕后再出栈——始终对栈顶矩阵图形渲染
    
    //绘制随机球体
    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(), vLightEyePos, vSphereColor);
        //可与公转球体使用同一个容器类对象
        sphereBatch.Draw();
        
        modelViewMatrix.PopMatrix();
    }
    
    //设置甜甜圈平移距离(z轴负方向2.5)和旋转角度;
    modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);
    modelViewMatrix.PushMatrix();
    modelViewMatrix.Rotate(yRot, 0.0f, 0.1f, 0.0f);
    //使用点光源着色器渲染
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightEyePos, vTorusColor);
    torusBatch.Draw();
    modelViewMatrix.PopMatrix();
    
    //设置公转球体:反方向旋转,在x轴上平移0.8
    modelViewMatrix.Rotate(yRot *-2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vSphereColor);
    sphereBatch.Draw();
    
    modelViewMatrix.PopMatrix();
    
    //后台渲染完成后交给前台
    glutSwapBuffers();
    //基于时间动画:实时刷新窗口
    glutPostRedisplay();
}

//图形定位

void SetupRC()
{
    //设置窗口背景颜色
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    //初始化管线控制器
    shaderManager.InitializeStockShaders();
    //开启深度测试:图形间重叠部分无须重复绘制
    glEnable(GL_DEPTH_TEST);

    //提交甜甜圈数据:三角形批次类对象、外圈半径、内圈半径、主半径三角形对数x、小半径三角形对数y(尽量:x=2*y,更圆滑)
    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 15);
    //提交公转球体数据:三角形批次类对象、半径、底部到顶部三角形带的数量、一条三角形带中的三角形对数(一般指球体中间那条,为最大数)
    gltMakeSphere(sphereBatch, 0.1f, 26, 20);

    //线段模式,325个顶点
    floorBatch.Begin(GL_LINES, 325);
    for (GLfloat x = -20.0f; x <= 20.0f; x+=0.5f) {
        /*
         1.一个格子四个顶点,格子方向朝屏幕里面;
         2.只绘制x和z轴方向上的顶点;
         3.y轴坐标保持不变,负值,展示随机球体悬浮效果;
         */
        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();

    //随机悬浮球体:y值不变,x、z值随机
    for (int i = 0; i < NUM_SPHERES; i++) {
        GLfloat x = (GLfloat)(((rand()%400)-200)*0.1f);
        GLfloat z = (GLfloat)(((rand()%400)-200)*0.1f);
        spheres[i].SetOrigin(x, 0.0f, z);
    }
}

三、效果

OpenGL 球体世界_第1张图片

OpenGL 球体世界_第2张图片

 

GitHub

你可能感兴趣的:(OpenGL 球体世界)