计算机图形学试验指导书1Word文档格式.docx
《计算机图形学试验指导书1Word文档格式.docx》由会员分享,可在线阅读,更多相关《计算机图形学试验指导书1Word文档格式.docx(71页珍藏版)》请在冰豆网上搜索。
三、实验内容及步骤26
四、实验习题27
实验四交互式绘图技术28
一、实验要求和目的28
二、实验内容及步骤28
三、实验习题33
实验五光照处理34
一、实验要求和目的34
二、相关知识提要34
三、实验内容及步骤37
四、实验习题40
实验六纹理映射41
一、实验要求和目的41
二、相关知识提要41
三、实验内容及步骤44
四、实验习题45
实验七曲面生成46
一、实验要求和目的46
二、相关知识提要46
三、实验内容及步骤49
四、实验习题54
实验八综合实验(供优秀学生选做)55
一、实验要求和目的55
二、实验内容55
三、实验步骤55
1OpenGL与三维图形
1.1OpenGL介绍
我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,必须能在三维空间描绘这些物体。
最近几年计算机图形学的发展使得三维表现技术得以形成,这些三维表现技术使我们能够再现三维世界中的物体,能够用三维形体来表示复杂的信息,这种技术就是可视化(Visualization)技术。
OpenGL已被认为是高性能图形和交互式视景处理的标准,目前包括ATT公司UNIX软件实验室、IBM公司、DEC公司、SUN公司、HP公司、Microsoft公司和SGI公司在内的几家在计算机市场占领导地位的大公司都采用了OpenGL图形标准。
值得一提的是,由于Microsoft公司在WindowsNT、Windows97及后续版本中提供OpenGL图形标准,OpenGL在微机中广泛应用,人们可以在微机上实现三维图形应用,如CAD设计、仿真模拟、三维游戏等。
OpenGL实际上是一种图形与硬件的接口。
它包括了100多个图形函数,开发者可以用这些函数来建立三维模型和进行三维实时交互。
为了实现一个完整功能的图形处理系统,设计一个与OpenGL相关的系统结构为:
其最底层是图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenGL,第五层为应用软件。
由于许多在计算机界具有领导地位的计算机公司纷纷采用OpenGL作为三维图形应用程序设计界面,OpenGL应用程序具有广泛的移植性。
因此,OpenGL已成为目前的三维图形开发标准,是从事三维图形开发工作的技术人员所必须掌握的开发工具。
OpenGL作为一个与硬件独立的图形接口,它不提供与硬件密切相关的设备操作函数,同时,它也不提供描述类似于飞机、汽车、分子形状等复杂形体的图形操作函数。
用户必须从点、线、面等最基本的图形单元开始构造自己的三维模型。
OpenGL提供了以下的对三维物体的绘制方式:
(1)线框绘图方式(wireframe)--这种方式仅绘制三维物体的网格轮廓线;
(2)深度优先线框绘图方式(depth_cued)--用线框方式绘图,增加模拟人眼看物体一样的效果,远处的物体比近处的物体要暗些;
(3)反走样线框绘图方式(antialiased)--用线框方式绘图,绘图时采用反走样技术以减少图形线条的参差不齐;
(4)平面消隐绘图方式(flat_shade)--对模型的隐藏面进行消隐,对模型的平面单元按光照程度进行着色但不进行光滑处理;
(5)光滑消隐绘图方式(smooth_shade)--对模型进行消隐按光照渲染着色的过程中再进行光滑处理,这种方式更接近于现实;
(6)加阴影和纹理的绘图方式(shadows,textures)--在模型表面贴上纹理甚至于加上光照阴影,使得三维景观象照片一样;
(7)运动模糊的绘图方式(motion-blured)--模拟物体运动时人眼观察所感觉的动感现象;
(8)大气环境效果(atmosphere-effects)--在三维景观中加入如雾等大气环境效果,使人身临其境;
(9)深度域效果(depth-of-effects)--类似于照相机镜头效果,模型在聚焦点处清晰,反之则模糊。
整个OpenGL的基本工作流程如下图
图1-1OpenGL基本工作流程
其中几何顶点数据包括模型的顶点集、线集、多边形集,这些数据经过流程图的上部,包括运算器、逐个顶点操作等;
像素数据包括像素集、影像集、位图集等,像素数据的处理方式与几何顶点数据的处理方式是不同的,但它们都经过光栅化、逐个片元(Fragment)处理直至把最后的光栅数据写入帧缓冲器。
在OpenGL中的所有数据包括几何顶点数据和像素数据都可以被存储在显示列表中或者立即可以得到处理。
OpenGL要求把所有的几何图形单元都用顶点来描述,这样运算器和逐个顶点计算操作都可以针对每个顶点进行计算和操作,然后进行光栅化形成图形片元;
对于像素数据,像素操作结果被存储在纹理组装用的内存中,再象几何顶点操作一样光栅化形成图形片元。
整个流程操作的最后,图形片元都要进行一系列的逐个片元操作,这样最后的像素值被送入帧缓冲器实现图形的显示。
在OpenGL中进行主要的图形操作直至在计算机屏幕上渲染绘制出三维图形景观的基本步骤为:
(1)根据基本图形单元建立景物模型,并且对所建立的模型进行数学描述(OpenGL中把点、线、多边形、图像和位图都作为基本图形单元);
(2)把景物模型放在三维空间中的合适的位置,并且设置视点(viewpoint)以观察所感兴趣的景观;
(3)计算模型中所有物体的色彩,其中的色彩根据应用要求来确定,同时确定光照条件、纹理粘贴方式等;
(4)把景物模型的数学描述及其色彩信息转换至计算机屏幕上的像素,这个过程也就是光栅化(rasterization)。
在这些步骤的执行过程中,OpenGL可能执行其他的一些操作,例如自动消隐处理等。
另外,景物光栅化之后被送入帧缓冲器之前还可以根据需要对像素数据进行操作。
OpenGL能够对整个三维模型进行渲染着色,从而绘制出与客观世界十分类似的三维景象。
另外OpenGL还可以进行三维交互、动作模拟等。
具体的功能主要有以下这些内容。
(1)模型绘制
OpenGL能够绘制点、线和多边形。
应用这些基本的形体,可以构造出几乎所有的三维模型。
OpenGL通常用模型的多边形的顶点来描述三维模型。
(2)模型观察
在建立了三维景物模型后,就需要用OpenGL描述如何观察所建立的三维模型。
观察三维模型是通过一系列的坐标变换进行的。
模型的坐标变换使观察者能够在视点位置观察与视点相适应的三维模型景观。
在整个三维模型的观察过程中,投影变换的类型决定观察三维模型的观察方式,不同的投影变换得到的三维模型的景象也是不同的。
最后的视窗变换则对模型的景象进行裁剪缩放,即决定整个三维模型在屏幕上的图像。
(3)颜色模式的指定
OpenGL应用了一些专门的函数来指定三维模型的颜色。
程序开发者可以选择二个颜色模式,即RGBA模式和颜色表模式。
在RGBA模式中,颜色直接由RGB值来指定;
在颜色表模式中,颜色值则由颜色表中的一个颜色索引值来指定。
开发者还可以选择平面着色和光滑着色二种着色方式对整个三维景观进行着色。
(4)光照应用
用OpenGL绘制的三维模型必须加上光照才能更加与客观物体相似。
OpenGL提供了管理四种光(自发光、环境光、镜面光和漫反射光)的方法,另外还可以指定模型表面的反射特性。
(5)图像效果增强
OpenGL提供了一系列的增强三维景观的图像效果的函数,这些函数通过反走样、混合和雾化来增强图像的效果。
反走样用于改善图像中线段图形的锯齿而更平滑,混合用于处理模型的半透明效果,雾使得影像从视点到远处逐渐褪色,更接近于真实。
(6)位图和图像处理
OpenGL还提供了专门对位图和图像进行操作的函数。
(7)纹理映射
三维景物因缺少景物的具体细节而显得不够真实,为了更加逼真地表现三维景物,OpenGL提供了纹理映射的功能。
OpenGL提供的一系列纹理映射函数使得开发者可以十分方便地把真实图像贴到景物的多边形上,从而可以在视窗内绘制逼真的三维景观。
(8)实时动画
为了获得平滑的动画效果,需要先在内存中生成下一幅图像,然后把已经生成的图像从内存拷贝到屏幕上,这就是OpenGL的双存技术(doublebuffer)。
OpenGL提供了双缓存技术的一系列函数。
(9)交互技术
目前有许多图形应用需要人机交互,OpenGL提供了方便的三维图形人机交互接口,用户可以选择修改三维景观中的物体。
1.2OpenGL函数的语法
OpenGL函数以“gl”为前缀,并把组成函数名的每个单词的首字母进行大写(glClearColor())。
类似地,OpenGL还定义了以前缀GL_开头的常量,所有单词使用大写形式,并以下划线分割(例如GL_COLOR_BUFFER_BIT)。
此外,有些函数,同一函数有多个不同版本,如glColor3f(),glColor3ub(),glColor3bv()等都用于设置当前绘图颜色,其中“3”表示函数接受3个参数,“f”表示参数类型为浮点数,“ub”表示参数类型为8位无符号整数,“bv”表示参数是含3个元素的数组,数组中每个元素为8位无符号整数。
OpenGL为同一函数定义不同参数类型的版本主要为了方便用户根据自己的数据格式向OpenGL传递参数。
表1-1列出用于指定数据类型的后缀字母,以供参考:
后缀
数据类型
对应典型C语言
OpenGL类型定义
b
8位整数
signedchar
GLbyte
s
16位整数
short
GLshort
i
32位整数
int或long
GLint,GLsizei
f
32位浮点数
float
GLfloat,GLclampf
d
64位浮点数
double
GLdouble,GLclampd
ub
8位无符号整数
unsignedchar
GLubyte,GLboolean
us
16位无符号整数
unsignedshort
GLushort
ui
32位无符号整数
unsignedint或unsignedlong
GLuint,GLenum,GLbitfield
1.3OpenGL是状态机
OpenGL是个状态机。
设置它的各种状态(或模式),则这些状态一直生效,直到它们被修改。
OpenGL所维护的状态变量很多,例如颜色,控制当前视图和投影变换,直线和多边形点画模式,多边形绘图模式,像素包装约定,光照位置和特征,被绘制物体的材料属性等。
许多表示模式的状态变量可以用glEnable()和glDisable()函数进行启用和禁用。
每个状态变量(或模式)都有一个默认值。
任何时候,都可以向系统查询每个状态变量的当前值。
使用6个函数之一完成这个任务:
glGetBooleanv(),glGetDoublev(),glGetFloatv(),glGetIntegerv(),glGetPointerv(),glIsEnabled()。
所选择的具体函数取决于希望返回的结果的数据类型。
有些状态变量还有更为特定的查询函数,可以查阅《OpenGL编程指南》等参考书,在此不在详述。
1.4OpenGL相关的函数库
OpenGL提供了一组功能强大但又比较原始的渲染函数,所有高层绘图操作必须根据这些函数完成。
同样,OpenGL程序必须使用窗口系统的底层机制。
有一些函数库可以用来帮助简化任务,它们是:
(1)OpenGL工具函数库(GLU)包含了一些函数,它们利用低层OpenGL函数来执行诸如为特定视图定向和投影设置矩阵、多边形分格化以及表面渲染等任务。
所有OpenGL实现都把这个函数库作为它的一部分。
GLU函数都使用前缀glu。
(2)所有的窗口系统都提供一个函数库,对该窗口系统的功能进行扩展,以支持OpenGL渲染。
对于MicrosoftWindows,WGL函数提供了Windows到OpenGL的接口。
所有的WGL函数都使用前缀wgl。
(3)OpenGL实用工具包(GLUT)是MarkKilgard所编写的一个独立于窗口系统的工具包,其目的是隐藏不同窗口系统API的复杂性。
GLUT函数使用前缀glut。
1.5OpenGL的缓冲区
OpenGL需要用到4个缓冲区进行图形显示,它们分别是:
颜色缓存、深度缓存、模板缓存和累积缓存。
这里我们只介绍颜色缓存和深度缓存的基本概念,更多内容请参阅《OpenGL编程指南》。
1.5.1颜色缓存
颜色缓存由红、绿、蓝、alpha位等位平面(bitplane)组成的,有前缓存(frontbuffer)、后缓存(backbuffer)、左前(front_left)和右前(front_right)缓存、左后(back_left)和右后(back_right)缓存。
左前缓存是必须的颜色缓存。
前缓存是可见缓存,后缓存是不可见缓存。
前后缓存技术可以实现动画操作。
与颜色缓存相关的主要函数有:
(1)清除颜色缓存:
glClear(GL_COLOR_BUFFER_BIT),用于清除当前显示缓冲区内容,为开始新的绘制做好准备。
(2)设置清除颜色:
glClearColor(red,green,blue,alpha),用当前颜色(red,green,blue,alpha)清除当前显示缓冲区内容,为开始新的绘制做好准备。
(3)屏蔽颜色缓存:
glColorMask(),分别设置红、绿、蓝和alpha的可写属性。
(4)选择颜色缓存:
glDrawBuffer(),对双缓存中的一个进行选择。
(5)交换颜色缓存:
swapBuffer(),交换前后缓存中的颜色,以实现动画。
1.5.2深度缓存
深度缓存也叫Z-buffer,它记录每个像素点所对应的物体点到视点的距离,由此决定表面的可见性。
在进行消隐的时候,OpenGL必须知道各物体间的相对位置关系,从而模拟出物体相互遮挡的效果,因此,需要进行深度测试。
而深度测试的结果就生成了深度缓存。
与深度缓存相关的OpenGL操作主要有:
(1)清除深度缓存:
glClear(GL_DEPTH_BUFFER_BIT),用于清除当前显示缓冲区内容,为开始新的绘制做好准备。
(2)设置清除值:
glClearDepth(1.0),1.0为最大深度。
(3)屏蔽深度缓存:
glDepthMask(GL_TRUE),表示可以写深度缓存;
glDepthMask(GL_FALSE),表示禁止写深度缓存。
(4)启动和关闭深度测试:
glEnableGL_DEPTH_TEST),表示开启深度测试;
glDisable(GL_DEPTH_TEST),表示禁止深度测试。
(5)确定测试条件:
glDepthFunc(),根据函数参数确定测试方式,具体的参数说明请参考实验五。
确定深度范围:
glDepthRange(GLclampdzNear,GLclampdzFar),参数zNear和zFar分别说明视景体的前景和后景面向窗口坐标映射的规格化坐标,便于后续使用。
2MicrosoftVisualC++6.0MFC编程基础
2.1MFC事件驱动简介
用OpenGL编写的程序结构类似于用其他语言编写的程序。
实际上,OpenGL是一个丰富的三维图形函数库,编写OpenGL程序并非难事,只需在基本C语言中调用这些函数,用法同TurboC、VC++等类似。
微软基础类库(Microsoftfoundationclass,MFC)是微软为Windows程序员提供的一个面向对象的Windows编程接口,它大大简化了Windows编程工作,使开发人员不必从头设计创建和管理一个标准Windows应用程序所需的程序,节省了时间;
同时它提供了大量代码,指导用户编程时实现某些技术和功能。
在事件驱动编程方面,通过MFC的核心——消息映射机制,定义一个消息与处理函数的对照表,实现消息处理的分离编程。
每当产生一个事件,便可通过这个对照表找到相应的消息处理函数,执行这个函数完成相应功能;
相应的,程序员只需利用VC集成开发环境提供的工具指定当鼠标在哪个GUI对象上操作时执行哪个函数即可,MFC事件驱动编程模式如图2.1所示。
2.1MFC中事件驱动编程模式
为了提高交互式绘图性能,为以后二维/三维开发打下基础,考虑到MicrosoftVisualC++的MFC开发环境提供了GDI工具及相对较好的交互式绘图环境,所以,本书采用该环境进行二维/三维图形的实验。
2.2MFC事件驱动编程
2.2.1建立MFC工程
步骤一:
打开MicrosoftVisualC++6.0应用程序。
在菜单中选择“文件”—>
“新建”打开建立用户应用程序对话框,在对话框的“工程”页面左边选择MFCAppWizard[exe];
在右边“位置”编辑框中键入要建的项目存放位置,例如D盘根目录;
在右边“工程”编辑框中键入要建的项目的名称,例如MFCTest,这时我们会看到“位置”编辑框中信息变为“D:
\MFCTest”,表示我们的项目文件都将存放在这个目录中。
如图2.2所示。
图2.2:
建立MFC应用程序
步骤二:
我们点击“确定”按钮进行下一步设置。
在“MFCAppWizard–Step1”对话框中有“S单个文档”、“M多个文档”“D基本对话框”三个选项。
“S单个文档”表示用户程序一次只能打开一个文档窗口;
“M多个文档”表示用户程序除了一个文档主窗口外,还可以打开若干个显示不同文档的小窗口,即子窗口;
“D基本对话框”表示用户程序的界面是对话框形式的。
这里我们选择“S单个文档”,然后,单击“下一个”按钮。
如图2.3所示。
图2.3:
MFCAppWizard–Step1
步骤三:
“MFCAppWizard–Step2of6”对话框是关于所建立的程序是否用到数据库,我们选择“否”,然后,单击“下一个”按钮。
步骤四:
“MFCAppWizard–Step3of6”对话框是关于所建立的程序是否用到复合文档,我们选择“否”,然后,单击“下一个”按钮。
步骤五:
“MFCAppWizard–Step4of6”对话框是关于所建立的程序的特点及是否支持打印及预览,我们选择其默认设置,单击“下一个”按钮。
步骤六:
“MFCAppWizard–Step5of6”对话框是关于所建立的程序的风格等的设置,我们选择其默认设置,单击“下一步”按钮。
步骤七:
“MFCAppWizard–Step6of6”对话框我们看到VC开发环境已经为我们的用户程序生成了四个类,包括它们的类名、头文件(.h)、实现文件(.cpp)及基类。
单击“完成”按钮,完成MFC应用程序框架的建立。
如图2.4所示。
图2.4:
MFCAppWizard–Step6of6
完成了MFC应用程序框架后我们看到MFC用户程序开发环境,如图2.5所示。
图2.5:
MFC用户程序开发环境
开发环境的左边是项目工作区,有三页,依次为类视图(ClassView)、资源视图(ResourceView)及文件视图(FileView),分别对应生成的类、项目资源及相应文件。
开发环境右边文档区中则显示相应类的具体代码。
2.2.2编译和运行MFC用户程序项目
现在开发环境已为我们搭建好了框架,我们只需对其进行编译和连接就可以得到一个用户程序的框架。
在前面打开MFCTest项目中,选择菜单的“编译”(Build)—>
“全部重建”(RebuildAll),对刚才生成的应用程序框架进行编译和连接。
成功后在开发环境的输出栏里看到“MFCTest.exe-0error(s),0warning(s)”提示。
选择菜单的“编译”—>
“执行MFCTest.exe”,可看到生成的MFC应用程序框架。
如图2.6所示。
图2.6:
MFCTest应用程序框架
2.2.3关闭和打开用户程序项目
要关闭MFCTest项目,只需选择菜单的“文件”—>
“关闭工作区”(CloseWorkspace);
反之,要打开一个已存在的用户程序项目选择菜单项“文件”—>
“打开工作区”(OpenWorkspace),在弹出的文件对话框中找到要打开的项目名称,这里是D:
\MFCTest\MFCTest.dsw。
如图2.7所示。
图2.7:
打开MFCTest项目
2.2.4在MFC中建立新类的方法
右键单击项目工作区的类视图页面的项目名称,在右键菜单中选择“NewClass…”,弹出如图2.8所示“新类(NewClass)”对话框:
图2.8建立新类
在Classtype中选择新建类的类型,其中“GenericClass”表示新建一般类,这也是本书实验中建类时经常用到的选项。
在Name栏中键入类名,按照VC约定,新类以”C”作为前缀,表示建立的是一个类,VC将新建的类按头文件(*.h)和实现文件(*.cpp)分开保存,并以去掉“C”前缀的类名作为文件名。
如果建立的类是一个派生类,则在“Bassclass”栏中选择基类。
最后点“OK”键完成类的建立。
2.2.5在MFC中添加类成员变量和成员函数的方法
右键单击项目工作区的类视图页面中需添加成员的类名,在右键菜单中选择“AddMemberFunction…”,添加成员函数,或者“AddMemberVariable…”添加成员变量,根据约定,类的成员变量名一律以”m_”为前缀,以便和临时变量或全局变量区别。
2.2.6在MFC中添加菜单项方法
切换到项目左边工作区的资源视图页(ResourceView),双击“Menu”文件夹下的IDR_MAINFRAME,则项目右边出现菜单栏。
如图2.9所示。
图2.9菜单编辑界面
双击菜单栏上的预留菜单项,弹出菜单项属性对话框。
在其标题栏中输入菜单项标题,如“茶壶”,在ID栏中给菜单项取一个ID号,如图2.10所示。
如果没有取,系统自动命名该菜单项ID,如果对自动命名的ID不满意(大多数情况),可以再次打开属性对话框,给菜单项取一个自己满意的ID。
2.10菜单项属性对话框
2.2.7在MFC中添加消息响应的方法
按照MFC规定,对于窗口类,如视图类,对话框类等可以添加事件响应处理函数。
方法如下:
切换到项目左边工作区的类视图页(ClassView),鼠标右击需添加事件响应的窗口类,在弹出的下拉列表中选择“AddWindowsMessageHandler…”,弹出“NewWindowsMessageandEventHandler