OpenGL--代码解读
来源:互联网 发布:管家婆打印软件 编辑:程序博客网 时间:2024/06/13 18:30
// SphereWorld.cpp// OpenGL SuperBible// New and improved (performance) sphere world// Program by Richard S. Wright Jr.#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>#ifdef __APPLE__#include <glut/glut.h>#else#define FREEGLUT_STATIC#include <GL/glut.h>#endif#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() { // Initialze Shader Manager shaderManager.InitializeStockShaders(); glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // This makes a torus gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30); // This make a sphere 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(); // Randomly place the spheres 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); } }///////////////////////////////////////////////////// Screen changes size or is initializedvoid ChangeSize(int nWidth, int nHeight) { glViewport(0, 0, nWidth, nHeight); // Create the projection matrix, and load it on the projection matrix stack viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f); projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix()); // Set the transformation pipeline to use the two matrix stacks transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix); }// Called to draw scenevoid RenderScene(void) { // Color values 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 }; // Time Based animation static CStopWatch rotTimer; float yRot = rotTimer.GetElapsedSeconds() * 60.0f; // Clear the color and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the current modelview matrix (the identity matrix) modelViewMatrix.PushMatrix(); M3DMatrix44f mCamera; cameraFrame.GetCameraMatrix(mCamera); modelViewMatrix.PushMatrix(mCamera); // Transform the light position into eye coordinates M3DVector4f vLightPos = { 0.0f, 10.0f, 5.0f, 1.0f }; M3DVector4f vLightEyePos; m3dTransformVector4(vLightEyePos, vLightPos, mCamera); // Draw the ground 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(); } // Draw the spinning Torus modelViewMatrix.Translate(0.0f, 0.0f, -2.5f); // Save the Translation modelViewMatrix.PushMatrix(); // Apply a rotation and draw the torus 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(); // "Erase" the Rotation from before // Apply another rotation, followed by a translation, then draw the sphere 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(); // Restore the previous modleview matrix (the identity matrix) modelViewMatrix.PopMatrix(); modelViewMatrix.PopMatrix(); // Do the buffer Swap glutSwapBuffers(); // Tell GLUT to do it again glutPostRedisplay(); }// Respond to arrow keys by moving the camera frame of referencevoid 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的大致结构。
首先是一些头文件的包含,因为会用到OpenGL的一些API。
GLShaderManager是着色管理器,没有着色管理器,就没法着色;作色存储器还提供存储着色器,能够进行一些初步和基本的渲染操作。
在Mac和Windows|Linux上,我们将会采用不同的处理器宏定义
#ifdef __APPLE__#include <glut/glut.h>#else#define FREEGLUT_STATIC#include <GL/glut.h>#endif
main()函数作为程序的入口函数,得先从这边来分析。
gltSetWorkingDirectory(argv[0]);
上函数是用来设置当前工作目录。
//传递命令行参数并初始化GLUT库glutInit(&argc, argv);//告诉GLUT库,在创建窗口时要使用哪种类型的显示模式//GLUT_DOUBLE表示使用双缓冲窗口,一般用来生成动画效果//GLUT_RGB表示使用RGB颜色模式//GLUT_DEPTH表示我们可以进行深度测试glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//指明GLUT窗口的大小,并以OpenGL SphereWorld为标题创建窗口。glutInitWindowSize(800,600);glutCreateWindow("OpenGL SphereWorld");
GLUT内部运行一个本地消息循环,拦截适当的消息,然后调用相应的回调函数。我们必须为窗口改变大小而设置一个回调函数,以便能够设置视点,还要注册一个函数来包含OpenGL渲染代码。如下:
glutReshapeFunc(ChangeSize);glutDisplayFunc(RenderScene);
初始化OpenGL驱动程序,并检查初始化是否出现问题
GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); return 1; }
在任何OpenGL函数起作用之前都得创建一个渲染环境,在这个函数里面我们会进行预加载纹理,建立几何图形、渲染器等工作。
SetupRC();
开始上面讲过的本地消息循环,并结束main函数。
glutMainLoop(); return 0;
glutMainLoop函数被调用之后,在主窗口被关闭之前都不会返回,一个应用程序只需要调用一次。这个函数负责处理所有操作系统特定的消息、按键动作等,直到我们关闭程序为止。它还能确保我们的这些回调函数被正确地调用。
ChangeSize函数中:
glViewport(x, y, w, h)
定义窗口与视口之间的关系,x参数和y参数代表窗口中视口的左下角坐标,w和h代表视口的宽带和高度,如下图所示:
glViewport(0, 0, nWidth, nHeight);
SetupRC中:
glClearColor是用来设置背景颜色,该函数不会立即清除背景,而是设置在以后颜色缓冲区被清除时(调用glClear函数)使用的颜色。
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
当设置OpenGL窗口时,我们制定要一个双缓冲渲染环境。这就意味着将在后台缓冲区进行渲染,然后结束的时候交换到前台缓冲区。这种形式能够防止观察者可能看到伴随着动画帧与动画帧之间闪烁的渲染过程。OpenGL有一个特定的函数来完成上述工作:
glutSwapBuffers();
刷新显示:告诉窗口需要更新内容
glutPostRedisplay
该函数来告诉GLUT发生了某些变化,应该对场景重新进行渲染
- OpenGL--代码解读
- 代码解读
- 代码解读
- 解读OpenGL棋盘纹理贴图
- 条码打印机代码解读!
- 解读eXtremeComponents代码结构
- FFMPEG框架代码解读
- DiskPerf代码解读
- Android震动代码解读
- LightweightSystem.setContents代码解读
- phpcms v9代码解读
- SEP4020 PWM代码解读
- Cassandra Compaction代码解读
- gpio_request 原形代码解读
- 解读Helloworld的代码
- live555代码解读
- freemodbus代码解读
- zookeeper客户端代码解读
- Win 10关机后电源灯不停闪烁的解决办法
- equals方法的重写1
- Struts 获取HttpServletRequest和HttpServletResponse的两种方式
- IOS开发之实现App消息推送(最新)
- 栈
- OpenGL--代码解读
- /etc目录介绍
- @RequestBody接收json字符串,自动将日期字符串转换为java.util.Date
- 独木舟问题
- React-Native 集成AMap实例
- Android学习11
- poj3468-线段树详解
- 作业:计数器仿真实验
- Ubuntu下切换JDK版本