3D游戏图形学实验一分解.docx

上传人:b****6 文档编号:7779142 上传时间:2023-01-26 格式:DOCX 页数:18 大小:86.21KB
下载 相关 举报
3D游戏图形学实验一分解.docx_第1页
第1页 / 共18页
3D游戏图形学实验一分解.docx_第2页
第2页 / 共18页
3D游戏图形学实验一分解.docx_第3页
第3页 / 共18页
3D游戏图形学实验一分解.docx_第4页
第4页 / 共18页
3D游戏图形学实验一分解.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

3D游戏图形学实验一分解.docx

《3D游戏图形学实验一分解.docx》由会员分享,可在线阅读,更多相关《3D游戏图形学实验一分解.docx(18页珍藏版)》请在冰豆网上搜索。

3D游戏图形学实验一分解.docx

3D游戏图形学实验一分解

 

《3D游戏图形学》

实验指导书

 

浙江理工大学

二0一五年十月

课程实验指导

一、实验总体方案

1.教学目标与基本要求

1)掌握本书所介绍的图形算法的原理。

2)掌握通过具体的平台实现图形算法的方法,培养学生使用现代图形系统API的能力。

3)通过实验培养具有开发一个基本图形软件包的能力。

2.实验平台

实验主要结合OpenGL设计程序,实现各种课堂教学中讲过的图形算法。

程序设计语言主要以C/C++为主,开发平台是VisualC++。

3.实验步骤

1)预习教材与实验指导的实验具体方案部分相关的算法理论及原理。

2)仿照教材与实验指导提供的算法,利用VC++OpenGL进行实验。

3)调试、编译、运行程序,运行通过后,可考虑对程序进行修改或改进。

二、实验预备知识

OpenGL作为当前主流的图形API之一,在一些场合具有比DirectX更优越的特性。

(1)与C语言紧密结合

OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL很容易理解和学习。

(2)强大的可移植性

微软的Direct3D虽然也是十分优秀的图形API,但它只适用于Windows系统,而OpenGL不仅适用于Windows,还可以用于Unix/Linux等其他系统,它甚至在大型计算机、各种专业计算机上都有应用。

并且,OpenGL的基本命令都做到了硬件无关,甚至是平台无关。

(3)高性能的图形渲染

OpenGL是一个工业标准,它的技术紧跟时代,现今各个显卡厂家无一不对OpenGL提供强力支持,激烈的竞争中使得OpenGL性能一直领先。

总之,OpenGL是一个非常优秀的图形软件接口。

下面对Windows下的OpenGL编程进行简单介绍。

以下几点是学习OpenGL前的准备工作。

1.选择一个编译环境

现在Windows系统的主流编译环境有VisualC++,C++Builder,Dev-C++等,它们都支持OpenGL。

这里选择VisualC++作为学习OpenGL的实验环境。

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

#include

//初始化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,50.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程序一般还要包含,但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);

......

glEnd();

......

除了上述的基本图元外,函数glRectf(x1,y1,x2,y2)可以画一个矩形,但这个函数不能放在glBegin()和glEnd()之间,下面的两句程序是画一个蓝色的矩形。

glColor3f(0.0f,0.0f,1.0f);

glRectf(10.0f,10.0f,50.0f,50.0f);

要求:

利用OpenGL库函数绘制基本图形,输出绘制结果。

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,50.0f);

glVertex2f(110.0f,150.0f);

glEnd();

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)

{

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;

}

介绍一下glutReshapeFunc()函数:

首次打开窗口、移动窗口和改变窗口大小时,窗口系统都将发送一个事件,以通知程序员。

如果使用的是GLUT,通知将自动完成,并调用向glutReshapeFunc()注册的函数。

该函数必须完成下列工作:

a.重新建立用作新渲染画布的矩形区域;

b.定义绘制物体时使用的坐标系。

如:

voidReshape(intw,inth)

{

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)根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果(示范代码有错误,指出并改正);

示范代码展示:

voidLineDDA(intx0,inty0,intx1,inty1)

{

floatx,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;

}

}

 

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);

glBegin(GL_POINTS);

glColor3f(1.0f,1.0f,1.0f);

glVertex2f(x,y);

glEnd();

x=x+1,e=e+k;

if(e>=0)

{

y++,e=e-1;

}

}

}

 

3)根据示范代码,将其改造为圆的光栅化算法,要求实现圆的中点算法,并利用八分法画出整圆。

圆的光栅化算法:

voidsetRound(GLintxc,GLintyc,GLintN){

for(inti=0;i

{

intx=xc,y=yc;

glLineWidth(4.0f);

glBegin(GL_POINTS);

glColor3f(0,1.0f,1.0f);

glVertex2f(x+R*cos(2*Pi/N*i),y+R*sin(2*Pi/N*i));

glEnd();

}

}

 

圆的中点算法:

 

 

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);

glEnd();

while(y>x)

{

if(d<=0)

{

d+=deltaE;

deltaSE+=8;

}

else

{

d+=deltaSE;

deltaSE+=16;

y--;

}

deltaE+=8;

x++;

glBegin(GL_POINTS);

glVertex2i(x,y);

glVertex2i(x,-y);

glVertex2i(-x,y);

glVertex2i(-x,-y);

glVertex2i(y,x);

glVertex2i(y,-x);

glVertex2i(-y,x);

glVertex2i(-y,-x);

glEnd();

}

}

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1