图形学实验1,2.docx_第1页
图形学实验1,2.docx_第2页
图形学实验1,2.docx_第3页
图形学实验1,2.docx_第4页
图形学实验1,2.docx_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数字图像处理实验指导书3D游戏图形学实验报告书(实验一、二)姓名: 学号:班级:浙江理工大学二一二 年 十 月2实验一 VC+6.0+OpenGL绘图环境及简单图形的输出一、实验目的1、 熟练使用实验主要开发平台VC+6.0;2、 进一步熟悉OpenGL的主要功能;3、 掌握OpenGL的绘图流程和原理;4、 掌握OpenGL的基本数据类型、核心函数的使用。二、实验内容创建一个OpenGL工程,利用OpenGL库函数进行简单图形设计与绘制。三、实验原理1、 基本语法(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。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的库函数构造几何物体对象的数学描述,包括点线面的位置和拓扑关系、几何变换、光照处理等。3、 OpenGL状态机制OpenGL的工作方式是一种状态机制,它可以进行各种状态或模式设置,这些状态或模式在重新改变它们之前一直有效。例如,当前颜色就是一个状态变量,在这个状态改变之前,绘制的每个像素都将使用该颜色,直到当前颜色被设置为其他颜色为止。OpenGL中大量地使用了这种状态机制,如颜色模式、投影模式、单双显示缓存区的设置、背景色的设置、光源的位置和特性等。许多状态变量可以通过glEnabel()、glDisable()这两个函数来设置成有效或无效状态,如是否设置光照、是否进行深度测试等;在被设置成有效状态之后,绝大部分状态变量都有一个缺省值。该程序是在一个黑色的窗口中画两条线,分别用白色和红色绘制。首先,需要包含头文件#include ,这是GLUT的头文件。本来OpenGL程序一般还要包含和,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。然后是main函数,其使用GLUT库实现窗口管理。我们关注的是display()函数,它是我们真正绘图的地方。函数glColor3f()以RGB方式设置颜色,格式为:glColor3f(red, green, blue),每种颜色值在(0.0, 1.0)之间。函数glVertex2f(x, y)设置二维顶点。函数glBegin(UINT State)、glEnd()是最基本的作图函数,下面对它作一介绍。如上所述,OpenGL是一个状态机,glBegin(UINT State)可以设定如下状态:GL_POINTS画点GL_LINES画线,每两个顶点(Vertex)为一组GL_LINE_STRIP画线,把若干个顶点顺次连成折线GL_LINE_LOOP画线,把若干个顶点顺次连成封闭折线GL_TRIANGLES画三角形,每三个顶点为一组GL_QUADS画四边形,每四个顶点为一组GL_POLYGON画多边形还有GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS_STRIP 等等。大家把每一种状态都试一试。另外,程序可以有多组glBegin()、glEnd()并列的形式,如:. .glBegin(GL_LINES);.glEnd();glBegin(GL_QUADS);. .glEnd();. .除了上述的基本图元外,函数glRectf(x1, y1, x2, y2)可以画一个矩形,但这个函数不能放在glBegin()和glEnd()之间,下面的两句程序是画一个蓝色的矩形。glColor3f (0.0f, 0.0f, 1.0f);glRectf(10.0f, 10.0f, 50.0f,50.0f);四、实验代码#include #include /初始化OpenGL场景void myinit (void) glClearColor (0.0, 0.0, 0.0, 0.0);/将背景置成黑色 glShadeModel (GL_FLAT);/设置明暗处理glMatrixMode(GL_PROJECTION); /设定投影参数 gluOrtho2D(0.0,200.0,0.0,150.0);/用户的绘图过程void display(void) glClear (GL_COLOR_BUFFER_BIT);/清除缓存 glBegin(GL_LINES);/开始画一根白线 glColor3f (1.0f, 1.0f, 1.0f);/设置颜色为白色/设置第一根线的两个端点,请注意:OpenGL坐标系的原点是在屏幕左下角 glVertex2f(10.0f, 50.0f); glVertex2f(110.0f, 50.0f); glColor3f (1.0f, 0.0f, 0.0f);/设置颜色为红色/设置第二根线的两个端点 glVertex2f(110.0f, 50.0f); glVertex2f(110.0f, 150.0f); glEnd();/画线结束glColor3f (0.0f, 0.0f, 1.0f);/绘制一个蓝色的矩形 glRectf(100.0f, 100.0f, 110.0f,110.0f);glColor3f (0.0f, 1.0f, 0.0f);/颜色为黄色 glBegin(GL_LINE_LOOP);/画封闭图形 glVertex2f(20.0f, 30.0f); glVertex2f(60.0f, 30.0f);glVertex2f(25.0f, 10.0f);glVertex2f(40.0f, 40.0f); glVertex2f(55.0f, 10.0f); glEnd();/绘制结束/主过程:/初始化Windows的窗口界面/并初始化OpenGL场景,绘图int main(int argc, char* argv)glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); /初始化窗口的显示模式glutInitWindowSize(400,300); /设置窗口的尺寸glutInitWindowPosition(100,120); /设置窗口的位置glutCreateWindow(); /创建一个名为的窗口glutDisplayFunc(display); /设置当前窗口的显示回调函数myinit(); /完成窗口初始化glutMainLoop(); /启动主GLUT事件处理循环 return(0);五、实验结果六、实验心得实验二 基本图形学算法实验一 实验目的1、 理解基本图形元素光栅的基本原理;2、 掌握直线和圆的多种生成算法;二 实验内容1、 编程实现DDA算法、中点算法和改进Bresenham算法生成直线;2、 编程实现简单方程算法和中点Bresenham算法生成圆;三 实验原理各算法的原理参考教材第五章内容。下面介绍一下OpenGL画线的一些基础知识和glutReshapeFunc()函数。(1) 数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。这里的线由一系列顶点顺次连接而成,有闭合和不闭合两种。(2) 首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。该函数必须完成下列工作:a 重新建立用作新渲染画布的矩形区域;b 定义绘制物体时使用的坐标系。如:void Reshape(int w, int h)glViewport(0, 0, (GLsizei)w, (GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h); 在GLUT内部,将给该函数传递两个参数:窗口被移动或修改大小后的宽度和高度,单位为像素。glViewport( )调整像素矩形,用于绘制整个窗口。接下来三个函数调整绘图坐标系,使左下角位置为(0,0),右上角为(w,h)。四 实验要求1)根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果(示范代码有错误,指出并改正);2)指出示范程序采用的算法,以此为基础将其改造为中点Bresenham算法和改进的Bresenham算法,写入实验报告;3)根据示范代码,将其改造为圆的光栅化算法,要求实现简单圆方程生成圆和中点Bresenham算法,并利用八分法画出整圆。五、实验代码DDA算法代码:# includevoid LineDDA(int x0, int y0, int x1, int y1)int x, dx;float m, y, dy;dx=x1-x0;dy=y1-y0;m=dy/dx;/m需要为非整形,则dy/dx的结果需为非整形y=y0;glColor3f(1.0f, 1.0f, 0.0f);glPointSize(1);for(x=x0;x=x1;x+)glBegin(GL_POINTS);glVertex2i(x,(int)(y+0.5);glEnd();y+=m;void myDisplay(void)glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0f,0.0f,0.0f);glRectf(25.0,25.0,75.0,75.0);glPointSize(5);glBegin(GL_POINTS);glColor3f(0.0f,1.0f,0.0f); glVertex2f(0.0f,0.0f);glEnd();LineDDA(0,0,200,300);glBegin(GL_LINES);glColor3f(1.0f,0.0f,0.0f); glVertex2f(100.0f,0.0f);glColor3f(0.0f,1.0f,0.0f); glVertex2f(180.0f,240.0f);glEnd();glFlush();void Init()glClearColor(0.0,0.0,0.0,0.0);glShadeModel(GL_FLAT);void Reshape(int w, int h)glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0,(GLdouble)w,0.0, (GLdouble)h);int main(int argc, char * argv)glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);glutInitWindowPosition(100,100);glutInitWindowSize(400,400);glutCreateWindow(Hello World!);Init();glutDisplayFunc(myDisplay);glutReshapeFunc(Reshape);glutMainLoop();return 0;算法步骤分析:当斜率大于1时,即表示y方向的增长速度大于x方向,此时当y轴每增加1,x方向增加斜率m,故m需要为非整形,再对x方向进行取整工作。同理,当斜率小于1是,当x轴每增加1,y方向增加斜率m,并对y轴进行取整操作。由于在光栅化过程中不可能绘制半个像素点,因此对求出的x和y进行四舍五入。中点算法主要代码:void LineDDA(int x0, int y0, int x1, int y1)int x, dy, dx;float m, d, y;dx=x1-x0;dy=y1-y0;m=dy/dx; /m需要为非整形,则dy/dx的结果需为非整形x=x0;/b=y1-m*x1;glColor3f(1.0f, 1.0f, 0.0f);glPointSize(1);d=dx-2*dy;for(y=y0;y=0)x=x;d=d-2*dx;else x=x+1;d=d+2*dy-2*dx;glEnd();/y+=m;算法步骤分析:根据直线的斜率确定变量在x或y方向上每次递增一个单位,而另一方向的增量为1或0,它取决于实际直线与相邻象素点的距离,这一距离称为误差项。输入直线的两端点P0(x0,y0)和P1(x1,y1)。计算初始值x、y、D0=x-2y、x=x0、y=y0。绘制点(x,y)。判断D的符号。若D0,则(x,y)更新为(x+1,y+1),D更新为D+2x-2y;否则(x,y)更新为(x+1,y), D更新为D-2y。当直线没有画完时,重复上一步骤,否则结束。改进Bresenham算法主要代码:void LineDDA(int x0, int y0, int x1, int y1)int x, dy, dx;float m, e, y;dx=x1-x0;dy=y1-y0;m=dy/dx; /m需要为非整形,则dy/dx的结果需为非整形x=x0;e=-1*dy;/b=y1-m*x1;glColor3f(1.0f, 1.0f, 0.0f);glPointSize(1);/d=dx-2*dy;for(y=y0;y0)x=x+1;e=e-2*dy;/y+=m;算法步骤分析:1.输入直线的两端点P0(x0,y0)和P1(x1,y1)。2.计算初始值x、y、e=-x、x=x0、y=y0。3.绘制点(x,y)。4.e更新为e+2y,判断e的符号。若e0,则(x,y)更新为(x+1,y+1),同时将e更新为e-2x;否则(x,y)更新为(x+1,y)。5.当直线没有画完时,重复步骤3和4。否则结束。简单圆方程生成圆主要代码:void LineDDA(int x, int y, int r)/确定圆心坐标、半径 float a;glPointSize(1);for(a=0;a=(3.14*2);a=a+0.01) /将a转换为弧度制glBegin(GL_POINTS);glVertex2i(int)(x+r*sin(a),(int)(y+r*cos(a);/要将整个值取值glEnd();算法步骤分析:在程序中首先指定圆心坐标和半径,对于圆心为任意的圆弧,可以先将其平移到原点,然后光栅化,再平移到原来的位置。在程序中for循环的判断条件的a应该转换为弧度制,并且由于用到sin、cos等数学运算符因此要包含头文件#include,而且此时LineDDA函数的参数为三个

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论