《计算机图形学》课程实验指导1课件.docx
《《计算机图形学》课程实验指导1课件.docx》由会员分享,可在线阅读,更多相关《《计算机图形学》课程实验指导1课件.docx(35页珍藏版)》请在冰豆网上搜索。
![《计算机图形学》课程实验指导1课件.docx](https://file1.bdocx.com/fileroot1/2023-1/22/da298331-1dd2-4e92-9d35-8d3a30d15cd8/da298331-1dd2-4e92-9d35-8d3a30d15cd81.gif)
《计算机图形学》课程实验指导1课件
《计算机图形学》 课程实验指导
一. 实验总体方案
1.教学目标与基本要求
(1) 掌握教材所介绍的图形算法的原理;
(2) 掌握通过具体的平台实现图形算法的方法,培养相应能力;
(3) 通过实验培养具有开发一个基本图形软件包的能力。
2. 实验平台与考核
实验主要结合OpenGL设计程序实现各种课堂教学中讲过的图形算法为主。
程序设计语言主要以C/C++语言为主,开发平台为Visual C++。
每次实验前完成实验报告的实验目的、实验内容、实验原理、实验代码四部分并接受抽查,实验完成后完成实验结果、实验体会两部分,本次实验课结束前提交。
3. 实验步骤
(1) 预习教材与实验指导相关的算法理论及原理;
(2) 仿照教材与实验指导提供的算法,利用VC+OpenGL进行实现;
(3) 调试、编译、运行程序,运行通过后,可考虑对程序进行修改或改进。
二. 实验具体方案
实验预备知识
OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性。
1)与C语言紧密结合:
OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的。
如果你曾经接触过TC的graphics.h,你会发现,使用OpenGL作图甚至比TC更加简单;
2)强大的可移植性:
微软的Direct3D虽然也是十分优秀的图形API,但它只用于Windows系统。
而OpenGL不仅用于 Windows,还可以用于Unix/Linux等其它系统,它甚至在大型计算机、各种专业计算机(如:
医疗用显示设备)上都有应用。
并且,OpenGL 的基本命令都做到了硬件无关,甚至是平台无关;
3)高性能的图形渲染:
OpenGL是一个工业标准,它的技术紧跟时代,现今各个显卡厂家无一不对OpenGL提供强力支持,激烈的竞争中使得OpenGL性能一直领先。
总之,OpenGL是一个非常优秀的图形软件接口。
OpenGL官方网站(英文)http:
//www.opengl.org
下面将对Windows下的OpenGL编程进行简单介绍。
如下是学习OpenGL前的准备工作:
1.选择一个编译环境
现在Windows系统的主流编译环境有Visual C++,C++ Builder,Dev-C++等,它们都是支持OpenGL的。
但这里我们选择Visual C++ 作为学习OpenGL的实验环境。
2.安装GLUT工具包
GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装。
Windows环境下的GLUT下载地址:
(大小约为150k)
http:
//www.opengl.org/resources/libraries/glut/glutdlls37beta.zip
Windows环境下安装GLUT的步骤:
1)将下载的压缩包解开,将得到5个文件
2)在“我的电脑”中搜索“gl.h”,并找到其所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\PlatformSDK\include\gl文件夹”)。
把解压得到的glut.h放到这个文件夹。
3)把解压得到的glut.lib和glut32.lib放到静态函数库所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\lib”文件夹)。
4)把解压得到的glut.dll和glut32.dll放到操作系统目录下面的system32文件夹内。
(典型的位置为:
C:
\Windows\System32)
3.建立一个OpenGL工程
这里以VC为例:
选择File->New->Project,然后选择Win32 Console Application,选择一个名字,然后按OK。
在谈出的对话框左边点Application Settings,找到Empty project并勾上,选择Finish。
然后向该工程添加一个代码文件,取名为“OpenGL.cpp”。
实验1 像素点的生成
1.实验目的:
熟悉编程环境;了解光栅图形显示器的特点;了解计算机绘图的特点;利用VC+OpenGL作为开发平台设计程序,以能够在屏幕上生成任意一个像素点为本实验的结束。
2.实验内容:
(1) 了解和使用VC的开发环境,理解简单的OpenGL程序结构。
(2) 掌握OpenGL提供的基本图形函数,尤其是生成点的函数。
3.实验原理:
(1)基本语法
常用的程序设计语言,如C、C++、Pascal、Fortran和Java等,都支持OpenGL的开发。
这里只讨论C版本下OpenGL的语法。
OpenGL基本函数均使用gl作为函数名的前缀,如glClearColor();实用函数则使用glu作为函数名的前缀,如gluSphere()。
OpenGL基本常量的名字以GL_开头,如GL_LINE_LOOP;实用常量的名字以GLU_开头,如GLU_FILL。
一些函数如glColor*()(定义颜色值),函数名后可以接不同的后缀以支持不同的数据类型和格式。
如glColor3b(...)、glColor3d(...)、glColor3f(...)和glColor3bv(...)等,这几个函数在功能上是相似的,只是适用于不同的数据类型和格式,其中3表示该函数带有三个参数,b、d、f分别表示参数的类型是字节型、双精度浮点型和单精度浮点型,v则表示这些参数是以向量形式出现的。
OpenGL定义了一些特殊标识符,如GLfloat,GLvoid。
它们其实就是C中的float和void。
在gl.h文件中可以看到以下定义:
……
typedef float GLfloat; typedef void GLvoid; ……
一些基本的数据类型都有类似的定义项。
(2)程序的基本结构
OpenGL程序的基本结构可分为三个部分:
第一部分是初始化部分。
主要是设置一些OpenGL的状态开关,如颜色模式(RGBA或ALPHA)的选择,是否作光照处理(若有的话,还需设置光源的特性),深度检验,裁剪等等。
这些状态一般都用函数glEnable(...), glDisable(…)来设置,…表示特定的状态。
第二部分设置观察坐标系下的取景模式和取景框位置大小。
主要利用了三个函数:
函数void glViewport(left,top,right,bottom):
设置在屏幕上的窗口大小,四个参数描述屏幕窗口四个角上的坐标(以象素表示)
函数void glOrtho(left,right,bottom,top,near,far):
设置投影方式为正交投影(平行投影),其取景体积是一个各面均为矩形的六面体;
函数void gluPerspective(fovy,aspect,zNear,zFar):
设置投影方式为透视投影,其取景体积是一个截头锥体。
第三部分是OpenGL的主要部分,使用OpenGL的库函数构造几何物体对象的数学描述,包括点线面的位置和拓扑关系、几何变换、光照处理等等。
以上三个部分是OpenGL程序的基本框架,即使移植到使用MFC的Windows程序中,也是如此。
只是由于Windows自身有一套显示方式,需要进行一些必要的改动以协调这两种不同显示方式。
(3)状态机制
OpenGL的工作方式是一种状态机制,它可以进行各种状态或模式设置,这些状态或模式在重新改变它们之前一直有效。
例如,当前颜色就是一个状态变量,在这个状态改变之前,绘制的每个象素都将使用该颜色,直到当前颜色被设置为其它颜色为止。
OpenGL中大量地使用了这种状态机制,如颜色模式、投影模式、单双显示缓存区的设置、背景色的设置、光源的位置和特性等等。
许多状态变量可以通过glEnable()、glDisable()这两个函数来设置成有效或无效状态,如是否设置光照、是否进行深度检测等;在被设置成有效状态之后,绝大部分状态变量都有一个缺省值。
通常情况下,可以用下列四个函数来获取某个状态变量的值:
glGetBooleanv()、glGetDouble()、glGetFloatv()和glGetIntegerv()。
究竟选择哪个函数应该根据所要获得的返回值的数据类型来决定。
还有些状态变量有特殊的查询函数,如glGetLight*()、glGetError()和glPolygonStipple()等。
另外,使用glPushAttrib()和glPopAttrib()
函数,可以存储和恢复最近的状态变量的值。
只要有可能,都应该使用这些函数,因为它们比其它查询函数的效率更高。
4.实验代码:
一个简单的OpenGL程序如下:
(注意,如果需要编译并运行,需要正确安装GLUT,安装方法如预备知识中所述)
该程序的作用是在一个黑色的窗口中央画一个矩形、三角形和三个点。
下面对各行语句进行说明:
首先,需要包含头文件#include ,这是GLUT的头文件。
本来OpenGL程序一般还要包含和,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含;
然后看main函数。
int main(int argc, char *argv[]),这个是带命令行参数的main函数。
注意main函数中的各语句,除了最后的return之外,其余全部以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) glutDisplayFunc,设置一个函数,当需要进行画图时,这个函数就会被调用。
(暂且这样理解);
7) glutMainLoop,进行一个消息循环。
(现在只需知道这个函数可以显示窗口,并且等待窗口关闭后才会返回。
)
在glutDisplayFunc函数中,我们设置了“当需要画图时,请调用myDisplay函数”。
于是myDisplay函数就用来画图。
观察myDisplay中的三个函数调用,发现它们都以gl开头。
这种以gl开头的函数都是OpenGL的标准函数,下面对用到的函数进行介绍:
1) glClearColor(0.0, 0.0, 0.0, 0.0) :
将清空颜色设为黑色(为什么会有四个参数?
);
2) glClear(GL_COLOR_BUFFER_BIT):
将窗口的背景设置为当前清空颜色;
3) glRectf,画一个矩形。
四个参数分别表示了位于对角线上的两个点的横、纵坐标;
4) glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。
5. 思考题
如图所示,根据示范程序,能否在原有结果基础上添加三条直线组成三角形?
实验2 直线生成算法的实现
1.实验目的:
理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
2.实验内容:
(1) 根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果;
(2) 指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告;
(3) 根据示范代码,将其改造为圆的光栅化算法,写入实验报告;
(4) 了解和使用OpenGL的生成直线的命令,来验证程序运行结果。
3.实验原理:
示范代码原理参见教材直线光栅化一节中的DDA算法。
下面介绍下OpenGL画线的一些基础知识和glutReshapeFunc()函数。
(1)数学上的直线没有宽度,但OpenGL的直线则是有宽度的。
同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。
可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
这里的线由一系列顶点顺次连结而成,有闭合和不闭合两种。
前面的实验已经知道如何绘“点”,那么OpenGL是如何知道拿这些顶点来做什么呢?
是一个一个的画出来,还是连成线?
或者构成一个多边形?
或是做其它事情呢?
为了解决这一问题,OpenGL要求:
指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略),并由glBegin来指明如何使用这些点。
例如:
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.0f);
glEnd();
则这两个点将分别被画出来。
如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,glBegin支持的方式除了GL_POINTS和GL_LINES,还有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN等,每种方式的大致效果见下图:
(2)首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。
如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。
该函数必须完成下列工作:
●重新建立用作新渲染画布的矩形区域;
●定义绘制物体时使用的坐标系。
如:
在GLUT内部,将给该函数传递两个参数:
窗口被移动或修改大小后的宽度和高度,单位为像素。
glViewport()调整像素矩形,用于绘制整个窗口。
接下来三个函数调整绘图坐标系,使左下角位置为(0, 0),右上角为(w, h)。
4.实验代码:
注:
glShadeModel选择平坦或光滑渐变模式。
GL_SMOOTH为缺省值,为光滑渐变模式,GL_FLAT为平坦渐变模式。
5.思考题
示范代码有个小错误,能否指出并改正?
请将结果写入实验报告。
实验3 变换
1.实验目的:
进一步掌握二维、三维变换的数学知识、变换原理、变换种类、变换方法;进一步理解采用齐次坐标进行二维、三维变换的必要性;利用OpenGL实现二维、三维图形变换。
2.实验内容:
(1) 掌握二维、三维变换的原理及数学公式;
(2) 利用OpenGL实现二维、三维图形变换,在屏幕上显示变换过程或变换结果。
(3) 掌握OpenGL常用的变换函数。
3.实验原理:
OpenGL的三个基本几何变换函数介绍如下:
(1)平移变换
平移变换函数如下:
void glTranslate{fd}(TYPE x,TYPE y,TYPE z);
三个函数参数就是目标分别沿三个轴向平移的偏移量。
这个函数表示用这三个偏移量生成的矩阵乘以当前矩阵。
当参数是(0.0,0.0,0.0)时,表示对函数glTranslate*()的操作是单位矩阵,也就是对物体没有影响。
(2) 旋转变换
旋转变换函数如下:
void glRotate{fd}(TYPE angle,TYPE x,TYPE y,TYPE z);
函数中第一个参数是表示目标沿从点(x,y,z)到原点的方向逆时针旋转的角度,后三个参数是旋转的方向点坐标。
这个函数表示用这四个参数生成的矩阵乘以当前矩阵。
当角度参数是0.0时,表示对物体没有影响。
(3) 比例变换
比例变换函数如下:
void glScale{fd}(TYPE x,TYPE y,TYPE z);
三个函数参数值就是目标分别沿三个轴向缩放的比例因子。
这个函数表示用这三个比例因子生成的矩阵乘以当前矩阵。
这个函数能完成沿相应的轴对目标进行拉伸、压缩和反射三项功能。
当参数是(1.0,1.0,1.0)时,表示对函数glScale*()操作是单位矩阵,也就是对物体没有影响。
当其中某个参数为负值时,表示将对目标进行相应轴的反射变换,且这个参数不为1.0,则还要进行相应轴的缩放变换。
最好不要令三个参数值都为零,这将导致目标沿三轴都缩为零。
4.实验代码:
这个程序需要注意的地方有几点。
使用了双缓存模式,程序在空闲时一直不停的调用display函数,这个函数绘制完图像后,改变旋转的角度,然后交换双缓存,这样,每画完一帧就交换,形成了动画。
另外,使用了深度缓存,激活了深度测试,这样,被遮挡的面就不会显示,大家可以把激活深度缓存的一行去掉看看效果。
大家还可以改变变换的方式,达到不同的效果。
实验4 裁剪
1.实验目的:
了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。
2.实验内容:
(1) 理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
(2) 利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
(3) 调试、编译、修改程序。
(4) 尝试实现梁友栋裁剪算法。
3.实验原理:
编码裁剪算法的主要思想是:
对于每条线段,分为三种情况处理。
(1)若线段完全在窗口之内,则显示该线段,称为“取”;
(2)若线段明显在窗口之外,则丢弃该线段,称为“弃”;(3)若线段既不满足“取”的条件,也不满足“舍”的条件,则把线段分割为两段。
其中一段完全在窗口之外,可弃之;对另一段则重复上述处理。
算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图所示的空间划分和编码方案。
延长窗口的四条边界,把未经裁剪的图形区域分为九个区,每个区有一个四位二进制的编码,从左到右各位依次表示上、下、右、左。
例如,区号0101,左起第二位1表示该区在窗口的下方;右起第一位的1表示该区在窗口的左方。
整个区号表示该区在窗口的左下方。
裁剪一条线段时,先求出两端点所在的区号code1和code2,若code1 = 0且code2 = 0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之;若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上方、下方、左方或右方。
这种情况下,对线段的处理是弃之。
如果上述两种条件都不成立,则按第三种情况处理。
求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理。
4.实验代码:
5.实验思考题
请分别给出直线的三种不同位置情况,测试实验代码是否存在问题,有的话请调试改正。
可能的话,可以尝试实现梁友栋裁剪算法。
实验5 Bezier曲线
1.实验目的:
了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法。
2.实验内容:
(1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier曲线;
(2) 调试、编译、修改示范程序。
3.实验原理:
Bezier曲线是通过一组多边形折线的顶点来定义的。
如果折线的顶点固定不变,则由其定义的Bezier曲线是唯一的。
在折线的各顶点中,只有第一点和最后一点在曲线上且作为曲线的起始处和终止处,其他的点用于控制曲线的形状及阶次。
曲线的形状趋向于多边形折线的形状,要修改曲线,只要修改折线的各顶点就可以了。
因此,多边形折线又称Bezier曲线的控制多边形,其顶点称为控制点。
三次多项式,有四个控制点,其数学表示如下:
其矩阵形式为
4.实验代码:
5.实验思考题
尝试实现B样条曲线算法。
实验6 简单光照明模型实现
1.实验目的:
了解简单光照明模型的基本原理,利用VC+OpenGL实现物体的真实感图形。
2.实验内容:
(1) 结合示范代码了解简单光照明模型的基本原理与实现;
(2) 调试、编译、修改示范程序,给出不同光照系数,观察验证显示效果。
(3) 尝试实现圆锥体的光照效果。
3.实验原理:
Phong光照明模型是由物体表面上一点P反射到视点的光强I为环境光的反射光强Ie、理想漫反射光强Id、和镜面反射光Is的总和,即
其中R,V,N为单位矢量;Ip为点光源发出的入射光强;Ia为环境光的漫反射光强;Ka环境光的漫反射系数;Kd漫反射系数
取决于表面的材料;Ks镜面反射系数
;n幂次,用以模拟反射光的空间分布,表面越光滑,n越大。
在用Phong模型进行真实感图形计算时,对物体表面上的每个点P,均需计算光线的反射方向R,再由V计算
。
为减少计算量,我们可以作如下假设:
a)光源在无穷远处,即光线方向L为常数;b)视点在无穷远处,即视线方向V为常数;c)用
近似
。
这里H为L和V的角平分向量,
。
在这种简化下,由于对所有的点总共只需计算一次H的值,节省了计算时间。
结合RGB颜色模型,Phong光照明模型最终有如下的形式:
本次实验中,光源在无穷远处,光线方向为单位向量L(0.5, 0.5, 0.707),视点在无穷远处,视线方向V为(0, 0, 1)。
4.实验代码:
5.实验思考题
尝试绘制一个圆锥体的简单光照效果。