渲染世界的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;}
- 渲染世界的OpenGL<7>基础变换代码分析
- 渲染世界的Opengl<5>基础渲染代码分析
- 渲染世界的OpenGL<6>基础变换
- 渲染世界的Opengl<4>基础渲染
- 渲染世界的OpenGL<8> 基础纹理
- 渲染世界的Opengl<前言>
- 渲染世界的OPENGL<11>模拟光线
- 渲染世界的Opengl<2>着色器基础-着色器语言概述
- 渲染世界的Opengl<1> Opengl基础知识整理
- OpenGL渲染流水线之世界矩阵,相机变换矩阵,透视投影变换矩阵
- 渲染世界的OPENGL<9>GLSL编程-单位着色器
- 渲染世界的OPENGL<14>纹理进阶-多重纹理
- 渲染世界的OPENGL<15>纹理进阶-点精灵
- 渲染世界的OPENGL<16>纹理进阶-纹理数组
- OpenGL基础渲染
- OpenGL基础变换
- OpenGL图形变换——几何变换(世界变换)
- OpenGL——基础变换
- Java过滤器,SpringMVC拦截器之间的区别与执行顺序
- [NOIP2015提高组Day1T2]信息传递_强联通分量
- GetMessage和PeekMessage的区别
- React入门HelloWorld示例
- 使用RestController访问请求报NetworkError: 406 Not Acceptable错误
- 渲染世界的OpenGL<7>基础变换代码分析
- 通过xml定义背景形状
- 认识java
- 来玩Play框架01 简介
- Cocos网络篇[3.2](3) ——Socket连接(1)
- Android——Service 四大组件之二
- spring配置文件的整合
- 第二周 项目2:程序的多文件组织
- ThinkPad E540 插入USB鼠标后自动禁用触摸板