渲染世界的OpenGL<7>基础变换代码分析

来源:互联网 发布:windows 图标 闪烁 编辑:程序博客网 时间:2024/06/16 21:40

(1)移动旋转方块代码分析

这个代码是基于最开始的代码分析当中对方块的移动的代码。
实现每一次移动方块,方块都会进行旋转相应的角度。通过对旋转矩阵的增加,并且将旋转矩阵和移动矩阵进行综合,并且将其作为参数投入到shadermanagement当中,从而使得每一个顶点都会遵循相应的移动矩阵方式对其进行移动。

#pragma comment(lib,"GLTools.lib")#include <GLTools.h>    // OpenGL toolkit#include <GLShaderManager.h>#include <math3d.h>#include <GL/glut.h>//渲染队列GLBatch  squareBatch;GLShaderManager shaderManager;GLfloat blockSize = 0.1f;GLfloat vVerts[] = { -blockSize, -blockSize, 0.0f,blockSize, -blockSize, 0.0f,blockSize,  blockSize, 0.0f,-blockSize,  blockSize, 0.0f };GLfloat xPos = 0.0f;GLfloat yPos = 0.0f;///////////////////////////////////////////////////////////////////////////////// 初始化渲染场景void SetupRC(){    // 设置背景颜色    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);    //初始化渲染器管理器    shaderManager.InitializeStockShaders();    //对squareBatch进行渲染。    squareBatch.Begin(GL_TRIANGLE_FAN, 4);    squareBatch.CopyVertexData3f(vVerts);    squareBatch.End();}// 设置按键对其进行控制void SpecialKeys(int key, int x, int y){    GLfloat stepSize = 0.025f;    //设置不同按键    if (key == GLUT_KEY_UP)        yPos += stepSize;    if (key == GLUT_KEY_DOWN)        yPos -= stepSize;    if (key == GLUT_KEY_LEFT)        xPos -= stepSize;    if (key == GLUT_KEY_RIGHT)        xPos += stepSize;    // 碰撞检测    if (xPos < (-1.0f + blockSize)) xPos = -1.0f + blockSize;    if (xPos > (1.0f - blockSize)) xPos = 1.0f - blockSize;    if (yPos < (-1.0f + blockSize))  yPos = -1.0f + blockSize;    if (yPos > (1.0f - blockSize)) yPos = 1.0f - blockSize;    glutPostRedisplay();}///////////////////////////////////////////////////////////////////////////////// 正真的渲染函数//注意其矩阵操作的方法。void RenderScene(void){    // 清除当前的缓冲区    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    //设置红色    GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };    //设置当前的矩阵    //最终矩阵、移动矩阵、旋转矩阵    M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationMatrix;    // 初始化使用相关的移动参数生成相关的矩阵    m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);    // 每一次操作,进行5个单位的旋转    static float yRot = 0.0f;    yRot += 5.0f;    //不断的绕着z轴进行旋转,利用不同的旋转参数生成矩阵    m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);    //利用矩阵乘法生成一个综合矩阵    m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);    //利用上述的参数对相关的点参数进行变换    shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);    squareBatch.Draw();    // 手动更新    glutSwapBuffers();}///////////////////////////////////////////////////////////////////////////////void ChangeSize(int w, int h){    glViewport(0, 0, w, h);}///////////////////////////////////////////////////////////////////////////////// 主函数int main(int argc, char* argv[]){    gltSetWorkingDirectory(argv[0]);    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);    glutInitWindowSize(600, 600);    glutCreateWindow("Move Block with Arrow Keys");    GLenum err = glewInit();    if (GLEW_OK != err)    {        // Problem: glewInit failed, something is seriously wrong.        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));        return 1;    }    glutReshapeFunc(ChangeSize);    glutDisplayFunc(RenderScene);    glutSpecialFunc(SpecialKeys);    SetupRC();    glutMainLoop();    return 0;}

(2)模型投影矩阵应用

注意模型投影矩阵的应用
生成透视投影:GLFrustum viewFrustum;
在窗口控制函数中:viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 1000.0f);
最终和模型矩阵综合:m3dMatrixMultiply44(mModelViewProjection,viewFrustum.GetProjectionMatrix(), mModelview);

#pragma comment(lib,"GLTools.lib")#include <GLTools.h>    // OpenGL toolkit#include <GLMatrixStack.h>#include <GLFrame.h>#include <GLFrustum.h>#include <GLGeometryTransform.h>#include <GLBatch.h>#include <StopWatch.h>#include <GL/glut.h>//  透视投影GLFrustum           viewFrustum;// 渲染器管理器GLShaderManager     shaderManager;// 渲染队列GLTriangleBatch     torusBatch;void ChangeSize(int w, int h){    // 避免下面设置透视的时候出错    if (h == 0)        h = 1;    // 将视口设置到窗口的规模    glViewport(0, 0, w, h);    //设置透视投影    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 1000.0f);}// 渲染窗口void RenderScene(void){    // 动画设置的秒表    static CStopWatch rotTimer;    //得到当前的时间并且计算旋转    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;    // 清除相关缓冲区    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 设置当前的矩阵变量    M3DMatrix44f mTranslate, mRotate, mModelview, mModelViewProjection;    // 初始化移动矩阵    m3dTranslationMatrix44(mTranslate, 0.0f, 0.0f, -2.5f);    // 初始化旋转矩阵    m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);    // 将上述两个矩阵综合进模型矩阵    m3dMatrixMultiply44(mModelview, mTranslate, mRotate);    // 将模型矩阵装入到投影矩阵当中    // 生成最终的模型投影矩阵    m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(), mModelview);    // 对各个顶点进行绘制    GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };    shaderManager.UseStockShader(GLT_SHADER_FLAT, mModelViewProjection, vBlack);    torusBatch.Draw();    // Swap buffers, and immediately refresh    glutSwapBuffers();    glutPostRedisplay();}// 渲染环境初始化void SetupRC(){    // 背景颜色设置    glClearColor(0.8f, 0.8f, 0.8f, 1.0f);    glEnable(GL_DEPTH_TEST);    shaderManager.InitializeStockShaders();    // 调用生成花拖的函数。    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);    //正反面都用线框渲染    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);}///////////////////////////////////////////////////////////////////////////////// 主函数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("ModelViewProjection Example");    glutReshapeFunc(ChangeSize);    glutDisplayFunc(RenderScene);    GLenum err = glewInit();    if (GLEW_OK != err) {        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));        return 1;    }    SetupRC();    glutMainLoop();    return 0;}

(3)渲染一个简单世界
这里包含了一个完整的渲染顺序
实例化两个MatrixStack,一个作为模型矩阵,一个作为投影矩阵。
然后实例化一个渲染管线。
ChangeSize当中对投影矩阵进行赋值,并且利用两个矩阵堆栈对渲染管线初始化。
RenderScene当中对模型矩阵进行操作,按照先渲染静止物体,在渲染移动物体的原则。
注意这里对地面的动态设置渲染:对于floorBatch不断为期增加点,对其渲染器进行装填。

    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);    }
#pragma comment(lib,"GLTools.lib")#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>#include <GL/glut.h>GLShaderManager     shaderManager;          // Shader ManagerGLMatrixStack       modelViewMatrix;        // 模型视图矩阵GLMatrixStack       projectionMatrix;       // 投影矩阵GLFrustum           viewFrustum;            // 视景体GLGeometryTransform transformPipeline;      // 几何变换管线GLTriangleBatch     torusBatch;GLBatch             floorBatch;//////////////////////////////////////////////////////////////////// 渲染环境初始化void SetupRC(){    // 初始化ShaderManager。    shaderManager.InitializeStockShaders();    //开启深度测试    glEnable(GL_DEPTH_TEST);    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);    //背景颜色为黑色    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    // 创建花拖    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);    //设置地板    //使用计算方法动态生成    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();}///////////////////////////////////////////////////// 设置屏幕大小void ChangeSize(int nWidth, int nHeight){    glViewport(0, 0, nWidth, nHeight);    // 创建透视矩阵,GLFrustum类的viewFrustum实例会为我们设置投影矩阵    //载入投影矩阵对象    viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);    //透视矩阵加载到透视矩阵堆栈中    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());    //初始化渲染管线    // 设置变换管线,从而可以使用两个矩阵堆栈    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);    //注意:我们本可以在SetupRC当中完成这项工作。但是窗口大小    //改变的时候,重新设置它们并没有坏处。并且可以一次性完成    //矩阵和管线的设置。}// 绘制两个物体void RenderScene(void){    // 设置绘制不同物体的颜色。    static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };    static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };    // 设置秒表计时器    static CStopWatch   rotTimer;    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;    // 清除相应的缓冲区    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 保存当前的矩阵,单位矩阵    modelViewMatrix.PushMatrix();    // 使用平面渲染器对其进行渲染    shaderManager.UseStockShader(GLT_SHADER_FLAT,        transformPipeline.GetModelViewProjectionMatrix(),        vFloorColor);    floorBatch.Draw();    // 绘制旋转的花拖    modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(),        vTorusColor);    torusBatch.Draw();    // 恢复初始的矩阵    modelViewMatrix.PopMatrix();    // Do the buffer Swap    glutSwapBuffers();    // Tell GLUT to do it again    glutPostRedisplay();}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);    GLenum err = glewInit();    if (GLEW_OK != err) {        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));        return 1;    }    SetupRC();    glutMainLoop();    return 0;}

(4)为世界添加一个移动的摄像机

以下程序说明对摄像机的控制,同时也多次渲染了一个球体。
渲染摄像机的步骤:
GLFrame cameraFrame:首先使用角色帧来完成一个摄像机的创建。
M3DMatrix44f mCamera:在render里面新创建一个矩阵。
cameraFrame.GetCameraMatrix(mCamera):找出符合条件的摄像机矩阵。
modelViewMatrix.PushMatrix(mCamera):把摄像机矩阵压入模型矩阵中。
在上述操作之后,在SpecialKey当中,也设置诸多的key对其进行渲染:
cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
cameraFrame.MoveForward(-linear);

对于渲染多个物体:
modelViewMatrix.PopMatrix();多次使用pop来取消之前的矩阵操作,从而之后的操作不会对之前的操作产生影响。

#pragma comment(lib,"GLTools.lib")#include <GLTools.h>#include <GLShaderManager.h>#include <GLFrustum.h>#include <GLBatch.h>#include <GLFrame.h>#include <GLMatrixStack.h>#include <GLGeometryTransform.h>#include <StopWatch.h>#include <math.h>#include <stdio.h>#include <GL/glut.h>GLShaderManager     shaderManager;          // 渲染管理器GLMatrixStack       modelViewMatrix;        // 模型矩阵GLMatrixStack       projectionMatrix;       // 透视矩阵GLFrustum           viewFrustum;            // 透视GLGeometryTransform transformPipeline;      // 渲染管线GLTriangleBatch     torusBatch;GLBatch             floorBatch;GLTriangleBatch     sphereBatch;//设置角色帧,作为相机GLFrame             cameraFrame;//////////////////////////////////////////////////////////////////// 渲染环境设置void SetupRC(){    //初始化渲染管理器    shaderManager.InitializeStockShaders();    //开启深度测试    glEnable(GL_DEPTH_TEST);    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    // 创建一个花拖    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);    //创建一个球    gltMakeSphere(sphereBatch, 0.1f, 26, 13);    //创建地板    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();}///////////////////////////////////////////////////// 改变窗口大小void ChangeSize(int nWidth, int nHeight){    glViewport(0, 0, nWidth, nHeight);    // 设置透视模式,初始化其透视矩阵    viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);    //把透视矩阵加载到透视矩阵对阵中    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());    // 初始化渲染管线。    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);}// 键位设置,通过不同的键位对其进行设置//控制Camera的移动,从而改变视口。void SpecialKeys(int key, int x, int y){    //设置移动的分量    float linear = 0.1f;    //设置旋转的分量    float angular = float(m3dDegToRad(5.0f));    //注意其如何对Camera进行操作    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.0f, 1.0f, 0.0f);    if (key == GLUT_KEY_RIGHT)        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);}// Called to draw scenevoid RenderScene(void){    //三种渲染颜色    static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };    static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };    static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };    // 计时器,从而做出基础动画    static CStopWatch   rotTimer;    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;    // 清除缓冲区    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 装载当前的单位矩阵    modelViewMatrix.PushMatrix();    //创建一个矩阵作为摄像机矩阵     M3DMatrix44f mCamera;    //这个函数用来检索条件适合的照相机矩阵并且初始化给mCamera。    cameraFrame.GetCameraMatrix(mCamera);    //将照相机矩阵压入模型矩阵堆栈    modelViewMatrix.PushMatrix(mCamera);    // 绘制地面    shaderManager.UseStockShader(GLT_SHADER_FLAT,        transformPipeline.GetModelViewProjectionMatrix(),        vFloorColor);    floorBatch.Draw();    // 绘制花拖进行移动    modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);    // 对上面的操作进行保存    modelViewMatrix.PushMatrix();    // 旋转一个角度。    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(),        vTorusColor);    torusBatch.Draw();    modelViewMatrix.PopMatrix(); //去掉Rotate的操作     // 应用一个其他的球体,并且对它进行移动。    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();    // Restore the previous modleview matrix (the identity matrix)    modelViewMatrix.PopMatrix();    modelViewMatrix.PopMatrix();    // 因为是GLUT_DOUBLE,所以需要后台渲染,再交换到前台    glutSwapBuffers();    // 手动刷新    glutPostRedisplay();}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");    glutSpecialFunc(SpecialKeys);    glutReshapeFunc(ChangeSize);    glutDisplayFunc(RenderScene);    GLenum err = glewInit();    if (GLEW_OK != err) {        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));        return 1;    }    SetupRC();    glutMainLoop();    return 0;}

(5)对世界渲染更多事物
渲染多个物体所遵循的原则和上面基本一致:
先渲染静态物体
再渲染动态物体
动态物体注意不断pop矩阵堆栈
摄像机矩阵添加到模型视图矩阵队列
投影矩阵添加到投影视图矩阵队列

#pragma comment(lib,"GLTools.lib")#include <GLTools.h>#include <GLShaderManager.h>#include <GLFrustum.h>#include <GLBatch.h>#include <GLFrame.h>#include <GLMatrixStack.h>#include <GLGeometryTransform.h>#include <StopWatch.h>#include <math.h>#include <stdio.h>#include <GL/glut.h>#define NUM_SPHERES 50GLFrame spheres[NUM_SPHERES];GLShaderManager     shaderManager;          // 渲染管理器GLMatrixStack       modelViewMatrix;        // 模型渲染矩阵GLMatrixStack       projectionMatrix;       // 投影矩阵GLFrustum           viewFrustum;            // 视图矩阵GLGeometryTransform transformPipeline;      // 渲染管线GLTriangleBatch     torusBatch;GLBatch             floorBatch;GLTriangleBatch     sphereBatch;GLFrame             cameraFrame;//////////////////////////////////////////////////////////////////// 渲染环境初始化void SetupRC(){    // 渲染器管理器初始化    shaderManager.InitializeStockShaders();    //开启深度检测    glEnable(GL_DEPTH_TEST);    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);    //设置黑色为背景颜色    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    // 创建花拖    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);    // 创建球体    gltMakeSphere(sphereBatch, 0.1f, 26, 13);    //创建地面    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();    // 随机分配相关的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);    }}///////////////////////////////////////////////////// 屏幕改变的时候需要调节的参数void ChangeSize(int nWidth, int nHeight){    glViewport(0, 0, nWidth, nHeight);    // 对GLFrustum生成投影矩阵    viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);    //把投影矩阵压入相关的投影矩阵堆栈    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());    // 初始化渲染管线    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);}// 实际渲染的方式void RenderScene(void){    // 设置相应的颜色参数    static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };    static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };    static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };    // 计时器的计算    static CStopWatch   rotTimer;    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;    // 清楚相关的缓冲区    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 对模型矩阵压入单位矩阵    modelViewMatrix.PushMatrix();    //设置一个Camera矩阵    M3DMatrix44f mCamera;    //对于创建的角色帧得到符合条件的摄像机矩阵    cameraFrame.GetCameraMatrix(mCamera);    //把得到的摄像机矩阵压入对应的模型矩阵    modelViewMatrix.PushMatrix(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_FLAT, transformPipeline.GetModelViewProjectionMatrix(),            vSphereColor);        sphereBatch.Draw();        modelViewMatrix.PopMatrix();        //每一次渲染之后,都需要对矩阵堆栈进行弹出        //清理之前的操作矩阵,并且向其中压入新的操作矩阵    }    //渲染静态物体结束    //开始渲染动态物体    //向模型视图矩阵堆栈传递位置矩阵    modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);    // 保存其操作    modelViewMatrix.PushMatrix();    // 应用旋转    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(),        vTorusColor);    torusBatch.Draw();    modelViewMatrix.PopMatrix(); //清空当前旋转操作矩阵    // 应用另外一个旋转矩阵    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();    modelViewMatrix.PopMatrix();    // 交换渲染区    glutSwapBuffers();    // 手动渲染    glutPostRedisplay();}// 通过按键来完成对相机的操作。void SpecialKeys(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.0f, 1.0f, 0.0f);    if (key == GLUT_KEY_RIGHT)        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);}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");    glutSpecialFunc(SpecialKeys);    glutReshapeFunc(ChangeSize);    glutDisplayFunc(RenderScene);    GLenum err = glewInit();    if (GLEW_OK != err) {        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));        return 1;    }    SetupRC();    glutMainLoop();    return 0;}

(6)光线渲染

关于光线的设置。需要设置一个光源矩阵。
并且把光源矩阵和之前得到的 GetCameraMatrix(mCamera)做Transform操作,得到一个结果矩阵。
然后把结果矩阵传入到对应的渲染器当中作为一个重要参数。参考之前的《基础渲染》文章,当中的诸多渲染器方法可供选择,选择一个可行的方式对想要操作的对象进行渲染。

#pragma comment(lib,"GLTools.lib")#include <GLTools.h>#include <GLShaderManager.h>#include <GLFrustum.h>#include <GLBatch.h>#include <GLFrame.h>#include <GLMatrixStack.h>#include <GLGeometryTransform.h>#include <StopWatch.h>#include <math.h>#include <stdio.h>#include <GL/glut.h>#define NUM_SPHERES 50GLFrame spheres[NUM_SPHERES];GLShaderManager     shaderManager;          // Shader ManagerGLMatrixStack       modelViewMatrix;        // Modelview MatrixGLMatrixStack       projectionMatrix;       // Projection MatrixGLFrustum           viewFrustum;            // View FrustumGLGeometryTransform transformPipeline;      // Geometry Transform PipelineGLTriangleBatch     torusBatch;GLBatch             floorBatch;GLTriangleBatch     sphereBatch;GLFrame             cameraFrame;//////////////////////////////////////////////////////////////////// This function does any needed initialization on the rendering// context. void SetupRC(){    shaderManager.InitializeStockShaders();    glEnable(GL_DEPTH_TEST);    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);    gltMakeSphere(sphereBatch, 0.1f, 26, 13);    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();    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);    }}///////////////////////////////////////////////////void ChangeSize(int nWidth, int nHeight){    glViewport(0, 0, nWidth, nHeight);    viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);}void RenderScene(void){    static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };    static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };    static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };    static CStopWatch   rotTimer;    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    modelViewMatrix.PushMatrix();    M3DMatrix44f mCamera;    cameraFrame.GetCameraMatrix(mCamera);    modelViewMatrix.PushMatrix(mCamera);    // 设置光源位置。注意,光源位置的全局坐标系存储在vLightPos    //包含了光源位置的x、y、z和w坐标。    M3DVector4f vLightPos = { 0.0f, 10.0f, 5.0f, 1.0f };    M3DVector4f vLightEyePos; //最终传入到渲染器的矩阵    //m3dTransformVector4使用该函数对光源位置进行变换    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();    }    modelViewMatrix.Translate(0.0f, 0.0f, -2.5f);    modelViewMatrix.PushMatrix();    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),        transformPipeline.GetProjectionMatrix(), vLightEyePos, vTorusColor);    torusBatch.Draw();    modelViewMatrix.PopMatrix(); // 删除之前的参数    modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),        transformPipeline.GetProjectionMatrix(), vLightEyePos, vSphereColor);    sphereBatch.Draw();    // 弹出之前所做的操作    modelViewMatrix.PopMatrix();    modelViewMatrix.PopMatrix();    // 因为是双渲染管道,需要交换后台和前台的渲染信息。    glutSwapBuffers();    //手动渲染    glutPostRedisplay();}void SpecialKeys(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.0f, 1.0f, 0.0f);    if (key == GLUT_KEY_RIGHT)        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);}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");    glutSpecialFunc(SpecialKeys);    glutReshapeFunc(ChangeSize);    glutDisplayFunc(RenderScene);    GLenum err = glewInit();    if (GLEW_OK != err) {        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));        return 1;    }    SetupRC();    glutMainLoop();    return 0;}
0 0
原创粉丝点击