1、计算机图形学期末实验报告附件1:封面格式得分: 计算机图形学期末考试答卷姓名:学号: 一、目标及任务目标:1、 熟悉OpenGL编程2、 学会平面网格的绘制3、 掌握Opengl的光照和动画实现任务一: 1、绘制如上图的一个绿色平面网格。网格x的世界坐标取值范围为-16,16,y的世界坐标取值范围为-16,16。z取值始终为0。 2、该题所绘制的平面网格,用于模拟地面,需将其整合到后面提高题中的场景中。任务二: 1.构造三个球体对象,要求启用光照,对象的色彩可以自行发挥想象。 2.三个球体对象,最大的球体A,中间大球体B,最小的球体C。球体A静止不动,球体B绕球体A旋转,球体C绕球体B旋转,同
2、时也绕球体A旋转(球体C有点类似月球,它绕地球旋转,同时也绕太阳旋转)。二、开发环境操作系统版本:win7集成开发环境:visua C+ 6.0三、总的技术思路、技术流程框架图及源代码任务一:主要用到的函数:1、void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);该函数定义一个视图矩阵,并与当前矩阵相乘。第一组eyex, eyey,eyez 相机在世界坐
3、标的位置第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置第三组upx,upy,upz 相机向上的方向在世界坐标中的方向2、void glLineStipple( GLint factor, GLushort pattern );参数pattern:是由1或0组成的16位序列,从这个模式的低位开始,一个一个像素地进行处理,如果模型中对应的位是1,就绘制这个像素,否则不绘制。factor:为重复因子,它与1和0的连续子序列相乘,如果模式中出现3个1,并且factor是2,那么他们就扩展为6个连续的1.3、glOrtho就是一个正射投影函数。它创建一个平行视景
4、体。实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。其中近裁剪平面是一个矩形,矩形左下角点三维空间坐标是(left,bottom,-near),右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。所有的near和far值同时为正或同时为负。如果没有其他变换,正射投影的方向平行于Z轴,且视点朝向Z负轴。这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。主要用到的技术:1、 正射投影正射投影,又叫平行投影。这种投影的
5、视景体是一个矩形的平行管道,也就是一个长方体,如图所示。正射投影的最大一个特点是无论物体距离相机多远,投影后的物体大小尺寸不变。这种投影通常用在建筑蓝图绘制和计算机辅助设计等方面,这些行业要求投影后的物体尺寸及相互间的角度不变,以便施工或制造时物体比例大小正确。2、 模型视图变换由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。设置的方法是以GL_MODELVIEW为参数调用glMatrixMode 函数。在代码中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。display()程序中绘图函数潜在的重复性强调了
6、:在指定的视图变换之前,应该使glLoadIdentity()函数把当前矩阵设置为单位矩阵。在载入单位矩阵之后,使用gluLookAt()函数指定视图变换。如果程序没有调用gluLookAt(),那么照相机会设定为一个默认的位置和方向。在默认的情况下,照相机位于原点,指向Z轴负方向,朝上向量为(0,1,0)。一般而言,display()函数包括:视图变换 + 模型变换 + 绘制图形的函数(如glutWireCube()。display()会在窗口被移动或者原来先遮住这个窗口的东西被一开时,被重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。在调用glFrustum()设置投影变
7、换之前,在reshape()函数中有一些准备工作:视口变换 + 投影变换 + 模型视图变换。由于投影变换,视口变换共同决定了场景是如何映射到计算机的屏幕上的,而且它们都与屏幕的宽度,高度密切相关,因此应该放在reshape()中。reshape()会在窗口初次创建,移动或改变时被调用。OpenGL中矩阵坐标之间的关系:物理坐标*模型视图矩阵*投影矩阵*透视除法*规范化设备坐标窗口坐标源代码:#include void myDisplay() glClear(GL_COLOR_BUFFER_BIT);/刷新背景 glMatrixMode(GL_MODELVIEW);/对模型视景矩阵操作 glLo
8、adIdentity(); /加载单位矩阵 gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0);/定义视图矩阵设置照相机位置 for(int i = -16; i 16; i+) for (int j = -16; j 16; j+) glBegin(GL_LINE_LOOP);/绘制线段 glVertex3f(i,j,0); glVertex3f(i,j+1,0); glVertex3f(i+1,j+1,0); glVertex3f(i+1,j,0); glEnd(); glFlush();void init() glColor3f(
9、1.0, 0.0, 1.0);/网格颜色 glLineStipple(3, 0xcccc);/定义点画模式 glMatrixMode(GL_PROJECTION);/投影矩阵 glLoadIdentity(); /加载单位矩阵 glOrtho(-24, 24, -24, 24, -24, 24);/设置修改空间范围void main(int argc, char * argv) glutInit(&argc, argv); glutInitWindowPosition(0, 0);/初始位置 glutInitWindowSize(800, 800); glutCreateWindow(line
10、s); glutDisplayFunc(myDisplay); glEnable(GL_LINE_STIPPLE);/启用直线点画功能 init(); glutMainLoop();/循环绘图运行效果图:任务二:主要技术:1、动画的实现:动画的实现是通过不断修改旋转变换的角度来实现的。并且利用双缓冲技术,在存储器(很有可能是显存)中开辟两块区域,一块作为发送到显示器的数据,一块作为绘画的区域,在适当的时候交换它们,只要在绘制完成时简单的调用glutSwapBuffers函数把绘制好的信息用于屏幕显示就可以了。在每次调用显示回调函数之前改变角度参数的值,使天体看起来像在旋转。其中,angle1为
11、地球绕太阳旋转的角度,angle2为月亮绕地球旋转的角度,月亮绕地球旋转速度是地球绕太阳旋转速度的12倍,设置angle1每次增加20.0f度,angle2每次增加2.0f度。2、深度测试:深度测试决定了是否绘制较远的象素点(或较近的象素点),通常选用较近的,而较远优先能实现透视的效果。深度测试只需要调用函数:glEnable(GL_DEPTH_TEST);就可以打开深度测试功能。另外,在创建窗口时指定其具有深度缓冲区,深度缓存的位数是衡量深度缓存精度的参数。深度缓存位数越高,则精确度越高,在每次渲染场景时,消除深度缓冲区即可。3、光照:简单的光照效果的,我们通过光照的层次,很容易的认为它是一
12、个三维的物体眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。因此对于人类而言,光线很大程度上表现了物体的立体感。OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。光源就是光的来源,可以是前面所说的太阳或者电灯等。材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,
13、指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。对于光源发出的光线,可以分别设置其经过镜面反射和漫反射后的光线强度。对于被光线照射的材质,也可以分别设置光线经过镜面反射和漫反射后的光线强度。这些因素综合起来,就形成了最终的光照效果。根据光的反射定律,由光的入射方向和入射点的法线就可以得到光的出射方向。因此,对于指定的物体,在指定了光源后,即可计算出光的反射方向,进而计算出光照效果的画面。本作业中使用了2个光源,一个在太阳中心light0,照亮地球和月亮;另一个光源light1只照亮太阳,在画太阳之前打开,画完之后使用函数glDisable(GL_LIGHT1);关闭light1
14、。4、表面材质:材质与光源相似,也需要设置众多的属性。不同的是,光源是通过glLight*函数来设置的,而材质则是通过glMaterial*函数来设置的。glMaterial*函数有三个参数。第一个参数表示指定哪一面的属性。可以是GL_FRONT、GL_BACK或者GL_FRONT_AND_BACK。分别表示设置“正面”“背面”的材质,或者两面同时设置。第二、第三个参数与glLight*函数的第二、三个参数作用类似。本作业中只用到了材质的发射光颜色,太阳、地球、月亮分别为红色、蓝色和黄色,如设置太阳glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,sun_e
15、mission);技术流程图: 源代码:#include #include void Initial() GLfloat light0_diffuse=1.0f,0.5f,0.0f,1.0f;/light0中漫反射光分量 GLfloat light0_position=10.0f,20.0f,-150.0f,1.0f;/light0的坐标位置 GLfloat light0_direction=0.0f,0.0f,-1.0f;/light0的聚光灯方向角 glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);/light0在太阳中心 glLightfv(G
16、L_LIGHT0,GL_POSITION,light0_position); glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,light0_direction); glEnable(GL_DEPTH_TEST);/ 启用深度测试 glEnable(GL_LIGHTING);/ 启用光源 glEnable(GL_LIGHT0);/ 使用0号光照 glEnable(GL_COLOR_MATERIAL);/启用颜色材质模式 glFrontFace(GL_CCW);/ 指定逆时针绕法表示多边形正面void ChangeSize(int w, int h) if(h=0)h=
17、1; glViewport(0,0,w,h);/ 设置视区尺寸 glMatrixMode(GL_PROJECTION);/指定当前操作投影矩阵堆栈 glLoadIdentity();/重置投影矩阵 gluPerspective(35.0,(float)w/(float)h,1.0,500.0);/指定透视投影的观察空间 glMatrixMode(GL_MODELVIEW);/投影矩阵 glLoadIdentity(); /加载单位矩阵 void Display(void) static float angle1=0.0f,angle2=0.0f; /angle1地球绕太阳旋转的角度,angle
18、2月亮绕地球旋转的角度 GLfloat sun_emission=0.6f,0.0f,0.0f,1.0f;/太阳颜色 GLfloat earth_emission=0.0f,0.0f,0.8f,1.0f;/地球颜色 GLfloat moon_emission=0.98f,0.625f,0.12f,1.0f;/月亮颜色 GLfloat light1_diffuse=0.5f,0.8f,0.0f,1.0f;/光源light1中漫反射光分量 GLfloat light1_position=50.0f,100.0f,100.0f,1.0f;/光源light1的坐标位置 GLfloat light1_d
19、irection=0.0f,0.0f,-1.0f;/光源light1的聚光灯方向角 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/清除颜色和深度缓冲区 glMatrixMode(GL_MODELVIEW);/指定当前操作模型视图矩阵堆栈 glLoadIdentity();/重置模型视图矩阵 glTranslatef(0.0f,0.0f,-150.0f);/将图形沿z轴负向移动150.0f /绘制太阳 glEnable(GL_LIGHT1); glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse); gl
20、Lightfv(GL_LIGHT1,GL_POSITION,light1_position); glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,light1_direction); glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,sun_emission); glutSolidSphere(12.0f,30,30);/绘制太阳 glDisable(GL_LIGHT1); /绘制地球 glPushMatrix();/保存当前的矩阵视图模型 glRotatef(angle1,0.0f,10.0f,1.0f);/旋转一定角度 glTr
21、anslatef(40.0f,0.0f,0.0f);/绕x轴正向移动40.0f glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,earth_emission); glutSolidSphere(6.0f,20,20);/绘制地球 /绘制月亮 glRotatef(angle2,0.0f,1.0f,0.0f); glTranslatef(15.0f,0.0f,0.0f);/绕x轴方向移动15.0f glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,moon_emission); glutSolidSphere(3.0f,20
22、,20);/绘制月亮 glPopMatrix();/恢复矩阵视图模型 angle1+=2.0f;/增加旋转步长,产生动画效果 if(angle1=360.0f) angle1=0.0f; angle2+=20.0f; if(angle2=360.0f) angle2=0.0f; glutSwapBuffers();/双缓冲下使用该函数交换两个缓冲区的内容void TimerFunc(int x) glutPostRedisplay();/重绘图像 glutTimerFunc(100,TimerFunc,1);/定时int main(int argc, char* argv) glutInit(
23、&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); /设置图形显示模式为双缓冲,深度缓冲,建立RGB模式窗口 glutInitWindowSize(640,480); glutInitWindowPosition(400,200); glutCreateWindow(太阳地球月亮); glutReshapeFunc(ChangeSize); glutDisplayFunc(Display); glutTimerFunc(500,TimerFunc,1); Initial(); glutMainLoop(
24、); return 0;运行效果图:四、心得在本学期的计算机图形学学习中,不仅让我学习到了很多图形学知识,期末的作业更培养了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情。学习计算机图形学不能停留在学习它的程序语言,而是利用学到的知识编写C语言程序来验证自己的想法,深入理解图形生成的原理,解决实际问题。而且计算机图形学是依附在C语言编程基础之上的,我们对图形生成算法的理解要通过C程序才能体现出来。通过本学期对计算机图形学这门课的学习,使我们巩固了一些关于C语言的知识,理解了我们计算机图形学的理论知识,这对我们将来到社会工作将会有莫大的帮助。同时它让我知道计算机图形的强大和瑰丽之处,虽然我们学的都是基本的生成算法,但是通过老师展示的几个计算机图形学高级程序,我们才了解到计算机图形学可以做出非常华丽的视觉效果,而且只要你努力,任何东西都不会太难。最后,还是很庆幸能学到计算机图形学这样的一门课程,在学习本课程的同时,已经涉及了很多的学科,让我们更有能力成为全方位、多特色的新世纪人才。使我们的编程能力、思维能力都获得了提高。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1