今天来分享一下计算机图形学及openGL和glut的使用
实验一 OpenGL编程初步
实验目的:
通过实验掌握下列知识:
1.OpenGL glut的安装;
2.OpenGL编程初步;
3.熟悉OpenGL glut下的编程框架;
4.使用OpenGL绘制点线等图元。
内容及步骤:
一、在Code Blocks环境下安装OpenGL(使用GLUT)
1、安装GLUT
下载GLUT安装包,解压后包含5个文件:
glut.h, glut.lib, glut32.lib, glut.dll, glut32.dll
安装GLUT包的方法:
(1)拷贝glut.dll和glut32.dll到C:\WINDOWS\SysWOW64或者C:\WINDOWS\system32
(2)拷贝glut.lib和glut32.lib到 C:\Program Files\CodeBlocks\MinGW\lib
(3)拷贝glut32.h到 C:\Program Files\CodeBlocks\MinGW\include\GL
注意:(2)(3)可能由于Code Block安装的位置不同而拷贝的地方不同,可能是把C盘改为D盘。
2、CodeBlocks上新建GLUT工程
(1)新建工程,选择GLUT project,一路确认即可,完成后可看到系统自动生成了一个 main.cpp文件,里面有若干行代码;
(2)如果需要配置GLUT的目录,请选择C:\Program Files\CodeBlocks\MinGW;
(3)main.cpp最前面添加头文件#include <windows.h>,注意这一步非常重要;
(4)点击Project—>build options—>link libraries,点击add,选择刚才复制到mingw\lib目录下的glut32.lib文件,提示选择no,然后确定,然后直接编译运行程序就可看到效果了
3、编写GLUT程序
在新建的GLUT工程的基础上修改得到自己的程序。
二、在VC++6.0环境下安装OpenGL(使用GLUT,不推荐,有需要的同学再看这部分)
本文档描述如何在MS Visual C++ 6.0中使用GLUT。
- 安装GLUT
下载GLUT安装包,解压后包含5个文件:
glut.h, glut.lib, glut32.lib, glut.dll, glut32.dll
安装GLUT包的方法:
(1)拷贝glut.dll和glut32.dll到C:\WINDOWS\system或者C:\WINDOWS\system32
(2)拷贝glut.lib和glut32.lib到D:\Program Files\Microsoft Visual Studio\VC98\Lib
(3)拷贝glut32.h到D:\Program Files\Microsoft Visual Studio\VC98\Include\GL
注意:(2)(3)可能由于Visual C++ 6.0安装的位置不同而拷贝的地方不同,可能是把D盘改为C盘。 - 建立Visual Studio 工程
(1)建立一个新的工程(File->New->Project)
(2)在Project页面选择Win32 Console Application, 输入工程名, 然后点击OK.
(3)在应用程序向导对话框中, 选中An empty project单选框, 然后点击Finish
- 添加代码
(1)添加新项(Project->Add To Project->New…)
(2)在File页面选择C++Source File, 写入文件名, 点击OK.
(3)输入以下的代码到文件中.
Example1.cpp
#include <GL/glut.h> // (or others, depending on the system in use)
void init (void)
{
glClearColor (1.0, 1.0, 1.0, 0.0); // 指定清空颜色(背景色)为白色
gluOrtho2D (0.0, 400.0, 0.0, 300.0); //指定二维坐标系中被显示的区域
}
void display (void)
{
glClear (GL_COLOR_BUFFER_BIT); // 清空显示窗口
glColor3f (0.0, 0.0, 1.0); // 指定前景色(当前绘制颜色)为蓝色
glBegin (GL_LINES);
glVertex2i (180, 15); // 指定顶点
glVertex2i (10, 145);
glEnd ( );
glFlush ( ); // 使绘制立即反映到屏幕上
}
void main (int argc, char** argv)
{
glutInit (&argc, argv); // 初始 GLUT.
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); //设定显示模式
glutInitWindowPosition (50, 100); // 设定窗口位置
glutInitWindowSize (400, 300); // 设定窗口大小
glutCreateWindow (“An Example OpenGL Program”); // 用前面指定参数创建窗口,并定义窗口名称
init ( ); // 进行一些初始化工作
glutDisplayFunc (display); // 指定绘制的回调函数
glutMainLoop ( ); // 进入无穷循环,等待事件处理
}
说明:
如果使用GLUT头文件, 它将自动包含其它GLUT头文件, 否则需要包含:
#include <GL/gl.h>
#include <GL/glu.h>
所以只需要包含
#include <GL/glut.h>
4 编译和运行程序
如果使用最新版的GLUT, 并且头文件包含的是#include <GL/glut.h> ,现在已经可以运行程序,。
生成解决方案(Build->Build OpenGLl Project.exe)
运行程序(Build->Execute OpenGL Project.exe)
查看运行结果
- 发布程序
如果你使用GLUT编写程序, 则在要发布程序时(在没有glut包的计算机上运行), 需要把glut32.dll拷贝到用户机器的C:\WINDOWS\System目录下,或与发布的程序放到一个文件夹中。
三、OpenGL glut下的编程框架
OpenGL实用函数工具包(OpenGL Utility Toolkit, GLUT)提供了一个和窗口系统无关的工具包,用于隐藏不同窗口系统API的复杂性,使得对窗口的操作非常方便。
一个简单的OpenGL GLUT程序如下:
#include <GL/glut.h>
void init(void)
{//初始化函数,也可以不要
glMatrixMode (GL_PROJECTION); //指定投影矩阵
gluOrtho2D (-1.0, 1.0, -1.0, 1.0); //指定显示的区域
}
void myDisplay(void)
{// 图形绘制回调函数,通常把图形绘制代码写到这个函数里面
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5f, -0.5f, 0.5f, 0.5f); //用自己的绘制代码或函数把这一句替换
glFlush();
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow(“第一个OpenGL程序”);
init();
glutDisplayFunc(&myDisplay);
glutMainLoop();
}
编译运行后得到:
该程序的作用是在一个黑色的窗口中央画一个白色的矩形。下面对各行语句进行说明。
首先,需要包含头文件#include <GL/glut.h>,这是GLUT的头文件。
本来OpenGL程序一般还要包含<GL/gl.h>和<GL/glu.h>,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。
然后看main函数。void main(int argc, char *argv[]),这个是带命令行参数的main函数,注意main函数中除了init(),其它的各语句全部以glut开头。这种以glut开头的函数都是GLUT工具包所提供的函数,下面对用到的几个函数进行介绍。
1、glutInit,对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。其格式比较死板,一般照抄这句glutInit(&argc, argv)就可以了。
2、 glutInitDisplayMode,设置显示方式,其中GLUT_RGB表示使用RGB颜色,与之对应的还有GLUT_INDEX(表示使用索引颜色)。GLUT_SINGLE表示使用单缓存,与之对应的还有GLUT_DOUBLE(使用双缓存)。
3、glutInitWindowPosition,设置窗口在屏幕中的位置。
4、glutInitWindowSize,设置窗口的大小。
5、glutCreateWindow,根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。
6、init,初始化函数,做一些初始化的工作,有时也可以不要。
7、glutDisplayFunc,设置一个回调函数,当需要进行画图时,这个函数就会被调用。
8、glutMainLoop,进行一个消息循环。(这个可能初学者也不太明白,现在只需要知道这个函数可以显示窗口,并且等待窗口关闭后才会返回,这就足够了。)
在glutDisplayFunc函数中,我们设置了“当需要画图时,请调用myDisplay函数”。于是myDisplay函数就用来画图。观察myDisplay中的三个函数调用,发现它们都以gl开头。这种以gl开头的函数都是OpenGL的标准函数,下面对用到的函数进行介绍。
1、glClear,清除。GL_COLOR_BUFFER_BIT表示清除颜色,glClear函数还可以清除其它的东西,但这里不作介绍。
2、glRectf,画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标。
3、glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。
总结:在以后的实验编程中,我们都采用如上例所示的OpenGL GLUT编程的框架,也就是:
#include <GL/glut.h>
void init(void)
{//初始化工作
glMatrixMode (GL_PROJECTION); //指定投影矩阵
gluOrtho2D (0.0, 400.0, 0.0, 400.0); //指定显示的区域
}
void myDisplay(void)
{//图形绘制
glClear(GL_COLOR_BUFFER_BIT);
//加绘制代码
glFlush();
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow(“窗口名称”);
init();
glutDisplayFunc(&myDisplay);
glutMainLoop();
}
四、绘制基本图元
我们知道数学(具体的说,是几何学)中有点、直线和多边形的概念,但这些概念在计算机中会有所不同。
数学上的点,只有位置,没有大小。一般情况下,OpenGL中的点将被画成单个的像素。
数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,线段可以由两个端点来确定。
多边形是由多条线段首尾相连而形成的闭合区域。OpenGL规定,一个多边形必须是一个“凸多边形”(其定义为:多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的)。多边形可以由其边的端点(这里可称为顶点)来确定。
可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个“曲面”。
因此,“点”是一切的基础。
在OpenGL中指定顶点是通过OpenGL提供了一系列函数。它们都以glVertex开头,后面跟一个数字和1~2个字母。例如:
glVertex2d glVertex2f glVertex3f glVertex3fv等等。
数字表示参数的个数,2表示有两个参数,3表示三个,4表示四个。
字母表示参数的类型,
s表示16位整数(OpenGL中将这个类型定义为GLshort),
i表示32位整数(OpenGL中将这个类型定义为GLint),
f表示32位浮点数(OpenGL中将这个类型定义为GLfloat),
d表示64位浮点数(OpenGL中将这个类型定义为GLdouble)。
v表示传递的几个参数将使用指针的方式,见下面的例子。
例如,以下五个代码段的功能是等效的:
(一)glVertex2i(1, 3);
(二)glVertex2f(1.0f, 3.0f);
(三)glVertex3f(1.0f, 3.0f, 0.0f);
(四)glVertex4f(1.0f, 3.0f,0.0f,1.0f);
(五)GLfloat VertexArr3[]={1.0f, 3.0f, 0.0f};
glVertex3fv(VertexArr3);
假设现在我已经指定了若干顶点,那么OpenGL是如何知道我想拿这些顶点来干什么呢?是一个一个的画出来,还是连成线?或者构成一个多边形?或者做其它什么事情?
为了解决这一问题,OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略),并由glBegin来指明如何使用这些点。
例如:
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(3.0f, 2.0f);
glEnd();
这里这两个点将分别被画出来。如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
我们还可以指定更多的顶点,然后画出更复杂的图形。glBegin支持的方式有
GL_POINTS 单个顶点集
GL_LINES 多组双顶点线段
GL_LINE_STRIP 不闭合折线
GL_LINE_LOOP 闭合折线
GL_POLYGON 单个简单填充凸多边形
GL_QUADS 多组独立填充四边形
GL_QUAD_STRIP 连续填充四边形串
GL_TRAINGLES 多组独立填充三角形
GL_TRAINGLE_STRIP 线型连续填充三角形串
GL_TRAINGLE_FAN 扇形连续填充三角形串
五、上机编程实习任务
用给定的框架,创建一个800×600像素的窗口,窗口位置为(0,0),窗口名称为“OpenGL基本图元绘制”,绘制以下图元:
(1)单个点(100,200);(GL_POINTS)
(2)线段,端点为(0, 0)和(300,100);(GL_LINES)
(3)三角形,端点为(400,300),(600,300)和(500,500);(GL_LINE_LOOP)
(4)填充三角形,端点为(400,50),(600,50)和(500,250);(GL_POLYGON)