@stepbystep
2015-01-30T17:49:44.000000Z
字数 7385
阅读 8587
实验楼
本项目的代码已经上传到githup,通过如下命令可以下载代码
git clone https://github.com/gostepbystep/EarthDemo.git
在配置好opengl和freeimage环境之后,运行效果图如下:

OpenGL是目前用于开发可移植的、可交互的2D和3D图形应用程序的首选环境,也是目前应用最广泛的计算机图形标准。OpenGL是SGI公司开发的一套的计算机图形处理系统,是图形硬件的软件接口,GL代表图形库(Graphics Library)。OpenGL具有可移植性,任何一个OpenGL应用程序无须考虑其运行环境所在平台与操作系统,在任何一个遵循OpenGL标准的环境下都会产生相同的可视效果。
OpenGL不是一种编程语言,而是一种API(Application Programming Interface,应用程序编程接口)。当我们说某个程序是基于OpenGL的或者说它是个OpenGL程序是,意思是说它是用某种编程语言如C或C++编写的,其中调用了一个或多个OpenGL库函数。作为一种API,OpenGL遵循C语言的调用约定。
OpenGL主要包括三个函数库,它们是核心库、实用函数库和编程辅助库。核心库中包含了OpenGL最基本的命令函数。核心库提供了一百多个函数,这些函数都以”gl”为前缀,用来建立各种各样的几何模型、进行坐标变换、产生光照效果、进行纹理映射、产生雾化效果等所有的二维和三维图形操作。实用函数库是比核心库更高一层的函数库,它提供四十多个函数,这些函数都以”glu”为前缀。由于OpenGL是一个图形标准,是独立于任何窗口系统或操作系统的,在OpenGL中没有提供窗口管理和消息事件响应的函数,也没有鼠标和键盘读取事件的功能,所以在编程辅助库提供了一些基本的窗口管理函数、事件处理函数和简单的事件函数。这类函数以”aux”作为前缀。值得一提的是,目前AUX编程辅助库已经很大程度上被GLUT库取代了。以下介绍以GLUT库为例。
GLUT代表OpenGL应用工具包(OpenGL Utility Toolkit),是一个与窗口系统无关的工具包。它作为AUX库的功能更强的替代品,用于隐藏不同窗口系统API的复杂性。GLUT的子程序的前缀使用”glut”。
linux 下安装OpenGl很简单,只需要安装其所需的库就好了
首先更新源, 实验楼下root密码是shiyanlou
sudo apt-get update
安装OpenGL Library
sudo apt-get install build-essential
安装OpenGL Utilities
OpenGL Utilities 是一组建构于 OpenGL Library之上的工具组,提供许多很方便的函式,使 OpenGL更强大且更容易使用。接下来我们安装OpenGL Utilities
sudo apt-get install libgl1-mesa-dev
安装OpenGL Utility Toolkit
OpenGL Utility Toolkit 是建立在 OpenGL Utilities 上面的工具箱,除了强化了 OpenGL Utilities 的不足之外,也增加了 OpenGL 对于视窗介面支援。
sudo apt-get install libglu1-mesa-dev
安装freeglut3-dev
$sudo apt-get install freeglut3-dev
安装过程截图

用桌面的gedit新建一个文件,输入如下内容
#include <GL/glut.h>void init(void){glClearColor(0.0,0.0,0.0,0.0);glMatrixMode(GL_PROJECTION);glOrtho(-5,5,-5,5,5,15);glMatrixMode(GL_MODELVIEW);gluLookAt(0,0,10,0,0,0,0,1,0);return;}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0,0);glutWireTeapot(3);glFlush();return;}int main(int argc,char *argv[]){glutInit(&argc,argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(0,0);glutInitWindowSize(300,300);glutCreateWindow("OpenGL #D View");init();glutDisplayFunc(display);glutMainLoop();return 0;}
保存在Code目录下的test.c文件,如下图:

在命令行输入如下命令,编译文件,并执行文件
gcc test.c -o test -lGL -lGLU -lglut./test
如出现下图,那么恭喜你,OpenGl已经配置成功了

因为需要贴纹理图,获取bmp文件内容。本项目使用freeimage获取
sudo apt-get install libfreeimage3sudo apt-get install libfreeimage-dev
此后的编译命令需要在末尾加上 -lfreeimage,如下:
gcc main.c -o main -lGL -lGLU -lglut -lfreeimage
GLUT采用一种函数注册的机制来实现OpenGL绘图。它的一般流程是:
新建main.c文件。
把earth.bmp图片从clone的目录中拷贝到与main.c同一目录下。
用geidt修改代码为:
#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#include <GL/gl.h>#include <GL/glu.h>#include <FreeImage.h>#define GLUT_WHEEL_UP 3 //定义滚轮操作#define GLUT_WHEEL_DOWN 4// 定义Bmp的结构体struct _AUX_RGBImageRec {unsigned long sizeX; // X方向大小unsigned long sizeY; // y方向大小unsigned char *data; // 数据地址};typedef struct _AUX_RGBImageRec AUX_RGBImageRec;/*** 定义变量*/GLuint texture[1]; // 存储一个纹理GLfloat rtri; // 存储旋转变量,不断改变其值GLfloat zoom = 1.0f; // 缩放程度,默认为1,用于方大和缩小GLfloat xpos = 0.f; // x方向移动GLfloat ypos = 0.f; // y方向移动/*** 利用freeimage加载bmp图像** 此函数在Linux系统上可以作为常用util调用*/GLboolean LoadBmp(const char* filename,AUX_RGBImageRec* texture_image) {FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(filename, 0);FIBITMAP *dib = FreeImage_Load(fifmt, filename, 0);dib = FreeImage_ConvertTo24Bits(dib);int width = FreeImage_GetWidth(dib);int height = FreeImage_GetHeight(dib);BYTE *pixels = (BYTE*) FreeImage_GetBits(dib);int pix = 0;if (texture_image == NULL)return FALSE;texture_image->data = (BYTE *) malloc(width * height * 3);texture_image->sizeX = width;texture_image->sizeY = height;for (pix = 0; pix < width * height; pix++) {texture_image->data[pix * 3 + 0] = pixels[pix * 3 + 2];texture_image->data[pix * 3 + 1] = pixels[pix * 3 + 1];texture_image->data[pix * 3 + 2] = pixels[pix * 3 + 0];}FreeImage_Unload(dib);return TRUE;}int LoadGLTextures()// 载入位图(调用上面的代码)并转换成纹理{int Status=FALSE; // 状态指示器AUX_RGBImageRec *textureImage; // 创建纹理的存储空间textureImage = malloc(sizeof(AUX_RGBImageRec));// 载入位图,检查有无错误,如果位图没找到则退出if ( LoadBmp("earth.bmp", textureImage) ){Status=TRUE; // 将 Status 设为 TRUEglGenTextures(1, &texture[0]); // 创建纹理// 使用来自位图数据生成 的典型纹理glBindTexture(GL_TEXTURE_2D, texture[0]);// 生成纹理glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage->sizeX, textureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage->data);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // 线形滤波glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // 线形滤波}if (textureImage) // 纹理是否存在{if (textureImage->data) // 纹理图像是否存在{free(textureImage->data); // 释放纹理图像占用的内存}free(textureImage); // 释放图像结构}return Status; // 返回 Status}// 初始化openglvoid init(void){// 载入文理LoadGLTextures();glEnable(GL_TEXTURE_2D); // 启用纹理映射glShadeModel(GL_SMOOTH); // 启用阴影平滑glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景glClearDepth(1.0f); // 设置深度缓存glEnable(GL_DEPTH_TEST); // 启用深度测试glDepthFunc(GL_LEQUAL); // 所作深度测试的类型glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正}/* 当窗口大小发生变化的时候调用 */void reshape (int w, int h){glViewport (0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode (GL_PROJECTION);glLoadIdentity ( );// 利用glOrtho创建一个正交平行的视景体if (w <= h){glOrtho (-1.5, 1.5, -1.5 * ( GLfloat ) h / ( GLfloat ) w,1.5 * ( GLfloat ) h / ( GLfloat ) w, -10.0, 10.0 );}else{glOrtho (-1.5 * ( GLfloat ) w / ( GLfloat ) h,1.5 * ( GLfloat ) w / ( GLfloat ) h, -1.5, 1.5, -10.0, 10.0);}glMatrixMode ( GL_MODELVIEW );glLoadIdentity ( ) ;}/* 定义对键盘的响应函数 */void keyboard ( unsigned char key, int x, int y){/*按Esc键退出*/switch (key) {case 27:exit ( 0 );break;// 按下+的时候zoom缩放增加case '+':zoom += 0.03;break;// 按下-的时候zoom缩放减少case '-':zoom -= 0.03;break;// w,s 分别使模型上下移动case 'w':ypos += 0.03;break;case 's':ypos -= 0.03;break;// a,d 分别使模型左右移动case 'a':xpos -= 0.03;break;case 'd':xpos += 0.03;break;}printf("Enter Key %c zoom=%f, xpos=%f, ypos=%f \n", key);}void display(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存glLoadIdentity(); // 重置当前的模型观察矩阵// 此处加上xpos,ypos 产生移动效果glTranslatef(0.0f+xpos,0.0f+ypos,-5.0f); // 移入屏幕 5 个单位// 此处进行缩放,x,y,z方向均按此比例缩放glScalef(zoom, zoom, zoom);glRotatef(rtri,0.0f,1.0f,0.0f); // 绕Y轴旋转glBindTexture(GL_TEXTURE_2D, texture[0]);glBegin(GL_QUADS);//绘制四边形GLUquadric* quadricObj=gluNewQuadric(); //gluNewQuadric 创建一个新的二次曲面对象gluQuadricTexture(quadricObj,GL_TRUE);gluSphere(quadricObj,1,100,100); //参数1:二次曲面对象指针,参数2:球半径,参数3:Z轴方向片数,经度方向,参数4:Y轴方向片数,维度方向gluDeleteQuadric(quadricObj); //gluDeleteQuadric 删除一个二次曲面对象glEnd();//结束绘制// 通知硬件绘制图形glFinish();return;}/* 处理鼠标事件 */void processMouse(int button, int state, int x, int y){if (state == GLUT_UP && button == GLUT_WHEEL_UP){ // 滚轮向上,表示方大,增加缩放比例zoom += 0.02;glutPostRedisplay();}if (state == GLUT_UP && button == GLUT_WHEEL_DOWN){// 滚轮向下,表示缩小,减少缩放比例if(zoom > 0.02){// 防止zoom太小zoom -= 0.02;}glutPostRedisplay();}}// 自动旋转函数,用于修改绘制时所需要的参数void changeParam( void ){rtri += 0.05f; // 旋转变量自动加上0.05glutPostRedisplay ();}int main(int argc,char *argv[]){/* GLUT环境初始化*/glutInit (&argc, argv);/* 显示模式初始化 */glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);/* 定义窗口大小 */glutInitWindowSize(600,600);/* 定义窗口位置 */glutInitWindowPosition (400, 400);/* 显示窗口,窗口标题为执行函数名 */glutCreateWindow("EarthDemo");/* 调用OpenGL初始化函数 */init ( );/* 注册OpenGL绘图函数 */glutDisplayFunc ( display );/* 注册窗口大小改变时的响应函数 */glutReshapeFunc ( reshape );/* 注册键盘响应函数 */glutKeyboardFunc ( keyboard );/* 注册鼠标事件 */glutMouseFunc( processMouse );/* 注册自动旋转的函数 */glutIdleFunc( changeParam );/* 进入GLUT消息循环,开始执行程序 */glutMainLoop( );return 0;}
编译代码
编译命令需要在末尾加上 -lfreeimage
gcc main.c -o main -lGL -lGLU -lglut -lfreeimage
执行代码
./main
执行结果
点击如下地址,可以查看视频录制结果
http://7u2m19.com1.z0.glb.clouddn.com/earth-out-2.ogv
OpenGl 在linux上做一些简单的界面显示效果非常好的。用起来也很方便,大家可以参考NeHe OpenGl教程学习相关知识。