3D游戏图形学实验一分解Word格式文档下载.docx
《3D游戏图形学实验一分解Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《3D游戏图形学实验一分解Word格式文档下载.docx(18页珍藏版)》请在冰豆网上搜索。
2.安装OpenGL工具包
1)将OpenGL工具包dll文件夹中的*.dll文件放到操作系统目录下面的system32文件夹(其路径一般为:
C:
\Windows\System32)。
2)打开VC,在VC中选择Tools→Options→Directories,然后在Showdirectoriesfor中选择Includefiles,在下面添加OpenGL工具包中Include文件夹的路径,如下图所示:
3)类似地,在Showdirectoriesfor中选择libraryfiles,在下面添加OpenGL工具包中lib文件夹的路径,然后按OK。
如下图所示:
3.建立一个OpenGL工程
打开VC后,在VC中选择File→New→Project,然后选择Win32ConsoleApplication,选择一个名字,然后按“OK”。
在弹出的对话框中点Anemptyproject,选择Finish。
然后向该工程添加一个源文件,选择一个名字。
三、实验报告要求
(1)有实验报告封面
(2)给出简要的设计思路(原理)。
(3)给出实现代码。
(4)给出实验结果的屏幕截图。
(5)实验的心得体会或建议。
实验一VC++6.0+OpenGL绘图环境及基本图形学算法
实验项目性质:
验证性实验
所属课程名称:
3D游戏图形学
实验计划学时:
3学时
一.实验目的
1、熟悉OpenGL的主要功能;
2、掌握OpenGL的绘图流程和原理;
3、掌握OpenGL核心函数的使用;
4、理解基本图形元素光栅的基本原理;
5、掌握直线和圆的多种生成算法。
二.实验内容
1、创建一个OpenGL工程,利用OpenGL库函数进行简单图形设计与绘制;
2、编程实现DDA算法和Bresenham算法生成直线;
3、编程实现中点算法生成圆。
三.实验原理
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(…)来设置,“…”表示特定的状态。
第二部分设置观察坐标系下的取景模式和取景框位置大小,主要利用了三个函数:
函数voidglViewport(left,top,right,bottom)设置在屏幕上的窗口大小,四个参数描述屏幕窗口四个角上的坐标(以像素表示);
函数voidglOrtho(left,right,bottom,top,near,far)设置投影方式为正交投影(平行投影),其取景体积是一个各面均为矩形的六面体;
函数voidgluPerspective(fovy,aspect,zNear,zFar)设置投影方式为透视投影,其取景体积是一个截头锥体。
第三部分是OpenGL的主要部分,是使用OpenGL的库函数构造几何物体对象的数学描述,包括点线面的位置和拓扑关系、几何变换、光照处理等。
3、OpenGL状态机制
OpenGL的工作方式是一种状态机制,它可以进行各种状态或模式设置,这些状态或模式在重新改变它们之前一直有效。
例如,当前颜色就是一个状态变量,在这个状态改变之前,绘制的每个像素都将使用该颜色,直到当前颜色被设置为其他颜色为止。
OpenGL中大量地使用了这种状态机制,如颜色模式、投影模式、单双显示缓存区的设置、背景色的设置、光源的位置和特性等。
许多状态变量可以通过glEnabel()、glDisable()这两个函数来设置成有效或无效状态,如是否设置光照、是否进行深度测试等;
在被设置成有效状态之后,绝大部分状态变量都有一个缺省值。
四.实验代码
1、如预备知识所述,安装OpenGL工具包,创建一个OpenGL工程,在源文件上输入如下代码:
#include<
windows.h>
GL/glut.h>
//初始化OpenGL场景
voidmyinit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
//将背景置成黑色
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,200.0,0.0,150.0);
glShadeModel(GL_FLAT);
//设置明暗处理
}
//用户的绘图过程
voiddisplay(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,150.0f);
glEnd();
//画线结束
glFlush();
//绘图结束
//
//主过程:
//初始化Windows的窗口界面
//并初始化OpenGL场景,绘图
intmain(intargc,char**argv)
glutInit(&
argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//初始化窗口的显示模式
glutInitWindowSize(400,300);
//设置窗口的尺寸
glutInitWindowPosition(100,120);
//设置窗口的位置
glutCreatWindow(“”);
//创建一个名为“”的窗口
glutDisplayFunc(Display);
//设置当前窗口的显示回调函数
myinit();
//完成窗口初始化
glutMainLoop();
//启动主GLUT事件处理循环
return(0);
glaux.lib
glu32.lib
glut32.lib
opengl32.lib
注:
glShadeModel选择平坦或光滑渐变模式。
GL_SMOOTH为缺省值,为光滑渐变模式,GL_FLAT为平坦渐变模式。
该程序是在一个黑色的窗口中画两条线,分别用白色和红色绘制。
首先,需要包含头文件#include<
,这是GLUT的头文件。
本来OpenGL程序一般还要包含<
GL/gl.h>
和<
GL/glu.h>
,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。
然后是main函数,其使用GLUT库实现窗口管理。
我们关注的是display()函数,它是我们真正绘图的地方。
函数glColor3f()以RGB方式设置颜色,格式为:
glColor3f(red,green,blue),每种颜色值在(0.0,1.0)之间。
函数glVertex2f(x,y)设置二维顶点。
函数glBegin(UINTState)、glEnd()是最基本的作图函数,下面对它作一介绍。
如上所述,OpenGL是一个状态机,glBegin(UINTState)可以设定如下状态:
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);
......
除了上述的基本图元外,函数glRectf(x1,y1,x2,y2)可以画一个矩形,但这个函数不能放在glBegin()和glEnd()之间,下面的两句程序是画一个蓝色的矩形。
glColor3f(0.0f,0.0f,1.0f);
glRectf(10.0f,10.0f,50.0f,50.0f);
要求:
利用OpenGL库函数绘制基本图形,输出绘制结果。
glClear(GL_COLOR_BUFFER_BIT);
//清除缓存
glColor3f(1.0f,1.0f,1.0f);
//设置第一根线的两个端点,请注意:
glColor3f(1.0f,0.0f,0.0f);
//设置第二根线的两个端点
glColor3f(0.0f,0.0f,1.0f);
glRectf(10.0f,10.0f,50.0f,50.0f);
//画线结束
glFlush();
2、创建一个新的OpenGL工程,在源文件上输入如下代码:
//DDA算法
#include<
voidLineDDA(intx0,inty0,intx1,inty1)
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)
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);
LineDDA(0,0,200,300);
glVertex2f(100.0f,0.0f);
glVertex2f(180.0f,240.0f);
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;
介绍一下glutReshapeFunc()函数:
首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。
如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。
该函数必须完成下列工作:
a.重新建立用作新渲染画布的矩形区域;
b.定义绘制物体时使用的坐标系。
如:
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);
在GLUT内部,将给该函数传递两个参数:
窗口被移动或修改大小后的宽度和高度,单位为像素。
glViewport()调整像素矩形,用于绘制整个窗口。
接下来三个函数调整绘图坐标系,使左下角位置为(0,0),右上角为(w,h)。
1)根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果(示范代码有错误,指出并改正);
示范代码展示:
floatx,dy,dx,y;
dx=x1-x0;
dy=y1-y0;
m=dy/dx;
y=y0;
for(x=x0;
x<
=x1;
x++)
glVertex2i(x,(int)(y+0.5));
y+=m;
2)根据示范程序采用的算法,以此为基础将其改造为Bresenham算法,写入实验报告;
voidBresenhamline(intx0,inty0,intx1,inty1,intcolor)
intx,y,dx,dy;
floatk,e;
dx=x1-x0,dy=y1-y0,k=dy/dx;
e=-0.5,x=x0,y=y0;
for(inti=0;
i<
=dx;
i++)
glPointSize(2.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex2f(x,y);
x=x+1,e=e+k;
if(e>
=0)
{
y++,e=e-1;
}
3)根据示范代码,将其改造为圆的光栅化算法,要求实现圆的中点算法,并利用八分法画出整圆。
圆的光栅化算法:
voidsetRound(GLintxc,GLintyc,GLintN){
for(inti=0;
N;
++i)
intx=xc,y=yc;
glLineWidth(4.0f);
glColor3f(0,1.0f,1.0f);
glVertex2f(x+R*cos(2*Pi/N*i),y+R*sin(2*Pi/N*i));
圆的中点算法:
voidDrawCirle(intradius)
intx,y;
floatd;
x=0;
y=radius;
d=5-4*radius;
floatdeltaE=12;
floatdeltaSE=20-8*radius;
glPointSize(3);
glBegin(GL_POINT);
glColor3f(0.0,1.0,0.0);
glVertex2i(x,y);
while(y>
x)
if(d<
d+=deltaE;
deltaSE+=8;
else
d+=deltaSE;
deltaSE+=16;
y--;
deltaE+=8;
x++;
glVertex2i(x,y);
glVertex2i(x,-y);
glVertex2i(-x,y);
glVertex2i(-x,-y);
glVertex2i(y,x);
glVertex2i(y,-x);
glVertex2i(-y,x);
glVertex2i(-y,-x);