3D游戏图形学实验五

3D游戏图形学实验五
3D游戏图形学实验五

《3D游戏图形学》实验指导书

指导老师:马文娟

姓名:

学号:

浙江理工大学

2013年12月

实验五纹理映射实验

实验项目性质:设计性实验

所属课程名称:3D游戏图形学

实验计划学时:3学时

一、实验目的和要求

掌握纹理映射的基本原理,利用VC++ OpenGL实现纹理映射技术。

二、实验原理

纹理映射是真实感图形制作的一个重要部分,运用纹理映射可以方便地制作真实感图形,而不必花更多的时间去考虑物体的表面纹理。如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。然后的具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。

另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。

此外,纹理映射也可以用于其他方面。例如,使用一大片植被的图像映射到一些连续的多边形上,以模拟地貌,或者以大理石、木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。

在OpenGL中提供了一系列完整的纹理操作函数,用户可以用它们构造理想的物体表面,可以对光照物体进行处理,使其映射出所处环境的景象,可以用不同方式应用到曲面上,而且可以随几何物体的几何属性变换而变化,从而使制作的三维场景和三维物体更真实更自然。

在OpenGL中要实现纹理映射,需要经历创建纹理、指定纹理应用方式、启用纹理映射、使用纹理坐标和几何坐标绘制场景几个过程。

用于指定一维、二维和三维纹理的函数分别为:

Void glTexImage1D(GLenum target, Glint level, Glint components, GLsizei width, Glint border, GLenum format, GLenum type, const GLvoid *texels);

Void glTexImage2D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels);

Void glTexImage3D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLsizei depth, Glint border, GLenum format, GLenum type, const GLvoid *texels);

其中,参数target取值一般为GL_TEXTURE_1D, GL_TEXTURE_2D和GL_TEXTURE_3D,分别与一维、二维和三维的纹理相对应。参数Level表示纹理多分辨率层数,通常取值为0,表示

只有一种分辨率。参数components的可能取值为1~4的整数以及多种符号常量(如GL_RGBA),表示纹理元素中存储的哪些分量(RGBA颜色、深度等)在纹理映射中被使用,1表示使用R颜色分量,2表示使用R和A颜色分量,3表示使用RGB颜色分量,4表示使用RGBA颜色分量。参数width,height,depth分别指定纹理的宽度、高度、深度。参数format 和type表示给出的图像数据的数据格式和数据类型,这两个参数的取值都是符号常量(比如format指定为GL_RGBA,type指定为GL_UNSIGNED_BYTE,参数texels指向内存中指定的纹理图像数据。

在定义了纹理之后,需要启用纹理的函数:

glEnable(GL_TEXTURE_1D);

glEnable(GL_TEXTURE_2D);

glEnable(GL_TEXTURE_3D);

在启用纹理之后,需要建立物体表面上点与纹理空间的对应关系,即在绘制基本图元时,在glVertex函数调用之前调用glTexCoord函数,明确指定当前顶点所对应的纹理坐标,例如:

glBegin(GL_TRIANGLES);

glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);

glTexCoord2f(1.0, 1.0); glVertex2f(15.0, 15.0);

glTexCoord2f(1.0, 0.0); glVertex2f(30.0, 0.0);

glEnd();

其图元内部点的纹理坐标利用顶点处的纹理坐标采用线性插值的方法计算出来。

在OpenGL中,纹理坐标的范围被指定在[0,1]之间,而在使用映射函数进行纹理坐标计算时,有可能得到不在[0,1]之间的坐标。此时OpenGL有两种处理方式,一种是截断,另一种是重复,它们被称为环绕模式。在截断模式(GL_CLAMP)中,将大于1.0的纹理坐标设置为1.0,将小于0.0的纹理坐标设置为0.0。在重复模式(GL_REPEAT)中,如果纹理坐标不在[0,1]之间,则将纹理坐标值的整数部分舍弃,只使用小数部分,这样使纹理图像在物体表面重复出现。例如,使用下面的函数:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

分别指定二维纹理中s坐标采用截断或重复处理方式。

另外,在变换和纹理映射后,屏幕上的一个像素可能对应纹理元素的一小部分(放大),也可能对应大量的处理元素(缩小)。在OpenGL中,允许指定多种方式来决定如何完成像素与纹理元素对应的计算方法(滤波)。比如,下面的函数可以指定放大和缩小的滤波方法:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

其中,glTexParameteri函数的第一个参数指定使用的是一维、二维或三维纹理;第二个参数为GL_TEXTURE_MAG_FILTER或GL_TEXTURE_MIN_FILTER,指出要指定缩小还是放大滤波算法;最后一个参数指定滤波的方法。

补充:透视投影函数

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);

它也创建一个对称透视视景体,但它的参数定义于前面的不同。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在X-Z平面的角度,范围是[0.0,180.0];参数aspect是投影平面宽度与高度的比率;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。

三、实验内容

在OpenGL中纹理映射所使用的纹理数据,既可以是程序生成的一组数据,也可以从外部文件中直接读取,参考示范代码完成以下两项内容:

利用直接创建纹理的方法生成二维纹理并映射到四边形上。

参考代码:

void makeImage(void)

{

int i, j, r,g,b;

for (i = 0; i < ImageWidth; i++)

{

for (j = 0; j < ImageHeight; j++)

{

r=(i*j)%255;

g=(4*i)%255;

b=(4*j)%255;

Image[i][j][0] = (GLubyte) r;

Image[i][j][1] = (GLubyte) g;

Image[i][j][2] = (GLubyte) b;

}

}

}

void myinit(void)

{

glClearColor (0.0, 0.0, 0.0, 0.0);

glEnable(GL_DEPTH_TEST);

glDepthFunc(GL_LESS);

// 生成纹理数据

makeImage();

// 设置像素存储模式

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

// 定义二维纹理映射

glTexImage2D(…… );

// 定义纹理映射参数

glTexParameterf(……);

glTexParameterf(……);

glTexParameterf(……);

glTexParameterf(……);

// 启用二维纹理

glEnable(GL_TEXTURE_2D);

glShadeModel(GL_FLAT);

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//绘制四边形,并完成纹理映射

……

glFlush();

}

void myReshape(GLsizei w, GLsizei h)

{

……

}

void main(int argc, char* argv[])

{

……

}

完整代码:

#include

#include

#define imageWidth 64

#define imageHeight 64

GLubyte Image[imageWidth][imageHeight][3];

void makeImage(void)

{

int i, j, r,g,b;

for (i=0; i

{

for (j=0; j

{

r=(i*j)%255;

g=(4*i)%255;

b=(4*j)%255;

Image[i][j][0] = (GLubyte) r;

Image[i][j][1] = (GLubyte) g;

Image[i][j][2] = (GLubyte) b;

}

}

}

void myinit(void)

{

glClearColor (0.0, 0.0, 0.0, 0.0);

glEnable(GL_DEPTH_TEST);

glDepthFunc(GL_LESS);

// 生成纹理数据

makeImage();

// 设置像素存储模式

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

// 定义二维纹理映射

glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHe ight,0,GL_RGB,GL_UNSIGNED_BYTE,&Image[0][0][0]);

// 定义纹理映射参数

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRA P_S,GL_CLAMP);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRA P_T,GL_CLAMP);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG _FILTER,GL_NEAREST);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_NEAREST);

// 启用二维纹理

glEnable(GL_TEXTURE_2D);

glShadeModel(GL_FLAT);

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//绘制四边形,并完成纹理映射

glBegin(GL_QUADS);

/*纹理的坐标和四边形顶点的对应*/

glTexCoord2f(0.0,0.0);

glVertex3f(-1.0,1.0,0.0);

glTexCoord2f(0.0,1.0);

glVertex3f(-1.0,-1.0,0.0);

glTexCoord2f(1.0,1.0);

glVertex3f(1.0,-1.0,0.0);

glTexCoord2f(1.0,0.0);

glVertex3f(1.0,1.0,0.0);

glEnd();

glFlush();

}

void myReshape(GLsizei w, GLsizei h)

{

glViewport(0,0,(GLsizei)w,(GLsizei)h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat) h,1.0,30.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main(int argc,char **argv)

{

/*初始化*/

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutInitWindowSize(300,300);

glutInitWindowPosition(200,200);

/*创建窗口*/

glutCreateWindow(" Texture ");

/*绘制与显示*/

myinit();

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutMainLoop();

return 0;

}

运行结果:

2. 从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。

整个过程需要三个步骤:创建纹理、启用纹理映射和使用纹理坐标和几何坐标绘制,下面我们对三个过程进行阐述,并给出参考代码。

1)创建纹理对象并绑定纹理

纹理创建即在内存中创建保存纹理数据的数组,一般是先读入一个图像文件,将图像文件的RGBA信息存入我们创建的纹理空间中,当然图像的位图不同,创建的纹理空间结构也会有所不同。为了更加简单易懂地实现这个过程,我们使用未压缩的纹理。

代码:

GLuinttexture[1]; //创建一个纹理空间

AUX_RGBImageRec *LoadBMP(CHAR *Filename) //载入位图图像

{

FILE *File=NULL; //文件句柄

if(!Filename) //确保文件名已提供

{

return NULL;

}

File=fopen(Filename, "r"); //尝试打开文件

if(File)

fclose(File); //关闭文件

return auxDIBImageLoadA(Filename); //载入位图并返回指针}

return NULL; //如果载入失败,返回NULL }

int LoadGLTextures() //载入位图并转换成纹理

{

int Status=FALSE; //状态指示器

AUX_RGBImageRec *TextureImage[1]; //创建纹理的存储空间

memset(TextureImage, 0, sizeof(void *)*1);//初始化

//载入位图,检查有无错误,如果位图没找到则退出

if(TextureImage[0]=LoadBMP("data.bmp"))

{

Status=TRUE;

glGenTextures(1,&texture[0]); //创建纹理

//使用来自位图数据生成的典型纹理

glBindTexture(GL_TEXTURE_2D, texture[0]); //生成2D纹理

glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImag e[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

}

if(TextureImage[0]) //纹理是否存在

{

if(TextureImage[0]->data) //纹理图像是否存在

{

free(TextureImage[0]->data); //释放纹理图像占用的内存}

free(TextureImage[0]); //释放图像结构

}

return Status; //返回Status

}

2)启用纹理映射操作,初始化相关参数

在OpenGL中使用纹理映射之前,必须打开纹理映射。

int InitGL(GLvoid)

{

if(!LoadGLTextures()) //调用纹理载入子例程

{

return FALSE;

glEnable(GL_TEXTURE_2D); //启用纹理映射glShadeModel(GL_SMOOTH); //启用阴影平滑glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //黑色背景

glClearDepth(1.0f); //设置深度缓存glEnable(GL_DEPTH_TEST); //启用深度测试return TRUE;

}

3)使用纹理坐标和几何坐标绘制

void DrawGLScene(void)

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0.0f,0.0f,-5.0f);

glRotatef(xrot,1.0f,0.0f,0.0f);

glRotatef(yrot,0.0f,1.0f,0.0f);

glRotatef(zrot,0.0f,0.0f,1.0f);

// 选择纹理

glBindTexture(GL_TEXTURE_2D,texture[0]);

//绘制一个正方体,给每个面贴上纹理,并使之转动

glBegin(GL_QUADS);

……

glEnd();

xrot+=0.3f;

yrot+=0.2f;

zrot+=0.4f;

}

完整代码:

#include

#include

#include

#include

#include

#pragma comment(lib, "openGL32.lib")

#pragma comment(lib, "glu32.lib")

#pragma comment(lib, "glaux.lib")

#pragma comment(lib,"openGL32.lib" )

GLuint texture[1];//创建纹理空间

GLfloat xRot,yRot,zRot;

AUX_RGBImageRec *LoadBMP(char *FileName) //载入位图图像

{

FILE *File = NULL;

if(!FileName)

return NULL;

File = fopen(FileName,"r");

if (File)

{

fclose(File);

return auxDIBImageLoad(FileName);

}

return NULL;

}

int LoadGLTextures() //载入位图并转换成纹理

{

int Status=FALSE; //

状态指示器

AUX_RGBImageRec *TextureImage[1]; //

创建纹理的存储空间

memset(TextureImage, 0, sizeof(void *)*1);//

初始化

//载入位图,检查有无错误,如果位图没找到则退出if(TextureImage[0]=LoadBMP("data.bmp"))

{

Status=TRUE;

glGenTextures(1,&texture[0]); //创建纹理

//使用来自位图数据生成的典型纹理

glBindTexture(GL_TEXTURE_2D, texture[0]); //生成2D纹理

glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[

0]->sizeX,TextureImage[0]->sizeY, 0, GL_RGB,

GL_UNSIGNED_BYTE, TextureImage[0]->data);

glTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_MAG_FILTER, GL_LINEAR);

}

if(TextureImage[0]) //纹理是否存在

{

if(TextureImage[0]->data) //纹理图像是否存在

{

free(TextureImage[0]->data); //释放纹理图像占用的内存

}

free(TextureImage[0]); //释放图像结构

}

return Status; //返回Status

}

int InitGL(GLvoid)

{

if(!LoadGLTextures()) //调用纹理载入子例程

{

return FALSE;

}

glEnable(GL_TEXTURE_2D); //启用纹理映射

glShadeModel(GL_SMOOTH); //启用阴影平滑

glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //黑色背景

glClearDepth(1.0f); //设置深度缓存

glEnable(GL_DEPTH_TEST); //启用深度测试

return TRUE;

}

void DrawGLScene()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0.0f,0.0f,-5.0f);

glRotatef(xRot,1.0f,0.0f,0.0f);

glRotatef(yRot,0.0f,1.0f,0.0f);

glRotatef(zRot,0.0f,0.0f,1.0f);

//选择纹理

glBindTexture(GL_TEXTURE_2D,texture[0]);

//绘制一个正方体,给每个面贴上纹理,并使之转动

glBegin(GL_QUADS);

// Front Face

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

glEnd();

glBindTexture(GL_TEXTURE_2D,texture[0]);

glBegin(GL_QUADS);

// Back Face

glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

glEnd();

glBindTexture(GL_TEXTURE_2D,texture[0]);

glBegin(GL_QUADS);

// Top Face

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,

glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);

glEnd();

glBindTexture(GL_TEXTURE_2D,texture[0]);

glBegin(GL_QUADS);

// Bottom Face

glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);

glEnd();

glBindTexture(GL_TEXTURE_2D,texture[0]);

glBegin(GL_QUADS);

// Right face

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,

glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);

glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);

glEnd();

glBindTexture(GL_TEXTURE_2D,texture[0]);

glBegin(GL_QUADS);

// Left Face

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);

glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);

glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);

glEnd();

图形学实验3

实验3:A Racing Car (综合实验预计18 小时) 实验目的: ●熟练掌握和综合运用OpenGL编程技术来开发简单的三维交互式游戏 实验内容: 1.利用Gl/Glu/Glut库,编写一个OpenGL程序,实现以下功能: ●设计并绘制一辆汽车模型以及一个简单的直线跑道;其中,车轮可以用 glutCylinder来绘制。关于glutCylinder的使用可以参照下面的例子: GLUquadricObj *quadratic; int InitGL(GLvoid) // 此处开始对OpenGL进行所有设置 { quadratic=gluNewQuadric(); // 创建二次几何体 } int DrawGLScene(GLvoid) // 从这里开始进行所有的绘制 { gluCylinder(quadratic,0.6f,0.6f,0.4f,32,32);//画圆柱 } ●缺省视图是从外面一个固定的视点观察汽车和跑道; ●利用鼠标和键盘控制汽车前进、后退、转弯、加速和减速; ●制作一个弹出菜单,上面的菜单项用来控制车身和车轮的颜色以及退出程序; ●定义对应于ReShape事件的回调函数,使得当用户改变窗口的大小时,显示 的汽车不会变形。 2.加分题(可选择做其中的0个、1个或多个) ●采用弯曲的封闭的跑道。 ●轮胎画成封闭的形状。以上例子画出的只是一个两端开放的圆柱面, 你们可 以使用gluDisk(…) 将圆柱体两端封闭。 ●在缺省视图下,绘制汽车在跑道上的阴影(自定义一个假想的点光源); ●在路边设置一些路标,对于地面、跑道和/或天空进行纹理映射等以增强逼 真度。 ●除了缺省视图之外,支持第二种视图:坐在车内从驾驶座位向前看的视图。 两种视图之间用“t”键进行切换。 3.完成一份实验报告,描述你如何设计本程序,你的程序实现了哪些功能,并 且给出屏幕截图。

计算机图形学实验三报告

计算机科学与通信工程学院 实验报告 课程计算机图形学 实验题目二维图形变换 学生姓名 学号 专业班级 指导教师 日期

成绩评定表

二维图形变换 1. 实验内容 完成对北极星图案的缩放、平移、旋转、对称等二维变换。 提示:首先要建好图示的北极星图案的数据模型(顶点表、边表)。另外,可重复调用“清屏”和“暂停”等函数,使整个变换过程具有动态效果。 2. 实验环境 软硬件运行环境:Windows XP 开发工具:visual studio 2008 3. 问题分析

4. 算法设计 程序框架: //DiamondView.h class CDiamondView : public CView { …… public: //参数输入和提示对话框 void Polaris();//北极星 …… }; //DiamondView.cpp void CDiamondView::OnMenuDiamond() { IsCutting = FALSE; if(dlgDiamond.DoModal()==IDOK) DrawDiamond(dlgDiamond.m_nVertex,dlgDiamond.

m_nRadius,100);//调用绘制金刚石的函数 } //北极星 void CDiamondView::Polaris() {......} 5. 源代码 //北极星 void hzbjx(CDC* pDC,long x[18],long y[18]) { CPen newPen1,*oldPen; newPen1.CreatePen(PS_SOLID,2,RGB(255,0,0)); oldPen = pDC->SelectObject(&newPen1); POINT vertex1[11]={{x[1],y[1]},{x[2],y[2]},{x[3],y[3]},{x[4],y[4]},{x[5],y[5]},{x[3],y[3]},{x[1],y[1]}, {x[6],y[6]},{x[3],y[3]},{x[7],y[7]},{x[5],y[5]}}; pDC->Polyline(vertex1, 11); newPen1.DeleteObject(); newPen1.CreatePen(PS_SOLID, 2, RGB(0,255,0)); oldPen = pDC->SelectObject(&newPen1); POINT vertex2[5]={{x[6],y[6]},{x[8],y[8]},{x[9],y[9]},{x[3],y[3]},{x[8],y[8]}}; pDC->Polyline(vertex2, 5); POINT vertex3[5]={{x[4],y[4]},{x[10],y[10]},{x[11],y[11]},{x[3],y[3]},{x[10],y[10]}}; pDC->Polyline(vertex3, 5);

图形学实验报告

计 算 机 图 形 学 实验指导书 学号:1441901105 姓名:谢卉

实验一:图形的几何变换 实验学时:4学时 实验类型:验证 实验要求:必修 一、实验目的 二维图形的平移、缩放、旋转和投影变换(投影变换可在实验三中实现)等是最基本的图形变换,被广泛用于计算机图形学的各种应用程序中,本实验通过算法分析以及程序设计实验二维的图形变换,以了解变换实现的方法。如可能也可进行裁剪设计。 二、实验内容 掌握平移、缩放、旋转变换的基本原理,理解线段裁剪的算法原理,并通过程序设计实现上述变换。建议采用VC++实现OpenGL程序设计。 三、实验原理、方法和手段 1.图形的平移 在屏幕上显示一个人或其它物体(如图1所示),用交互操作方式使其在屏幕上沿水平和垂直方向移动Tx和Ty,则有 x’=x+Tx y’=y+Ty 其中:x与y为变换前图形中某一点的坐标,x’和y’为变换后图形中该点的坐标。其交互方式可先定义键值,然后操作功能键使其移动。 2.图形的缩放 在屏幕上显示一个帆船(使它生成在右下方),使其相对于屏幕坐标原点缩小s倍(即x方向和y方向均缩小s倍)。则有: x’=x*s y’=y*s 注意:有时图形缩放并不一定相对于原点,而是事先确定一个参考位置。一般情况下,参考点在图形的左下角或中心。设参考点坐标为xf、yf则有变换公式x’=x*Sx+xf*(1-Sx)=xf+(x-xf)*Sx y’=y*Sy+yf*(1-Sy)=yf+(y-yf)*Sy 式中的x与y为变换前图形中某一点的坐标,x’和y’为变换后图形中该点的坐标。当Sx>1和Sy>1时为放大倍数,Sx<1和Sy<1时为缩小倍数(但Sx和Sy

计算机图形学实验

实验1 直线的绘制 实验目的 1、通过实验,进一步理解和掌握DDA和Bresenham算法; 2、掌握以上算法生成直线段的基本过程; 3、通过编程,会在TC环境下完成用DDA或中点算法实现直线段的绘制。实验环境 计算机、Turbo C或其他C语言程序设计环境 实验学时 2学时,必做实验。 实验内容 用DDA算法或Besenham算法实现斜率k在0和1之间的直线段的绘制。 实验步骤 1、算法、原理清晰,有详细的设计步骤; 2、依据算法、步骤或程序流程图,用C语言编写源程序; 3、编辑源程序并进行调试; 4、进行运行测试,并结合情况进行调整; 5、对运行结果进行保存与分析; 6、把源程序以文件的形式提交; 7、按格式书写实验报告。 实验代码:DDA: # include # include

void DDALine(int x0,int y0,int x1,int y1,int color) { int dx,dy,epsl,k; float x,y,xIncre,yIncre; dx=x1-x0; dy=y1-y0; x=x0; y=y0; if(abs(dx)>abs(dy)) epsl=abs(dx); else epsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { putpixel((int)(x+0.5),(int)(y+0.5),4); x+=xIncre; y+=yIncre; } } main(){ int gdriver ,gmode ;

计算机图形学实验一

实验一二维基本图元的生成与填充 实验目的 1.了解并掌握二维基本图元的生成算法与填充算法。 2.实现直线生成的DDA算法、中点算法和Bresenham算法。 3.实现圆和椭圆生成的DDA和中点算法, 对几种算法的优缺点有感性认识。 二.实验内容和要求 1.选择自己熟悉的任何编程语言, 建议使用VC++6.0。 2.创建良好的用户界面,包括菜单,参数输入区域和图形显示区域。 3.实现生成直线的DDA算法、中点算法和Bresenham算法。 4.实现圆弧生成的中点算法。 5.实现多边形生成的常用算法, 如扫描线算法,边缘填充算法。 6.实现一般连通区域的基于扫描线的种子填充算法。 7.将生成算法以菜单或按钮形式集成到用户界面上。 8.直线与圆的坐标参数可以用鼠标或键盘输入。 6. 可以实现任何情形的直线和圆的生成。 实验报告 1.用户界面的设计思想和框图。 2.各种实现算法的算法思想。 3.算法验证例子。 4.上交源程序。 直线生成程序设计的步骤如下: 为编程实现上述算法,本程序利用最基本的绘制元素(如点、直线等),绘制图形。如图1-1所示,为程序运行主界面,通过选择菜单及下拉菜单的各功能项分别完成各种对应算法的图形绘制。 图1-1 基本图形生成的程序运行界面 2.创建工程名称为“基本图形的生成”单文档应用程序框架

(1)启动VC,选择“文件”|“新建”菜单命令,并在弹出的新建对话框中单击“工程”标签。 (2)选择MFC AppWizard(exe),在“工程名称”编辑框中输入“基本图形的生成”作为工程名称,单击“确定”按钮,出现Step 1对话框。 (3)选择“单个文档”选项,单击“下一个”按钮,出现Step 2对话框。 (4)接受默认选项,单击“下一个”按钮,在出现的Step 3~Step 5对话框中,接受默认选项,单击“下一个”按钮。 (5)在Step 6对话框中单击“完成”按钮,即完成“基本图形的生成”应用程序的所有选项,随后出现工程信息对话框(记录以上步骤各选项选择情况),如图1-2所示,单击“确定”按钮,完成应用程序框架的创建。 图1-2 信息程序基本 3.编辑菜单资源 设计如图1-1所示的菜单项。在工作区的ResourceView标签中,单击Menu项左边“+”,然后双击其子项IDR_MAINFRAME,并根据表1-1中的定义编辑菜单资源。此时VC已自动建好程序框架,如图1-2所示。 表1-1菜单资源表 菜单标题菜单项标题标示符ID 直线DDA算法生成直线ID_DDALINE Bresenham算法生成直线ID_BRESENHAMLINE 中点算法生成直线ID_MIDPOINTLINE 4.添加消息处理函数 利用ClassWizard(建立类向导)为应用程序添加与菜单项相关的消息处理函数,ClassName栏中选择CMyView,根据表1-2建立如下的消息映射函数,ClassWizard会自动完成有关的函数声明。 表1-2菜单项的消息处理函数 菜单项ID消息消息处理函数ID_DDALINE CONMMAN OnDdaline

计算机图形学实验报告

《计算机图形学》实验报告姓名:郭子玉 学号:2012211632 班级:计算机12-2班 实验地点:逸夫楼507 实验时间:15.04.10 15.04.17

实验一 1 实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析实验数据的能力; 编程实现DDA 算法、Bresenham 中点算法;对于给定起点和终点的直线,分别调用DDA 算法和Bresenham 中点算法进行批量绘制,并记录两种算法的绘制时间;利用excel 等数据分析软件,将试验结果编制成表格,并绘制折线图比较两种算法的性能。 2 实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One (自制平台) 3 实验结果 3.1 程序流程图 (1)DDA 算法 是 否 否 是 是 开始 计算k ,b K<=1 x=x+1;y=y+k; 绘点 x<=X1 y<=Y1 绘点 y=y+1;x=x+1/k; 结束

(2)Mid_Bresenham 算法 是 否 否 是 是 是 否 是 否 开始 计算dx,dy dx>dy D=dx-2*dy 绘点 D<0 y=y+1;D = D + 2*dx - 2*dy; x=x+1; D = D - 2*dy; x=x+1; x

3.2程序代码 //-------------------------算法实现------------------------------// //绘制像素的函数DrawPixel(x, y); (1)DDA算法 void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) { //----------请实现DDA算法------------// float k, b; float d; k = float(Y1 - Y0)/float(X1 - X0); b = float(X1*Y0 - X0*Y1)/float(X1 - X0); if(fabs(k)<= 1) { if(X0 > X1) { int temp = X0; X0 = X1; X1 = temp; }

计算机图形学实验报告 (2)

中南大学信息科学与工程学院 实验报告实验名称 实验地点科技楼四楼 实验日期2014年6月 指导教师 学生班级 学生姓名 学生学号 提交日期2014年6月

实验一Window图形编程基础 一、实验类型:验证型实验 二、实验目的 1、熟练使用实验主要开发平台VC6.0; 2、掌握如何在编译平台下编辑、编译、连接和运行一个简单的Windows图形应用程序; 3、掌握Window图形编程的基本方法; 4、学会使用基本绘图函数和Window GDI对象; 三、实验内容 创建基于MFC的Single Document应用程序(Win32应用程序也可,同学们可根据自己的喜好决定),程序可以实现以下要求: 1、用户可以通过菜单选择绘图颜色; 2、用户点击菜单选择绘图形状时,能在视图中绘制指定形状的图形; 四、实验要求与指导 1、建立名为“颜色”的菜单,该菜单下有四个菜单项:红、绿、蓝、黄。用户通过点击不同的菜单项,可以选择不同的颜色进行绘图。 2、建立名为“绘图”的菜单,该菜单下有三个菜单项:直线、曲线、矩形 其中“曲线”项有级联菜单,包括:圆、椭圆。 3、用户通过点击“绘图”中不同的菜单项,弹出对话框,让用户输入绘图位置,在指定位置进行绘图。

五、实验结果: 六、实验主要代码 1、画直线:CClientDC *m_pDC;再在OnDraw函数里给变量初始化m_pDC=new CClientDC(this); 在OnDraw函数中添加: m_pDC=new CClientDC(this); m_pDC->MoveTo(10,10); m_pDC->LineTo(100,100); m_pDC->SetPixel(100,200,RGB(0,0,0)); m_pDC->TextOut(100,100); 2、画圆: void CMyCG::LineDDA2(int xa, int ya, int xb, int yb, CDC *pDC) { int dx = xb - xa; int dy = yb - ya; int Steps, k; float xIncrement,yIncrement; float x = xa,y= ya; if(abs(dx)>abs(dy))

图形学实验报告

山东建筑大学测绘地理信息学院 实验报告 (2016—2017学年第一学期) 课程:计算机图形学 专业:地理信息科学 班级:地信141 学生姓名:王俊凝 学号:20140113010 指

实验一直线生成算法设计 一、实验目的 掌握基本图形元素直线的生成算法,利用编程语言C分别实现直线和圆的绘制算法。 二、实验任务 在TurboC环境下开发出绘制直线和圆的程序。 三、实验仪器设备 计算机。 四、实验方法与步骤 1 运行TurboC编程环境。 2 编写Bresenham直线绘制算法的函数并进行测试。 3 编写中点圆绘制算法的函数并进行测试。 4 增加函数参数,实现直线颜色的设置。 提示: 1. 编程时可分别针对直线和圆的绘制算法,设计相应的函数,例如void drawline(…)和void drawcircle(…),直线的两个端点可作为drawline的参数,圆的圆心和半径可作为drawcircle的参数。 2. 使用C语言编写一个结构体类型用来表示一个点,结构体由两个成员构成,x和y。这样,在向函数传入参数时,可使用两个点类型来传参。定义方法为:

typedef struct{ int x; int y; }pt2; 此处,pt2就是定义的一个新的结构体数据类型,之后就可用pt2来定义其他变量,具体用法见程序模板。 3. 在main函数中,分别调用以上函数,并传入不同的参数,实现对直线的绘制。 4. 线的颜色也可作为参数传入,参数可采用TurboC语言中的预设颜色值,具体参见TurboC图形函数。 五、注意事项 1 代码要求正确运行,直线和圆的位置应当为参数,实现可配置。 2 程序提交.c源文件,函数前和关键代码中增加注释。 程序模板 #include #include typedef struct{ int x; int y; }pt2; /*declare your drawing functions.*/ void drawline(pt2 startpt,pt2 endpt,int color); void drawcircle(pt2 centerpt,int radius,int color); void circlePlotPoints(pt2 centerpt,int x,int y,int color); int main() { int color,radius;

计算机图形学实验报告

目录

实验一直线的DDA算法 一、【实验目的】 1.掌握DDA算法的基本原理。 2.掌握DDA直线扫描转换算法。 3.深入了解直线扫描转换的编程思想。 二、【实验内容】 1.利用DDA的算法原理,编程实现对直线的扫描转换。 2.加强对DDA算法的理解和掌握。 三、【测试数据及其结果】 四、【实验源代码】 #include

#include #include #include GLsizei winWidth=500; GLsizei winHeight=500; void Initial(void) { glClearColor(1.0f,1.0f,1.0f,1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,200.0,0.0,150.0); } void DDALine(int x0,int y0,int x1,int y1) { glColor3f(1.0,0.0,0.0); int dx,dy,epsl,k; float x,y,xIncre,yIncre; dx=x1-x0; dy=y1-y0; x=x0; y=y0; if(abs(dx)>abs(dy)) epsl=abs(dx); else epsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { glPointSize(3); glBegin(GL_POINTS); glV ertex2i(int(x+0.5),(int)(y+0.5)); glEnd(); x+=xIncre; y+=yIncre; } } void Display(void) { glClear(GL_COLOR_BUFFER_BIT); DDALine(100,100,200,180); glFlush(); }

《计算机图形学实验报告》

一、实验目的 1、掌握中点Bresenham直线扫描转换算法的思想。 2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。 3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察流程。 4掌握三维形体在计算机中的构造及表示方法 二、实验环境 Windows系统, VC6.0。 三、实验步骤 1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下: void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y); 在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。 COLORREF SetPixel(int x, int y, COLORREF crColor ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine 函数画出不同斜率情况的直线,如下图:

最后、调试程序直至正确画出直线。 2、给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、实现边标志算法或有效边表算法函数,如下: void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb); px:该数组用来表示每个顶点的x坐标 py :该数组用来表示每个顶点的y坐标 ptnumb:表示顶点个数 注意实现函数FillPolygon可以直接通过窗口的DC(设备描述符)来进行多边形填充,不需要使用帧缓冲存储。(边标志算法)首先用画线函数勾画出多边形,再针对每条扫描线,从左至右依次判断当前像素的颜色是否勾画的边界色,是就开始填充后面的像素直至再碰到边界像素。注意对顶点要做特殊处理。 通过调用GDI画点函数SetPixel来画出填充过程中的每个点。需要画线可以使用CDC的画线函数MoveTo和LineTo进行绘制,也可以使用实验一实现的画直线函数。 CPoint MoveTo(int x, int y ); BOOL LineTo(int x, int y ); 实现边标志算法算法需要获取某个点的当前颜色值,可以使用CDC的成员函数 COLORREF GetPixel(int x, int y ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用FillPolygon 函数画出填充的多边形,如下: void CTestView::OnDraw(CDC* pDC) { CTestcoodtransDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

《计算机图形学基础》第三次大作业实验报告word资料3页

第三次实验 1. 实验目的 实现用 Phong 光照明模型显示网格模型(*.smf)。分别实现不使用/使用增量式光强/法 向插值算法,比较三种不同的显示效果和效率。 Phong模型中各参数可调,观察它们的作用。 与用户的交互方式为图形用户界面,操作简单,界面友好。 2. 算法描述 2.1. 基于扫描线算法的Phong 模型实现 上一次大作业中我没有完成扫描线 ZBuffer 算法,使得程序的效率很低,这次作业考虑 到各种计算对时间的消耗会更大,所以我首先完成了扫描线算法再进行这次作业代码的编写。 对扫描线Z-Buffer算法这里不作详细描述,主要介绍 Phong模型的实现。基于扫描线算 法的 Phong 模型实现是非常方便的,因为最基本的 Phong 模型中每个面的颜色是法向量的 函数,因此每个面的颜色是相同的,这样在扫描线算法之前我首先初始化了一个数组,将各 个面的颜色根据用户提供的参数以及 Phong 模型公式计算出来保存在这个数组里,每一项 对应一个面,这样在具体扫描线算法的执行过程中每一个点颜色的获取

都仅仅是对数组的读 取操作,是O(1)的复杂度,不会消耗太多时间。 算法如下: 1.对物体表面上的每个点P,均需计算光线L的反射方向R, R=2N(N·L)-L。 为了减少计算量,假设: 2.光源在无穷远处,L为常向量 3.视点在无穷远处,V为常向量 4.用(H?N)近似(R?V),H为L与V的平分向量 5.Phong光照明模型的RGB颜色模型形式 2.2. 双线性光强差值算法 考虑到双线性光强差值算法的核心思想是由顶点的光强插值计算各边的光强,然后由各 边的光强插值计算出多边形内部点的光强,结合之前实现的扫描线ZBuffer 算法,我使用了 增量的方式实现这个算法,也就是将它和扫描线算法结合起来,在扫描线算法每个面的边表 中多加几个个域来表示当前的光强、光强在X 方向的单位增量和光强在 Y 方向的单位增量, 这样在扫描到每个点的时候就可以根据前一个点的光强以及光强增量获得该点的光强,另外 在扫描线改变的时候光强也需要根据Y方向的增量来进行相应的修改。

计算机图形学实验报告

计算机图形学 实验报告 姓名:谢云飞 学号:20112497 班级:计算机科学与技术11-2班实验地点:逸夫楼507 实验时间:2014.03

实验1直线的生成 1实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析 实验数据的能力; 编程实现DDA算法、Bresenham中点算法;对于给定起点和终点的 直线,分别调用DDA算法和Bresenham中点算法进行批量绘制,并记 录两种算法的绘制时间;利用excel等数据分析软件,将试验结果编 制成表格,并绘制折线图比较两种算法的性能。 2实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One(自制平台)。 本实验提供名为 Experiment_Frame_One的平台,该平台提供基本 绘制、设置、输入功能,学生在此基础上实现DDA算法和Mid_Bresenham 算法,并进行分析。 ?平台界面:如错误!未找到引用源。所示 ?设置:通过view->setting菜单进入,如错误!未找到引 用源。所示 ?输入:通过view->input…菜单进入.如错误!未找到引用 源。所示 ?实现算法: ◆DDA算法:void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) Mid_Bresenham法:void CExperiment_Frame_OneView::Mid_Bresenham(int X0, int Y0, int X1, int Y1)

3实验结果 3.1程序流程图 1)DDA算法流程图:开始 定义两点坐标差dx,dy,以及epsl,计数k=0,描绘点坐标x,y,x增 量xIncre,y增量yIncre ↓ 输入两点坐标x1,y1,x0,y0 ↓ dx=x1-x0,dy=y1-y0; _________↓_________ ↓↓ 若|dx|>|dy| 反之 epsl=|dx| epsl=|dy| ↓________...________↓ ↓ xIncre=dx/epsl; yIncre=dy/epsl ↓ 填充(强制整形)(x+0.5,y+0.5); ↓←←←← 横坐标x+xIncre; 纵坐标y+yIncre; ↓↑ 若k<=epsl →→→k++ ↓ 结束 2)Mid_Bresenham算法流程图开始 ↓ 定义整形dx,dy,判断值d,以及UpIncre,DownIncre,填充点x,y ↓ 输入x0,y0,x1,y1 ______↓______ ↓↓ 若x0>x1 反之 x=x1;x1=x0;x0=x; x=x0;

计算机图形学实验二

实验报告 课程名称:计算机图形学 实验项目:区域填充算法 实验仪器:计算机 系别:计算机学院 专业:计算机科学与技术 班级姓名:计科1602/ 学号:2016011 日期:2018-12-8 成绩: 指导教师:

一.实验目的(Objects) 1.实现多边形的扫描线填充算法。 二.实验内容 (Contents) 实现多边形的扫描线填充算法,通过鼠标,交互的画出一个多边形,然后利用种子填充算法,填充指定的区域。不能使用任何自带的填充区域函数,只能使用画点、画线函数或是直接对图像的某个像素进行赋值操作;

三.实验内容 (Your steps or codes, Results) //widget.cpp //2016CYY Cprogramming #include"widget.h" #include #include #include using namespace std; #define H 1080 #define W 1920 int click = 0; //端点数量 QPoint temp; QPoint first; int result = 1; //判断有没有结束 int sign = 1; //2为画线 int length = 5; struct edge { int ymax; float x; float dx; edge *next; }; edge edge_; QVector edges[H]; QVector points;//填充用 bool fin = false; QPoint *Queue = (QPoint *)malloc(length * sizeof(QPoint)); //存放端点的数组 Widget::Widget(QWidget *parent) : QWidget(parent) { } Widget::~Widget() { } void Widget::mouseMoveEvent(QMouseEvent *event) { setMouseTracking(true); if (click > 0 && result != 0) { startPt = temp; endPt =event->pos(); sign = 2; update(); } } void Widget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { } else if (event->button() == Qt::RightButton) { sign = 2;

计算机图形学实验报告三

《计算机图形学》实验报告

glClear(GL_COLOR_BUFFER_BIT); //glEnable(GL_SCISSOR_TEST); //glScissor(0.0f,0.0f,500,300); glutWireTeapot(0.4); glFlush(); } //窗口调整子程序 void myReshape(int w, int h) { glViewport(500, -300, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-1, 1, -(float)h / w, (float)h / w, -1, 1); else glOrtho(-(float)w / h, (float)w / h, -1, 1, -1, 0.5); } 2,使用opengl函数写一个图形程序,要求分别使用三个光源从一个茶壶的前右上方(偏红色),正左侧(偏绿色)和前左下方(偏蓝色)对于其进行照射,完成程序并观察效果。

} //绘图子程序 void display(void) { glColor3f(1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); //设置光源的属性1 GLfloat LightAmbient1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; //环境光参数 ( 新增 ) GLfloat LightDiffuse1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; // 漫射光参数 ( 新增 ) GLfloat Lightspecular1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; // 镜面反射 GLfloat LightPosition1[] = { 500.0f, 500.0f, 500.0f, 1.0f }; // 光源位置 ( 新增 ) glLightfv(GL_LIGHT0, GL_POSITION, LightPosition1);

图形学实验报告

课程设计报告实验名称:计算机图形学实验

目录 1.1 实验目的与要求 (1) 1.2 实验任务内容与步骤 (1) 实验一 (1) 实验二 (3) 1.3 实验结果 (3) 实验一结果 (3) 实验二结果 (8) 1.4 心得体会 (8) 1.5 源代码 (9)

1.1实验目的与要求: 目的: 利用OpenGL库,对课本的图形原理进行C语言编程,从而实现各种绘图算法。从中进一步了解计算机图形学的原理,加深对课程内容的理解,逐步掌握算法原理的实现过程。另外,初步掌握OpenGL的基本使用方法,能够使用其进行简单图形、图素的绘制。 实验要求: I. (1)理解glut程序框架 (2)理解窗口到视区的变换 (3)理解OpenGL实现动画的原理 (4)添加代码实现中点Bresenham算法画直线 (5)添加代码实现改进Bresenham算法画直线 (6)添加代码实现圆的绘制(可以适当对框架坐标系进行修改 II. (1)理解OpenGL中的变换过程 (2)理解透视投影与平行投影的不同 (3)添加代码实现太阳、地球和月亮的运动模型 (4)了解深度测试 (5)通过变换调整观察的位置与方向 (6)加入光照模型 1.2实验内容和实验步骤: 实验一、利用各种算法实现直线与圆的扫描转换,在对应图中显示的同时,还要在控制台中打印显示像素点的坐标,以及误差d,e的值。 (1)中点Bresenham算法 ①.利用中点Bresenham算法画出直线,其中直线的斜率要求为:0<=k<=1. ②.具体参数如下: x0,y0 起点坐标 x1,y1 终点坐标 num 扫描转换时从起点开始输出的点的数目

计算机图形学实验(3-6)

实验三:区域填充 一、实验目的 区域填充是指先将区域内的一点(常称为种子点)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。区域填充技术广泛应用于交互式图形、动画和美术画的计算机辅助制作中。本实验采用递归填充算法或扫描线算法实现对光栅图形的区域填充。通过本实验,可以掌握光栅图形编程的基本原理和方法。 二、实验内容 掌握光栅图形的表示方法,实现种子算法或扫描线算法。通过程序设计实现上述算法。 建议采用VC++实现OpenGL程序设计。 三、实验原理、方法和手段 递归算法 在要填充的区域内取一点(X,Y)的当前颜色记为oldcolor,用要填充的颜色ne wcolor去取代,递归函数如下: procedure flood-fill(X,Y,oldcolor,newcolor:integer); begin if getpixel(framebuffer,x,y)=oldcolor then begin setpixel(framebuffer,x,y,newcolor); flood-fill(X,Y+1,oldcolor,newcolor); flood-fill(X,Y-1,oldcolor,newcolor); flood-fill(X-1,Y,oldcolor,newcolor); flood-fill(X+1,Y,oldcolor,newcolor); end end 扫描线算法 扫描线算法的效率明显高于递归算法,其算法的基本思想如下:(1)(初始化)将算法设置的堆栈置为空,将给定的种子点(x,y)压入堆栈。 (2)(出栈)如果堆栈为空,算法结束;否则取栈顶元素(x,y)作为种子点。 (3)(区段填充)从种子点(x,y)开始沿纵坐标为y的当前扫描线向左右两个方向逐个象素进行填色,其值置为newcolor,直到抵达边界为止。 (4)(定范围)以x left和x right分别表示在步骤3中填充的区段两端点的横坐标。 (5)(进栈)分别在与当前扫描线相邻的上下两条扫描线上,确定位于区间[x left,x right]内的给定区域的区段。如果这些区段内的象素的颜色值为newcolor或者boundarycolor(边界上象素的颜色值),则转到步骤2,否则取区段的右端点为种子压入堆栈,再转到步骤2继续执行。 四、实验组织运行要求 本实验采用集中授课形式,每个同学独立完成上述实验要求。

计算机图形学实验3

实验三 课程名称:计算机图形学实验名称:曲线的生成实验日期:2015.4.22 班级:数媒1302 姓名:徐进都学号1030513230 仪器编号:×× 一、实验目的和要求 1、掌握Hermite曲线生成算法; 2、掌握Bezier曲线的定义生成算法、离散生成算法,了解Bezier曲面的生成算法; 3、掌握B样条曲线的定义生成算法,了解B样条曲面。 二、实验内容 1、已知空间点两点P0(-40.0,-40.0,0.0)、P1(10.0,-200.0,0.0)及该点上的切向量分别为R0(30.0,240.0,0.0),R1(30.0,-240.0,0.0)。运行附件程序,分析理解Hermite曲线生成算法。 2、已知空间四点P0(-40.0,-40.0,0.0)、P1(-10.0,200.0,0.0)、P2(10.0,-200.0,0.0)、P3(40.0,40.0,0.0),参照1的程序并根据Bezier曲线的定义编程绘制三次Bezier曲线。 3、已知空间四点P0(-40.0,-40.0,0.0)、P1(-10.0,200.0,0.0)、P2(10.0,-200.0,0.0)、P3(40.0,40.0,0.0),参照1的程序并根据B样条曲线的定义绘制三次B样条曲线。 4、思考如何利用实验一到实验三所学的知识,实现绘制自己的姓名。(该题作为平时成绩的单独加分项) 三、实验步骤 P(t)=(1-t)3p0+3t(1-t)2p1+3t2(1-t)p2+t3p3 0 #include #include #include GLsizei winWidth = 600, winHeight = 600; GLfloat xwcMin = -50, xwcMax = 50;

图形学实验5

图形学实验5

《3D游戏图形学》实验报告书 (实验五)

姓名: 学号: 班级: 浙江理工大学 二0一二年十二月

实验五纹理映射实验 一、实验目的和要求 掌握纹理映射的基本原理,利用VC++ OpenGL实现纹理映射技术。 二、实验原理 纹理映射是真实感图形制作的一个重要部分,运用纹理映射可以方面地制作真实感图形,而不必花更多的时间去考虑物体的表面纹理。如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。然后的具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。 另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。 此外,纹理映射也可以用于其他方面。例如,使用一大片植被的图像映射到一些连续的多边

形上,以模拟地貌,或者以大理石、木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。 在OpenGL中提供了一系列完整的纹理操作 函数,用户可以用它们构造理想的物体表面,可以对光照物体进行处理,使其映射出所处环境的景象,可以用不同方式应用到曲面上,而且可以随几何物体的几何属性变换而变化,从而使制作的三维场景和三维物体更真实更自然。 在OpenGL中要实现纹理映射,需要经历创建纹理、指定纹理应用方式、启用纹理映射、使用纹理坐标和几何坐标绘制场景几个过程。 用于指定一维、二维和三维纹理的函数分别为: Void glTexImage1D(GLenum target, Glint level, Glint components, GLsizei width, Glint border, GLenum format, GLenum type, const GLvoid *texels); Void glTexImage2D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels);

计算机图形学实验代码及截图分解

目录 实验一:OpenGL基础知识 (1) 实验二 OpenGL中的建模与变换 (2) 实验三 OpenGL中的光照 (5) 实验四 OpenGL中的拾取 (8) 实验五 OpenGL中的纹理映射 (11)

实验一:OpenGL基础知识 一、实验目的 1、建立Windows系统下的OpenGL实验框架。 2、学习理解OpenGL工作流程。 二、实验环境 ⒈硬件:每个学生需配备计算机一台。 ⒉软件:Visual C++; 三、实验内容 1、建立非控制台的Windows程序框架。 2、建立OpenGL框架。 3、建立OpenGL框架的类文件。 4、完善Windows框架。 5、理解程序间的相互关系。 四、实验要求 1、学习教材第2章的内容。 2、理解教材中相关实例的代码,按要求添加到适当的地方,调试并通过运行。 3、运行结果应该与教材中的相关实例相符。 4、编译第2章的框架代码,修改背景色、窗口标题。 五、程序设计提示 (略) 六、报告要求 1.认真书写实验报告,字迹清晰,格式规范。报告中应写清姓名、学号、实验日期、实验题目、实验目的、实验原理。 2.报告中应书写主要源程序,且源程序中要有注释。 3.报告中应包含运行结果及结果分析。如调试通过并得到预期的效果,请注明‘通过’并粘贴运行效果图;如未调试通过或结果不正确,试分析原因。 4.报告最后包含实验总结和体会。

实验二 OpenGL中的建模与变换 一、实验目的 1.学习配置OpenGL环境。 2.掌握在OpenGL中指定几何模型的方法。 3. 掌握OpenGL中的透视投影和正投影的设置方法,学会诊断投影问题导致的显示异常。 二、实验环境 ⒈硬件:每个学生需配备计算机一台。 ⒉软件:Visual C++; 三、实验内容 1.建立OpenGL编程环境 (注:Windows自带gl和glu,还需要安装glut库文件。) (a)查看Windows自带的OpenGL文件。在文件夹c:\windows\system32下查看是否存在文件opengl32.dll和glu32.dll;在Visual Studio的安装目录Vc7\PlatformSDK\Include\gl下查看是否存在gl.h和glu.h;在Vc7\PlatformSDK\Lib下是否存在opengl32.lib和glu32.lib。 (b)安装glut库。将文件glut.h复制到Visual Studio的安装目录Vc7\PlatformSDK\Include\gl下;将文件glut32.lib复制到Vc7\PlatformSDK\Lib下;将文件glut32.dll复制到c:\windows\system32下。 2.OpenGL几何建模 (a)建立基本的几何图元,指定图元的颜色,对图元进行平移、旋转、缩放变换。基本几何图元包括: GL_LINES(线)、GL_LINE_STRIP(线带)、GL_LINE_LOOP(线环)、GL_TRIANGLES(三角形)、GL_TRIANGLE_STRIP(三角形带)、GL_TRIANGLE_FAN(三角形扇)、GL_QUADS(四边形)、GL_QUAD_STRIP(四边形带)、GL_POLYGON(多边形)。 (b) 设置合适的投影参数,分别用透视投影和正投影显示步骤(a)中指定的几何图元。 (c) 每按下鼠标左键一次,模型向右旋转一定角度。 (d) 按下ESC键,退出程序。

相关文档
最新文档