计算机图形学期末考查报告第一学期.docx
《计算机图形学期末考查报告第一学期.docx》由会员分享,可在线阅读,更多相关《计算机图形学期末考查报告第一学期.docx(15页珍藏版)》请在冰豆网上搜索。
计算机图形学期末考查报告第一学期
x
《计算机图形学》
期末考查报告
学年学期:
xxxx
专业班级:
xxxx
学生姓名:
xxxx
学号:
xxxx
成绩:
任课老师:
xxxx
提交日期:
xxxx
内容与要求
一、目的
本学期通过课堂授课、上机练习、作业等诸多教学环节,要求学生了解计算机图形学理论体系及其在图形处理系统开发中的应用;掌握二维及三维图形的几何变换、投影变换、裁剪、消隐的基本理论和方法;理解基本图元、曲线、曲面的生成算法;理解图形的明暗处理、纹理映射、阴影生成、真实感图形的生成与处理的原理。
掌握OpenGL编程基础知识及三维图形系统开发的实用技术。
期末考查将以计算机图形学OpenGL编程为主要考查内容。
二、内容及要求
(一)、总结OpenGL编程基础知识
OpenGL不是一种编程语言,而是一种API(ApplicationProgrammingInterface,应用程序编程接口)。
OpenGL的核心库中包含了OpenGL多个函数,这些函数都以“g1”为前缀最基本的命令函数。
OpenGL的实用函数库是比OpenGL核心库更高一层的函数库,也可以看作是对基本核心库的扩充。
它提供了四十多个函数,这些函数都以字母“glu”为前缀。
GLUT代表OpenGL应用工具包(GLUT:
OpenGLUtilityToolkit),是一个和窗口系统无关的工具包。
OpenGL包含200多个函数。
按照功能对这些函数进行分类是大有帮助的:
(1)图元函数。
这些函数定义了可在屏幕上生成图像的元素。
有两种类型的图元:
几何图元(例如多边形),它们可采用2个、3个或者4个维度来定义;以及图像图元,比如位图。
(2)属性函数。
这些函数控制图元的外观。
这些函数定义了颜色、线条类型、材料性质(materialproperty、光源以及材质。
(3)观视函数。
这些函数决定了照相机的属性。
OpenGL提供了一个虚拟照相机,可相对于图元函数定义的对象来定位它和调整它的方向。
还可对照相机的镜头进行控制,使其产生广角与远距拍摄效果。
(4)视窗函数。
这些函数不是OpenGL核心的一部分。
但是,由于它们对于交互式应用程序的重要性,所以使用单独的库(比如GLUT)来容纳它们。
我们可利用这些函数来控制屏幕上的窗口显示,并可通过它们来使用鼠标及键盘。
(5)控制函数。
这些函数允许我们启用各种OpenGL特性。
还可利用它们来了解一个特定实现具有的能力。
按照使用功能,GLUT中的函数可以分为以下几类:
1.初始化和创建窗口
(1)函数如下:
voidglutInit(antargc,char**argv);功能:
该函数用于初始化GLUT库。
(2)函数如下:
VoidglutInitDisplayMode(unsignedintmode);功能:
该函数为即将创建的窗口指定一种显示模式,如RGBA或颜色索引,单缓存或双缓存。
另外,还可以指定该窗口相关的深度、模板或累积缓存。
(3)函数如下:
VoidglutInitWindowSize(intwidth,intheight);功能:
该函数为即将创建的窗口指定一个初始的大小。
(4)函数如下:
VoidglutInitWindowPosition(intx,inty);功能:
该函数为即将创建的窗口指定一个初始的位置。
(5)函数如下:
VoidglutCreateWindow(char**name);功能:
该命令用于创建一个允许使用的OpenGL窗口,并将其视为当前窗口。
2.处理窗口和愉入
(1)函数如下:
voidglutDisplayFunc(void(*func)(void));功能:
该函数用于绘制当前窗口。
(2)函数如下:
VoidglutReshapeFunc(void(*func)(intwidth,intheight));功能:
该函数指定了当窗口的尺寸被缩放或移动时所调用的函数。
(3)函数如下:
VoidglutKeyboardFunc(void(*func)(unsignedintkey,intx,inty));功能:
该函数指定了当按下一个生成ASCII字符的键时,调用的函数。
(4)函数如下:
VoidglutMouseFunc(void(*fonc)(intbutton,intstate,intx,inty));功能:
该函数指定了当按下或释放一个鼠标键时,调用的函数。
(5)函数如下:
VoidglutSpecialFunc(void(*func)(unsignedintkey,intx,inty));功能:
该函数指定了当按下一个非ASCII字符的键(如Shift键)时,调用的函数。
(6)函数如下:
VoidglutMotionFunc(void(*func)(intx,inty));功能:
该函数指定了当按下鼠标在窗口内移动时,调用的函数。
3.绘制三维物体
(1)函数如下:
VoidglutWireCone(GLdoublebase,GLdoubleheight,GLintslices,GLintstacks);
VoidglutSolidCone(GLdou6lebase,GLdoubleheight,GLintslices,GLintstacks);功能:
绘制一个线框的或实心的圆锥体。
圆锥的底面位于原点(0,0,0),圆锥的顶点位于Z轴之上。
(2)函数如下:
VoidglutWireCube(GLdoublesize);VoidglutSolidCube(GLdoublesize);功能:
绘制一个边长为size的线框的或实心立方体,立方体的中心位于原点。
(3)函数如下:
VoidglutWireDodecahedron(Void);
VoidglutSolidDodecahedron(Void);功能:
绘制一个线框的或实心的正十二面体。
(4)函数如下:
VoidglutWireIcosahedron(Void);
VoidglutSolidIcosahedron(Void);功能:
绘制一个线框的或实心的正二十面体。
(5)函数如下:
VoidglutWireOctahedran(Void);
VoidglutSolidOctahedron(Void);功能:
绘制一个线框的或实心的正八面体。
(6)函数如下:
VoidglutWireSphere(GLdoubleradius,GLintslices,GLintstacks);
VoidglutSolidSphere(GLdoubleradius,GLintslices,GLintstacks);
功能:
绘制一个线框的或实心的球体。
(7)函数如下:
VoidglutWireTetrahedron(void);VoidglutSolidTetrahedron(void);
功能:
绘制一个线框的或实心的正四面体。
(8)函数如下:
VoidglutWireTorus(GLdoubleinnerRadius,GLdoubleouterRadius,GLintslices,GLintstacks);
VoidglutSolidTorus(GLdnubleinnerRadius,GLdoubleouterRadius,GLintslices,GLintstacks);功能:
绘制一个线框的或实心的圆环体。
(9)函数如下:
VoidglutWireTeapot(GLdoubleSize);
VoidglutSolidTeapot(GLdoubleSize);功能:
绘制一个以半径为size的线框的或实心茶壶。
4.管理后台处理
当没有其他的待处理的事件时,用户可以用函数glutIdleFun。
指定执行另一个函数。
函数如下:
voidglutIdIeFunc(void(*func)(void));功能:
该函数的参数中指定了一个函数名func,当其他的事情处于挂起时,就可以执行函数func。
5.运行程序
在完成了所有的设置之后,最后要做的事情就是开始执行所有的命令了,这时调用运行程序的函数。
函数如下:
voidglutMainLoop(void);功能:
这个函数开始启动主GLUT处理循环。
OpenGL是图形硬件的软件接口,其中包括了大约250个不同的函数。
作为一种应用程序编程接口(API),OpenGL的库函数遵循C语言的调用规定。
在以后的示例中,程序都是以C语言编写的。
一个实用的OpenGL程序从规模上说比较庞大,但基本结构是非常简单的。
一般包括以下几个部分:
(1)定义绘制对象。
通常对象绘制于指定的窗口之上。
首先必须定义窗口在屏幕上的位置及窗口的大小等属性,然后在窗口上建立坐标系,定义图形在窗口中的生成位置。
(2)初始化。
即初始化OpenGL中的状态变量,为下一步图形显示做准备工作。
包括定义投影类型、定义光照模型及纹理映射等。
(3)渲染屏幕图像。
按照显示的方位角度等要求绘制并显示图形,将物体的数学描述及状态变量如颜色纹理等变换为屏幕像素。
OpenGL函数命名与数据类型
OpenGL函数都遵循一个命名的约定,函数的头几个字母会说明该函数来自哪个库,后面部分包含一个根命令,代表该函数相应的OpenGL命令,后缀中的数字和字母表示该函数需要的参数类型与个数。
比如对于glColor3f命令,g1前缀代表该函数来自g1库,其根命令为Color,代表对颜色的设定,后缀3f表示该函数需要3个浮点型的参数。
同样地,OpenGL中对常量的定义,都是以大写字母GL开头,并且所有的字母都大写,在单词之间以下划线进行分隔,例如GL_COLORBUFFERBIT等。
有一些OpenGL函数的后缀中带有一个字母V,这表示该命令带有一个指向矢量或数组
值的指针作为参数。
许多函数都有矢量和非矢量两种参数形式。
OpenGL中还提供了一些更具描述性的名称。
如GLenum用于枚举变量,GLbitfield用于包含二进制位字段的变量,GLboolean变量用于表示真或假的条件。
OpenGL数据类型也可同样用于对数组和指针的定义。
比如10个GLint的变量数组只需定义为:
GLintints[10];对于指向GLfloat变量的指针可以定义为:
GLfloat*floats;
库和头文件
所有的OpenGL核心库的函数、类型和宏的原型都包括在头文件gl.h中,实用函数库glu函数的原型则位于另一个头文件glu.h中,这些文件通常要放在编程环境include路径中某个特殊目录下。
窗口坐标设置
在所有的窗口操作中,当执行初始化打开窗口、移动窗口或改变窗口的大小尺寸操作时,都会调用到GLUT中的一个子程序:
函数如下:
VoidglutReshapeFunc(void(*func)(intwidth,intheight));它所包含的两个变量width和height,指定了窗口新的宽度和高度。
只要窗口的大小发生改变,glutReshapeFunc()就可以收到新的宽度与高度。
我们就可以利用这些信息,定义OpenGL函数在窗口上坐标系及作图区域。
对于二维的坐标系,最常用的方法是调用函数glutReshapeFunc(myreshape),其中reshape()是用户自己定义的函数。
(2)、阐述三维表面数据结构(以立方体为例)
假设要表示的形体T可以放在一个充分大的实体C内,C的边长为2n,形体TC,它的八叉树可以用以下递归的方法来定义:
八叉树的每个节点与C的一个子立方体对应,树根与C本身相对应,如果T=C,那么T的八叉树仅有树根,如果T不等于C,则C等分为八个子立方体,每个子立方体与树根的一个子节点相对应。
只要某个子立方体不是完全空白或完全为T所占据,就要被八等分,从而对应的节点也就有了八个子节点。
这样递归判断、分割一直要进行到节点所对应的立方体或是完全空白,或者是完全为T占据,或是其大小已是预先定义的体素大小,并且对它与T之交作一定的“舍入”,使体素或认为是空白的,或认为是T占据的。
如此所生成的八叉树上的节点可以分为三类:
一是灰节点,对应的立方体部分地为T所占据;二是白节点,对应的立方体中无T的内容;三是黑节点,对应的立方体全为T所占据。
后两类又称为叶节点。
与四叉树结构相类似的八叉树结构可以沿用四叉树的有关方法。
根据存储方式的不同,八叉树可以分为常规的、线形的、一对八的八叉树等等。
1)规则的八叉树八叉树的存储结构是用一个有九个字段的记录来表示树中的每个结点,其中一个字段用来秒苏该结点的特性,其余的八段用来作为存放指向其八个子结点的指针。
但是规则八叉树的缺陷较多,最大的问题就是指针占用了很大的空间。
因此虽然其易于理解掌握,但存储代价太大。
2)线形八叉树线形八叉树注重考虑的是如何提高空间利用率,用某一预先确定的次序遍历八叉树,将八叉树转换成一贯线形表,表的每个元素与一个结点相对应。
线形八叉树不仅节省存储空间,对某些运算也比较方便,但是不够灵活。
3)一对八式的八叉树在一对八式的八叉树中,一个非叶结点有八个子结点,如果一个记录与一个结点对应,那么在这个记录中描述的是这个结点的八个子结点的特征值,而指针给出的则是该八个子结点所对应记录的存放处,而且还隐含地假设了这些子结点记录存放的次序。
也就是说,即使某个记录是不必要的,那么相应的存储位置也必须空闲在那里,以保证不会错误地存取到其它同层结点的记录。
很显然,当它不是完全八叉树的时候,存储空间会有一定的浪费。
为了克服这种缺陷,一是增加计算量,即在存取相应结点记录之前,首先检查它的父结点记录,看一下之前有几个叶结点,从而可以知道应该如何存取所需结点记录。
这种方法可以减小存储需求,但会增加计算量;另一个是在记录中增加一定的信息,使计算工作适当减少或者更方便。
例如在原记录中增加三个字节,一分为八,每个字节点对应三位,代表它的子结点在指针指向区域中的偏移。
(三)、总结OpenGL颜色、纹理、光源设置方法以及鼠标和键盘响应函数的用法
颜色:
从视觉的角度看,颜色由其色彩(hue)、饱和度(saturation)和亮度(lightness)决定。
颜色模型:
RGB颜色模型、CMY颜色模型、HSV颜色模型。
在执行程序之初,必须先设置颜色的显示方式。
OpenGL中提供了两种颜色模式:
RGBA模式和颜色索引模式。
颜色的显示方式一旦确定下来,就不能再进行更改。
对于创建RGBA模式或颜色索引模式的窗口,使用命令:
glutInitDisplayMode(GLU_RGB);或:
glutInitDisplayMode(GLUT_INDEX);
在RGBA模式下,可使用glColor*()函数指定当前颜色。
VoidglColor3{bsifdubusui}(TYPER,TYPEG,TYPEB);
VoidglColor4{bsifdubusui}(TYPER,TYPEG,TYPEB,TYPEA);
VoidglColor3{bsifdubusui}(constTYPE*v);
VoidglColor4{bsifdubusui}(constTYPE*v);
功能:
用RGBA模式指定当前颜色。
在颜色索引模式中,可使用如下函数来设置当前的颜色索引:
VoidglIndex{sifd}(TYPEC);
VoidglIndex{sifd}(TYPEC);
着色模式:
OpenGL中的函数glShadeModel()用于指定不同的着色模式。
VoidglShadeModel(Glrnummode);
纹理:
我们可使用函数g1TexImage1D()和函数g1TexImage3D(),建立一维、二维、三维纹理映射。
几何对象上的点与纹理单元之间的映射是通过函数g1TexCoord*()完成的:
可通过设置矩阵模式和使用处理模型一观视矩阵与投影矩阵的相同技术来更改纹理矩阵:
glMatrixMode(GL_TEXTURE);
尽管函数glTexCoord*()和glTexImage*()是纹理映射中的必备例程,但还必须设置一些额外的所需参数。
这里还有其他可选参数,它们为如何将纹理应用到对象表面提供了更多的控制。
可以通过g1TexParameter*)设置这些参数。
二维纹理的典型用法可能类似于以下形式:
对表面应用纹理:
通过函数glTexEnv*()设置。
置换(replace)模式是最重要模式,在该模式中,只通过纹理颜色确定从帧缓存中可看到的颜色。
我们可通过函数glTexEnv*()设置这些模式。
默认的调谐模式与执行以下函数等价:
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
OpenGL要求纹理大小(小于任何边界)是2的幂。
我们可以使用GLU函数gluScaleImage()将图像映射成纹理映射可接受的大小,还可以通过函数glCopyTexImage2D()从帧缓存图像获取纹理映射。
我们使用GLU函数gluQquadricTexture()来启动纹理坐标的自动生成:
纹理对象:
光源设置方法:
定义光源:
定义材质:
控制阴影计算:
若确实需要双面光照计算,如看对象内部时可请求OpenGL通过以下函数执行正确的光照计算:
通过以下函数告诉OpenGL取景器相距场景无穷远:
OpenGL提供了函数glDepthMask(),该函数可将深度缓存设置为只读(GL_FALSE)或可写的(GL_TRUE)。
鼠标和键盘响应函数:
键盘:
GLUT有一个通过函数glutKeyboardFunc()来标识的键盘回调函数。
只要按下键盘上的按键,就会调用这个回调函数。
GLUT会忽略松开按键事件,不过许多视窗系统都允许应用程序对松开按键事件做出响应。
特殊的键:
GLUT也考虑到了如何使用各种特殊的按键,比如功能键和箭头键。
大多数键盘上都有此类特殊的按键。
这些键是通过glutSpecialFunction()回调函数来处理的。
鼠标:
有一种事件称为“进入事件”(entryevent),只要鼠标进入或离开窗口,就会产生这个事件。
运动回调函数由glutMotionFunc()指定,被动运动回调函数由glutPassiveMotionFunc()指定。
两者都会返回鼠标的位置。
4、编程内容
1)编程实现一个带颜色纹理的旋转立方体的程序
在VC++编程环境下,用学过的OpenGL编程知识独立完成编程并上机实现。
2)纹理设置可以选择棋盘格明暗相间的颜色纹理函数(见参考资料)
3)该立方体的运动对点击鼠标键及按下某一键盘上的字符键这样的事件响应。
对鼠标的响应是:
用户按下鼠标左键后,立方体以x轴为旋转轴旋转;按下中间键,以y轴为旋转轴旋转;后改变旋转;按下右键,以z轴为旋转轴旋转。
对键盘的响应是:
按下数字键1时,立方体继续旋转;按下数字键2时停止旋转;按下字母q键时,停止运行退出程序。
5、考查报告提交要求
报告中要给出上机实现后的结果的截图。
A4纸(字体小四)打印考查报告,并按时提交打印好的报告、报告电子文档及程序源代码和可执行文件。
(完)