计算机图形学OpenGL版实验14.docx
- 文档编号:4115740
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:17
- 大小:140.96KB
计算机图形学OpenGL版实验14.docx
《计算机图形学OpenGL版实验14.docx》由会员分享,可在线阅读,更多相关《计算机图形学OpenGL版实验14.docx(17页珍藏版)》请在冰豆网上搜索。
计算机图形学OpenGL版实验14
实验1OpenGL初识
一、实验目的:
熟悉编程环境;了解光栅图形显示器的特点;了解计算机绘图的特点;利用VC+OpenGL作为开发平台设计程序,以能够在屏幕上生成任意一个像素点为本实验的结束。
二、实验内容:
(1)了解和使用VC的开发环境,理解简单的OpenGL程序结构。
(2)掌握OpenGL提供的基本图形函数,尤其是生成点的函数。
三、该程序的作用是在一个黑色的窗口中央画一个矩形、三角形和三个点,如图所示。
下面对各行语句进行说明:
首先,需要包含头文件#include
然后看main函数。
intmain(intargc,char*argv[]),这个是带命令行参数的main函数。
这种以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命令立即执行(而不是让它们在缓冲区中等待)。
四、实验代码:
#include
voidmydisplay(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,1.0f,1.0f);
glRectf(-0.5f,-0.5f,0.5f,0.5f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex2f(0.0f,1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex2f(0.8f,-0.5f);
glColor3f(0.0f,0.0f,1.0f);
glVertex2f(-0.8f,-0.5f);
glEnd();
glBegin(GL_LINES);
glColor3f(0.0f,0.0f,1.0f);
glVertex2i(-0.6f,-0.6f);
glVertex2i(0.6f,-0.6f);
glColor3f(0.0f,1.0f,0.0f);
glVertex2i(-0.6f,-0.6f);
glVertex2i(0.0f,0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex2i(0.6f,-0.6f);
glVertex2i(0.0f,0.0f);
glEnd();
glPointSize(3);
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex2f(-0.4f,-0.4f);
glColor3f(0.0f,1.0f,0.0f);
glVertex2f(0.0f,-0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex2f(0.4f,0.4f);
glEnd();
glFlush();
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("HelloWorld!
");
glutDisplayFunc(&mydisplay);
glutMainLoop();
return0;
}
五、结果截图:
实验2直线生成算法实现
一、实验目的:
理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
二、实验内容:
(1)根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果;
(2)指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告;
(3)根据示范代码,将其改造为圆的光栅化算法,写入实验报告;
(4)了解和使用OpenGL的生成直线的命令,来验证程序运行结果。
三、实验原理:
(1)数学上的直线没有宽度,但OpenGL的直线则是有宽度的。
同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。
可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
这里的线由一系列顶点顺次连结而成,有闭合和不闭合两种。
(2)首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。
如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。
该函数必须完成下列工作:
(1)重新建立用作新渲染画布的矩形区域;
(2)定义绘制物体时使用的坐标系。
四、实验代码:
#include
voidLineDDA(intx0,inty0,intx1,inty1/*,intcolor*/)
{
intx,dy,dx,y;
floatm;
dx=x1-x0;
dy=y1-y0;
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;
}
}
voidmyDisplay(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();
}
voidInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_FLAT);
}
voidReshape(intw,inth)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("HelloWorld!
");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMainLoop();
return0;
}
五、结果截图:
实验3OpenGL几何变换
一、实验目的:
理解掌握一个OpenGL程序平移、旋转、缩放变换的方法。
二、实验内容:
(1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移、旋转、缩放变换的方法;
(2)根据示范代码,尝试完成实验作业;
三、实验原理:
(1)OpenGL下的几何变换
在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义。
平移矩阵构造函数为glTranslate
tx,ty,tz指定这个移动物体的矩阵,它们可以是任意的实数值,后缀为f(单精度浮点float)或d(双精度浮点double),对于二维应用来说,tz=0.0。
旋转矩阵构造函数为glRotate
theta,vx,vy,vz指定这个旋转物体的矩阵,物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数theta表示旋转的角度。
向量v=(vx,vy,vz)的分量可以是任意的实数值,该向量用于定义通过坐标原点的旋转轴的方向,后缀为f(单精度浮点float)或d(双精度浮点double),对于二维旋转来说,vx=0.0,vy=0.0,vz=1.0。
缩放矩阵构造函数为glScale
sx,sy,sz指定这个缩放物体的矩阵,分别表示在x,y,z方向上的缩放比例,它们可以是任意的实数值,当缩放参数为负值时,该函数为反射矩阵,缩放相对于原点进行,后缀为f(单精度浮点float)或d(双精度浮点double)。
(2)OpenGL下的各种变换简介
我们生活在一个三维的世界——如果要观察一个物体,我们可以:
1、从不同的位置去观察它(人运动,选定某个位置去看)。
(视图变换)
2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它(物体运动,让人看它的不同部分)。
(模型变换)
3、如果把物体画下来,我们可以选择:
是否需要一种“近大远小”的透视效果。
另外,我们可能只希望看到物体的一部分,而不是全部(指定看的范围)。
(投影变换)
4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部(指定在显示器窗口的那个位置显示)。
(视口变换)
这些,都可以在OpenGL中实现。
从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。
在OpenGL中,实现这两种功能甚至使用的是同样的函数。
由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。
设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样:
glMatrixMode(GL_MODELVIEW);
该语句指定一个4×4的建模矩阵作为当前矩阵。
四、实验代码:
#include
voidinit(void)
{
glClearColor(1.0,1.0,1.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-5.0,5.0,-5.0,5.0);//设置显示的范围是X:
-5.0~5.0,Y:
-5.0~5.0
glMatrixMode(GL_MODELVIEW);
}
voiddrawSquare(void)//绘制中心在原点,边长为2的正方形
{
glBegin(GL_POLYGON);//顶点指定需要按逆时针方向
glVertex2f(-1.0f,-1.0f);//左下点
glVertex2f(1.0f,-1.0f);//右下点
glVertex2f(1.0f,1.0f);//右上点
glVertex2f(-1.0f,1.0f);//左上点
glEnd();
}
voidmyDraw(void)
{
glClear(GL_COLOR_BUFFER_BIT);//清空
glLoadIdentity();//将当前矩阵设为单位矩阵
glPushMatrix();
glTranslatef(0.0f,2.0f,0.0f);
glScalef(3.0,0.5,1.0);
glColor3f(1.0,0.0,0.0);
drawSquare();//上面红色矩形
glPopMatrix();
glPushMatrix();
glTranslatef(-3.0,0.0,0.0);
glPushMatrix();
glRotatef(45.0,0.0,0.0,1.0);
glColor3f(0.0,1.0,0.0);
drawSquare();//中间左菱形
glPopMatrix();
glTranslatef(3.0,0.0,0.0);
glPushMatrix();
glRotatef(45.0,0.0,0.0,1.0);
glColor3f(0.0,0.7,0.0);
drawSquare();//中间中菱形
glPopMatrix();
glTranslatef(3.0,0.0,0.0);
glPushMatrix();
glRotatef(45.0,0.0,0.0,1.0);
glColor3f(0.0,0.4,0.0);
drawSquare();//中间右菱形
glPopMatrix();
glPopMatrix();
glTranslatef(0.0,-3.0,0.0);
glScalef(4.0,1.5,1.0);
glColor3f(0.0,0.0,1.0);
drawSquare();//下面蓝色矩形
glFlush();
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0,0);
glutInitWindowSize(600,600);
glutCreateWindow("几何变换函数综合示例");
init();
glutDisplayFunc(myDraw);
glutMainLoop();
}
五、结果实例:
实验4编码裁剪算法
一、实验目的:
了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。
二、实验内容:
(1)理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
(2)利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
(3)调试、编译、修改程序。
(4)尝试实现梁友栋裁剪算法。
三、实验原理:
编码裁剪算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图所示的空间划分和编码方案。
裁剪一条线段时,先求出两端点所在的区号code1和code2,若code1=0且code2=0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之;若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上方、下方、左方或右方。
这种情况下,对线段的处理是弃之。
如果上述两种条件都不成立,则按第三种情况处理。
求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理。
四、实验代码:
#include
#include
#include
#defineLEFT_EDGE1
#defineRIGHT_EDGE2
#defineBOTTOM_EDGE4
#defineTOP_EDGE8
voidLineGL(intx0,inty0,intx1,inty1)
{
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);glVertex2f(x0,y0);
glColor3f(0.0f,1.0f,0.0f);glVertex2f(x1,y1);
glEnd();
}
structRectangle
{
floatxmin,xmax,ymin,ymax;
};
Rectanglerect;
intx0,y0,x1,y1;
intCompCode(intx,inty,Rectanglerect)
{
intcode=0x00;
if(y code=code|4; if(y>rect.ymax) code=code|8; if(x>rect.xmax) code=code|2; if(x code=code|1; returncode; } intcohensutherlandlineclip(Rectanglerect,int&x0,int&y0,int&x1,int&y1) { intaccept,done; floatx,y; accept=0; done=0; intcode0,code1,codeout; code0=CompCode(x0,y0,rect); code1=CompCode(x1,y1,rect); do{ if(! (code0|code1)) { accept=1; done=1; } elseif(code0&code1) done=1; else { if(code0! =0) codeout=code0; else codeout=code1; if(codeout&LEFT_EDGE){ y=y0+(y1-y0)*(rect.xmin-x0)/(x1-x0); x=(float)rect.xmin; } elseif(codeout&RIGHT_EDGE){ y=y0+(y1-y0)*(rect.xmax-x0)/(x1-x0); x=(float)rect.xmax; } elseif(codeout&BOTTOM_EDGE){ x=x0+(x1-x0)*(rect.ymin-y0)/(y1-y0); y=(float)rect.ymin; } elseif(codeout&TOP_EDGE){ x=x0+(x1-x0)*(rect.ymax-y0)/(y1-y0); y=(float)rect.ymax; } if(codeout==code0) { x0=x;y0=y; code0=CompCode(x0,y0,rect); } else { x1=x;y1=y; code1=CompCode(x1,y1,rect); } } }while(! done); if(accept) LineGL(x0,y0,x1,y1); returnaccept; } voidmyDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f,0.0f,0.0f); glRectf(rect.xmin,rect.ymin,rect.xmax,rect.ymax); LineGL(x0,y0,x1,y1); glFlush(); } voidInit() { glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_FLAT); rect.xmin=100; rect.xmax=300; rect.ymin=100; rect.ymax=300; x0=450,y0=0,x1=0,y1=450; printf("Presskey'c'toClip! \nPresskey'r'toRestore! \n"); } voidReshape(intw,inth) { glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h); } voidkeyboard(unsignedcharkey,intx,inty) { switch(key) { case'c': cohensutherlandlineclip(rect,x0,y0,x1,y1); glutPostRedisplay(); break; case'r': Init(); glutPostRedisplay(); break; case
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 OpenGL 实验 14