第一篇:圖形學(xué)實(shí)驗(yàn)5
《3D游戲圖形學(xué)》
實(shí)驗(yàn)報(bào)告書(shū)
(實(shí)驗(yàn)五)
姓名:
學(xué)號(hào): 班級(jí):
浙江理工大學(xué) 二0一二 年 十二 月
數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
實(shí)驗(yàn)五 紋理映射實(shí)驗(yàn)
一、實(shí)驗(yàn)?zāi)康暮鸵?/p>
掌握紋理映射的基本原理,利用VC++ OpenGL實(shí)現(xiàn)紋理映射技術(shù)。
二、實(shí)驗(yàn)原理
紋理映射是真實(shí)感圖形制作的一個(gè)重要部分,運(yùn)用紋理映射可以方面地制作真實(shí)感圖形,而不必花更多的時(shí)間去考慮物體的表面紋理。如一張木制桌子其表面的木紋是不規(guī)范的,看上去又是那么自然,如果在圖形制作中不用紋理映射,那么只是這張桌面紋理的設(shè)計(jì),就要花費(fèi)很大精力,而且設(shè)計(jì)結(jié)果也未必能像現(xiàn)實(shí)中那么自然。如果運(yùn)用紋理映射就非常方便,可以用掃描儀將這樣的一張桌子掃成一個(gè)位圖。然后的具體的操作中,只需把桌面形狀用多邊形畫出來(lái),把桌面紋理貼上去就可以了。
另外,紋理映射能夠在多邊形進(jìn)行變換時(shí)仍保證紋理的圖案與多邊形保持一致性。例如,以透視投影方式觀察墻面時(shí),遠(yuǎn)端的磚會(huì)變小,而近處的磚就會(huì)大一些。
此外,紋理映射也可以用于其他方面。例如,使用一大片植被的圖像映射到一些連續(xù)的多邊形上,以模擬地貌,或者以大理石、木紋等自然物質(zhì)的圖像作為紋理映射到相應(yīng)的多邊形上,作為物體的真實(shí)表面。
在OpenGL中提供了一系列完整的紋理操作函數(shù),用戶可以用它們構(gòu)造理想的物體表面,可以對(duì)光照物體進(jìn)行處理,使其映射出所處環(huán)境的景象,可以用不同方式應(yīng)用到曲面上,而且可以隨幾何物體的幾何屬性變換而變化,從而使制作的三維場(chǎng)景和三維物體更真實(shí)更自然。
在OpenGL中要實(shí)現(xiàn)紋理映射,需要經(jīng)歷創(chuàng)建紋理、指定紋理應(yīng)用方式、啟用紋理映射、使用紋理坐標(biāo)和幾何坐標(biāo)繪制場(chǎng)景幾個(gè)過(guò)程。
用于指定一維、二維和三維紋理的函數(shù)分別為: 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);其中,參數(shù)target取值一般為GL_TEXTURE_1D, GL_TEXTURE_2D和GL_TEXTURE_3D,分別與一維、二維和三維的紋理相對(duì)應(yīng)。參數(shù)Level表示紋理多分辨率層數(shù),通常取值為0,表示只有一種分辨率。參數(shù)components的可能取值為1~4的整數(shù)以及多種符號(hào)常量(如GL_RGBA),表示紋理元素中存儲(chǔ)的哪些分量(RGBA顏色、深度等)在紋理映射中被使用,1表示使用R顏色分量,2表示使用R和A顏色分量,3表示使用RGB顏色分量,4表示使用RGBA顏色分量。參數(shù)width,height,depth分別指定紋理的寬度、高度、深度。參數(shù)format和type表示給出的圖像數(shù)據(jù)的數(shù)據(jù)格式和數(shù)據(jù)類型,這兩個(gè)參數(shù)的取值都是符號(hào)常量(比如format指定為GL_RGBA,type指定為GL_UNSIGNED_BYTE,參數(shù)texels指向內(nèi)存中指定的紋理圖像數(shù)據(jù)。
在定義了紋理之后,需要啟用紋理的函數(shù): 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
glEnable(GL_TEXTURE_1D);glEnable(GL_TEXTURE_2D);glEnable(GL_TEXTURE_3D);在啟用紋理之后,需要建立物體表面上點(diǎn)與紋理空間的對(duì)應(yīng)關(guān)系,即在繪制基本圖元時(shí),在glVertex函數(shù)調(diào)用之前調(diào)用glTexCoord函數(shù),明確指定當(dāng)前頂點(diǎn)所對(duì)應(yīng)的紋理坐標(biāo),例如:
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();其圖元內(nèi)部點(diǎn)的紋理坐標(biāo)利用頂點(diǎn)處的紋理坐標(biāo)采用線性插值的方法計(jì)算出來(lái)。
在OpenGL中,紋理坐標(biāo)的范圍被指定在[0,1]之間,而在使用映射函數(shù)進(jìn)行紋理坐標(biāo)計(jì)算時(shí),有可能得到不在[0,1]之間的坐標(biāo)。此時(shí)OpenGL有兩種處理方式,一種是截?cái)?,另一種是重復(fù),它們被稱為環(huán)繞模式。在截?cái)嗄J剑℅L_CLAMP)中,將大于1.0的紋理坐標(biāo)設(shè)置為1.0,將小于0.0的紋理坐標(biāo)設(shè)置為0.0。在重復(fù)模式(GL_REPEAT)中,如果紋理坐標(biāo)不在[0,1]之間,則將紋理坐標(biāo)值的整數(shù)部分舍棄,只使用小數(shù)部分,這樣使紋理圖像在物體表面重復(fù)出現(xiàn)。例如,使用下面的函數(shù):
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);分別指定二維紋理中s坐標(biāo)采用截?cái)嗷蛑貜?fù)處理方式。
另外,在變換和紋理映射后,屏幕上的一個(gè)像素可能對(duì)應(yīng)紋理元素的一小部分(放大),也可能對(duì)應(yīng)大量的處理元素(縮小)。在OpenGL中,允許指定多種方式來(lái)決定如何完成像素與紋理元素對(duì)應(yīng)的計(jì)算方法(濾波)。比如,下面的函數(shù)可以指定放大和縮小的濾波方法:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);其中,glTexParameteri函數(shù)的第一個(gè)參數(shù)指定使用的是一維、二維或三維紋理;第二個(gè)參數(shù)為GL_TEXTURE_MAG_FILTER或GL_TEXTURE_MIN_FILTER,指出要指定縮小還是放大濾波算法;最后一個(gè)參數(shù)指定濾波的方法。
補(bǔ)充:透視投影函數(shù)
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);它也創(chuàng)建一個(gè)對(duì)稱透視視景體,但它的參數(shù)定義于前面的不同。其操作是創(chuàng)建一個(gè)對(duì)稱的透視投影矩陣,并且用這個(gè)矩陣乘以當(dāng)前矩陣。參數(shù)fovy定義視野在X-Z平面的角度,范圍是[0.0,180.0];參數(shù)aspect是投影平面寬度與高度的比率;參數(shù)zNear和Far分別是遠(yuǎn)近裁剪面沿Z負(fù)軸到視點(diǎn)的距離,它們總為正值。
三、實(shí)驗(yàn)內(nèi)容
在OpenGL中紋理映射所使用的紋理數(shù)據(jù),既可以是程序生成的一組數(shù)據(jù),也可以從外部文件中直接讀取,參考示范代碼完成以下兩項(xiàng)內(nèi)容: 1.利用直接創(chuàng)建紋理的方法生成二維紋理并映射到四邊形上。參考代碼:
void makeImage(void){ 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
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);// 生成紋理數(shù)據(jù) makeImage();// 設(shè)置像素存儲(chǔ)模式
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);// 定義二維紋理映射 glTexImage2D(……);// 定義紋理映射參數(shù) 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[]){ ……} 2.從外部文件中直接讀取紋理實(shí)現(xiàn)正方體每個(gè)面的紋理映射,并使正方體轉(zhuǎn)動(dòng)。
數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
整個(gè)過(guò)程需要三個(gè)步驟:創(chuàng)建紋理、啟用紋理映射和使用紋理坐標(biāo)和幾何坐標(biāo)繪制,下面我們對(duì)三個(gè)過(guò)程進(jìn)行闡述,并給出參考代碼。1)創(chuàng)建紋理對(duì)象并綁定紋理
紋理創(chuàng)建即在內(nèi)存中創(chuàng)建保存紋理數(shù)據(jù)的數(shù)組,一般是先讀入一個(gè)圖像文件,將圖像文件的RGBA信息存入我們創(chuàng)建的紋理空間中,當(dāng)然圖像的位圖不同,創(chuàng)建的紋理空間結(jié)構(gòu)也會(huì)有所不同。為了更加簡(jiǎn)單易懂地實(shí)現(xiàn)這個(gè)過(guò)程,我們使用未壓縮的紋理。代碼:
GLuinttexture[1];//創(chuàng)建一個(gè)紋理空間
AUX_RGBImageRec *LoadBMP(CHAR *Filename)//載入位圖圖像 { FILE *File=NULL;//文件句柄
if(!Filename)//確保文件名已提供
{
return NULL;} File=fopen(Filename, “r”);//嘗試打開(kāi)文件
if(File){
fclose(File);//關(guān)閉文件
return auxDIBImageLoadA(Filename);//載入位圖并返回指針
} return NULL;} //如果載入失敗,返回NULL int LoadGLTextures()//載入位圖并轉(zhuǎn)換成紋理 { int Status=FALSE;//狀態(tài)指示器
AUX_RGBImageRec *TextureImage[1];//創(chuàng)建紋理的存儲(chǔ)空間
memset(TextureImage, 0, sizeof(void *)*1);//初始化 //載入位圖,檢查有無(wú)錯(cuò)誤,如果位圖沒(méi)找到則退出
if(TextureImage[0]=LoadBMP(“data.bmp”)){
Status=TRUE;
glGenTextures(1,&texture[0]);//創(chuàng)建紋理 //使用來(lái)自位圖數(shù)據(jù)生成的典型紋理
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)//紋理圖像是否存在 { 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
free(TextureImage[0]->data);//釋放紋理圖像占用的內(nèi)存
}
free(TextureImage[0]);//釋放圖像結(jié)構(gòu)
} return Status;//返回Status }
2)啟用紋理映射操作,初始化相關(guān)參數(shù)
在OpenGL中使用紋理映射之前,必須打開(kāi)紋理映射。int InitGL(GLvoid){ if(!LoadGLTextures())//調(diào)用紋理載入子例程
{
return FALSE;} glEnable(GL_TEXTURE_2D);//啟用紋理映射
glShadeModel(GL_SMOOTH);//啟用陰影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);//黑色背景
glClearDepth(1.0f);//設(shè)置深度緩存
glEnable(GL_DEPTH_TEST);//啟用深度測(cè)試
return TRUE;}
3)使用紋理坐標(biāo)和幾何坐標(biāo)繪制 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]);//繪制一個(gè)正方體,給每個(gè)面貼上紋理,并使之轉(zhuǎn)動(dòng)
glBegin(GL_QUADS);……
glEnd();xrot+=0.3f;yrot+=0.2f;zrot+=0.4f;}
四、實(shí)驗(yàn)代碼 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū)
1、利用直接創(chuàng)建紋理的方法生成二維紋理并映射到四邊形上。#include
#define imageWidth 64 #define imageHeight 64 GLubyte image[imageWidth][imageHeight][3];
/*繪制一個(gè)簡(jiǎn)單的二維紋理圖*/ void makeImage(void){ int i,j,r,g,b;
/*根據(jù)點(diǎn)的位置設(shè)置不同的顏色*/ for(i = 0;i < imageWidth;i++){
for(j = 0;j r =(i*j)%255; g =(i*i)%255; b =(j*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);// 生成紋理數(shù)據(jù) makeImage();// 設(shè)置像素存儲(chǔ)模式 glPixelStorei(GL_UNPACK_ALIGNMENT,1);/*指定二維紋理映射*/ glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);//紋理過(guò)濾函數(shù) /*GL_TEXTURE_2D: 操作D紋理.GL_TEXTURE_WRAP_S: S方向上的貼圖模式.GL_CLAMP: 將紋理坐標(biāo)限制在.0,1.0的范圍之內(nèi).如果超出了會(huì)如何呢.不會(huì)錯(cuò)誤,只是會(huì)邊緣拉伸填充.GL_TEXTURE_MAG_FILTER: 放大過(guò)濾 GL_LINEAR: 線性過(guò)濾, 使用距離當(dāng)前渲染像素中心最近的個(gè)紋素加權(quán)平均值.數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) GL_TEXTURE_MIN_FILTER: 縮小過(guò)濾 GL_LINEAR_MIPMAP_NEAREST: 使用GL_NEAREST對(duì)最接近當(dāng)前多邊形的解析度的兩個(gè)層級(jí)貼圖進(jìn)行采樣,然后用這兩個(gè)值進(jìn)行線性插值.*/ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);/*設(shè)置紋理環(huán)境參數(shù)*/ //glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);// 啟用二維紋理 glEnable(GL_TEXTURE_2D);glShadeModel(GL_FLAT);} void myDisplay(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/*將紋理映射到四邊形上*/ glBegin(GL_QUADS);/*紋理的坐標(biāo)和四邊形頂點(diǎn)的對(duì)應(yīng)*/ glTexCoord2f(0.0,0.0);glVertex3f(-0.7,-0.25,0.0);glTexCoord2f(0.0,1.0);glVertex3f(-0.2,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(-0.2,0.25,0.0);glTexCoord2f(1.0,0.0);glVertex3f(-0.7,0.25,0.0);glTexCoord2f(0.0,0.0);glVertex3f(0.2,-0.25,1.875);glTexCoord2f(0.0,1.0);glVertex3f(0.6,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(0.6,0.25,0.125);glTexCoord2f(1.0,0.0);glVertex3f(0.2,0.25,2.0);glEnd();glFlush();} void myReshape(int w,int 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(400,400);數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) glutInitWindowPosition(200,200);glutCreateWindow(“ Texture ”);//創(chuàng)建窗口 myInit();//繪制與顯示 glutReshapeFunc(myReshape);glutDisplayFunc(myDisplay);glutMainLoop();return 0;} 2、從外部文件中直接讀取紋理實(shí)現(xiàn)正方體每個(gè)面的紋理映射,并使正方體轉(zhuǎn)動(dòng)。#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];//創(chuàng)建紋理空間 GLfloat xRot,yRot,zRot;//控制正方體的旋轉(zhuǎn) //載入位圖圖像 AUX_RGBImageRec *LoadBMP(CHAR *Filename){ //載入位圖圖像 FILE *File=NULL; //文件句柄 if(!Filename){ //確保文件名已提供 return NULL;} File=fopen(Filename, “r”); //嘗試打開(kāi)文件 if(File){ fclose(File); //關(guān)閉文件 return auxDIBImageLoadA(Filename); //載入位圖并返回指針 } return NULL; //如果載入失敗,返回NULL } int LoadGLTextures(){ //載入位圖并轉(zhuǎn)換成紋理 int Status=FALSE; //狀態(tài)指示器 AUX_RGBImageRec *TextureImage[1]; //創(chuàng)建紋理的存儲(chǔ)空間 memset(TextureImage, 0, sizeof(void *)*1);//初始化 //載入位圖,檢查有無(wú)錯(cuò)誤,如果位圖沒(méi)找到則退出 if(TextureImage[0]=LoadBMP(“data.bmp”)){ Status=TRUE; glGenTextures(1,&texture[0]); //創(chuàng)建紋理 //使用來(lái)自位圖數(shù)據(jù)生成的典型紋理 glBindTexture(GL_TEXTURE_2D, texture[0]); //生成D紋理 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 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); //釋放紋理圖像占用的內(nèi)存 } free(TextureImage[0]); //釋放圖像結(jié)構(gòu) } return Status; //返回Status } int InitGL(GLvoid){ if(!LoadGLTextures()){ //調(diào)用紋理載入子例程 return FALSE;} glEnable(GL_TEXTURE_2D); //啟用紋理映射 glShadeModel(GL_SMOOTH); //啟用陰影平滑 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //黑色背景 glClearDepth(1.0f); //設(shè)置深度緩存 glEnable(GL_DEPTH_TEST); //啟用深度測(cè)試 return TRUE;} void display(){ 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); //繪制正方體,貼上紋理并使之轉(zhuǎn)動(dòng) glBindTexture(GL_TEXTURE_2D,texture[0]);//選擇紋理 glBegin(GL_QUADS); //前 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); //后 glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 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); // 上 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); glTexCoord2f(1.0f, 1.0f);glVertex3f(1.0f, 1.0f,-1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); //下 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); //右 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); //左 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(); glutPostRedisplay(); glutSwapBuffers(); } void reshape(int w,int h){ if(0 == h) h = 1; glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION);數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) glLoadIdentity(); gluPerspective(60.0f,(GLfloat)w /(GLfloat)h,1,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void spinDisplay(void){ xRot += 0.2f; yRot += 0.2f; glutPostRedisplay();} void mouse(int button, int state, int x, int y)//鼠標(biāo)監(jiān)聽(tīng) { switch(button){ case GLUT_LEFT_BUTTON: if(state == GLUT_DOWN) glutIdleFunc(spinDisplay);//設(shè)備空閑時(shí)調(diào)用的函數(shù) break; case GLUT_MIDDLE_BUTTON: case GLUT_RIGHT_BUTTON: if(state == GLUT_DOWN) glutIdleFunc(NULL); break; default: break; } } int main(int argc,char** argv){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(400,400); glutInitWindowPosition(100,100); glutCreateWindow(“Texture Map”); InitGL(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse);//鼠標(biāo)監(jiān)聽(tīng) glutMainLoop(); return 0; } 五、實(shí)驗(yàn)結(jié)果 1、利用直接創(chuàng)建紋理的方法生成二維紋理并映射到四邊形上。數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 2、從外部文件中直接讀取紋理實(shí)現(xiàn)正方體每個(gè)面的紋理映射,并使正方體轉(zhuǎn)動(dòng)。(按左鍵轉(zhuǎn)動(dòng),按右鍵停止) 六、實(shí)驗(yàn)心得 實(shí)驗(yàn)三 MFC畫直線 最近自己在學(xué)習(xí)如何在VC 6.0 開(kāi)發(fā)環(huán)境下的使用MFC AppWizard(exe)來(lái)繪畫一條直線,雖然比較簡(jiǎn)單,通過(guò)這樣的練習(xí)可以幫助你熟悉MFC的開(kāi)發(fā)環(huán)境以及其中的消息傳遞機(jī)制,希望對(duì)于像我一樣初入MFC圖形繪制學(xué)習(xí)的人有幫 助 第一步:構(gòu)建MFC窗體 打開(kāi)Visual C++ 6.0編譯器 新建→工程→MFC AppWizard(exe),工程名以DrawLine為例,然后確定。為了方便,在MFC應(yīng)用程序向?qū)А襟E1當(dāng)中選擇“單文檔”,其余所有的步驟都為默認(rèn)值,直接“完成”。這樣一個(gè)簡(jiǎn)單的MFC窗體就構(gòu)建好了,自己不妨Compile—Build—BuildExecute一下。 第二步:編輯菜單項(xiàng) 選擇ResourceView視窗展開(kāi)Menu文件夾,左鍵雙擊IDR_DRAWLITYPE,右邊就會(huì)出現(xiàn)菜單圖形編輯界面,為了簡(jiǎn)化,我們只在添加幫助→DrawLine功能選擇項(xiàng)。雙擊空白會(huì)彈出“菜單項(xiàng)目 屬性”對(duì)話框。ID:ID_DRAW_LINE;標(biāo)明: DrawLine(&D),其它的為缺省。 第三步:建立消息命令 如果此時(shí)運(yùn)行該程序,你會(huì)發(fā)現(xiàn)幫助—DrawLine的功能選項(xiàng)是灰色的,原因就在于我們還沒(méi)有添加該功能的消息命令相應(yīng)函數(shù)。通過(guò)“查看—Message Maps—Project:DrawLine—Class name:CDrawLineView—Object IDs:ID_DRAW_LINE—選定COMMAND—Add Function?”,其它為默認(rèn),最后確定完成?,F(xiàn)在如果再重新運(yùn)行該程序的話,會(huì)發(fā)現(xiàn)原來(lái)的灰色已經(jīng)消除了。 第四步:添加鼠標(biāo)消息響應(yīng) 打開(kāi)ClassView視窗,右鍵選定CDrawLineView,選擇Add Windows Messsage Handler會(huì)彈出對(duì)話框,完成CDrawLineView類的WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP三個(gè)Windows消息事件的新建。 第五步:添加響應(yīng)代碼 首先,在ClassView視窗中雙擊CDrawLineView會(huì)定位到“DrawLineView.h : interface of the CDrawLineView class”的文件,添加CDrawLineView類的成員:protected: int m_Drag;POINT m_pPrev;POINT m_pOrigin;三個(gè)成員變量。視窗中展開(kāi)CDrawLineView類,雙擊定位OnLBUTTONDOWN()函數(shù)。在該函數(shù)消息響應(yīng) 處添加如下代碼: //建立好繪圖的設(shè)備環(huán)境 CClientDC dc(this);OnPrepareDC(&dc); dc.DPtoLP(&point); //獲取起始點(diǎn)坐標(biāo) m_pPrev=point;m_pOrigin=point; m_Drag=1; 然后,定位于OnMouseMove(),添加如下代碼(其中關(guān)鍵用到了橡皮筋技術(shù)): //建立好繪圖的設(shè)備環(huán)境 CClientDC dc(this); OnPrepareDC(&dc);dc.DPtoLP(&point); dc.SetROP2(R2_NOT);//橡皮筋繪圖技術(shù) //判斷是否BUTTONDOWN if(m_Drag) { dc.MoveTo(m_pOrigin);dc.LineTo(m_pPrev);dc.MoveTo(m_pOrigin);dc.LineTo(point); } m_pPrev=point; 最后,在OnLBUTTONDOWN()添加代碼: m_Drag=0; 程序運(yùn)行效果圖 實(shí)驗(yàn)4 實(shí)現(xiàn)圓的生成算法 一、實(shí)驗(yàn)?zāi)康?/p> 1.熟悉CDC圖形程序庫(kù); 2.掌握中點(diǎn)畫圓生成算法; 3.掌握Bresenham畫圓算法。 二、實(shí)驗(yàn)內(nèi)容 利用VisualC++6.0設(shè)計(jì)一個(gè)簡(jiǎn)易畫圓繪圖板,驗(yàn)證圓生成算法。 三、實(shí)驗(yàn)指導(dǎo) 1.生成繪圖應(yīng)用程序的框架,如下圖所示。具體實(shí)現(xiàn)見(jiàn)第二次實(shí)驗(yàn),過(guò)程不再詳細(xì)說(shuō)明。 2.在應(yīng)用程序中增加菜單 完成相關(guān)菜單的設(shè)計(jì),具體的效果如下圖所示,并設(shè)置好相關(guān)菜單消息的映射,具體的實(shí)現(xiàn)在前面的實(shí)驗(yàn)中介紹過(guò),再此不在詳細(xì)說(shuō)明。 3.在繪圖函數(shù)中添加代碼 通過(guò)以上步驟,得到了與菜單對(duì)應(yīng)的消息映射,就可以在函數(shù)中添加代碼繪制圖形了。(1)利用中點(diǎn)畫圓算法實(shí)現(xiàn)圓的生成(算法原理見(jiàn)教材)。void CDraw_CirView::OnMid(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到繪圖類指針 RedrawWindow();//重繪窗口 int x,y,x0=200,y0=200,r=100;//圓的圓心為(x0,y0),半徑為r float d;x=0;y=r;d=1.25-r; pDC->SetPixel(x+x0,y+y0,RGB(255,0,0));pDC->SetPixel(y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));while(x<=y){ if(d<0) { d=d+2*x+3; x++; } else { d=d+2*(x-y)+5; x++; y--;} pDC->SetPixel(x+x0,y+y0,RGB(255,0,0)); pDC->SetPixel(y+x0,x+y0,RGB(255,0,0)); pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0)); pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0)); pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0)); pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0)); pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0)); pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));} } 由以上代碼繪出的圖形如下: (2)利用Bresenham算法生成圓(算法原理見(jiàn)教材)。void CDraw_CirView::OnBre(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到繪圖類指針 //RedrawWindow();//重繪窗口 int x,y,x0=200,y0=200,r=50;//圓的圓心為(x0,y0),半徑為r int delta,delta1,delta2,direction;x=0;y=r;delta=2*(1-r);while(y>=0){ pDC->SetPixel(x+x0,y+y0,RGB(0,0,255)); pDC->SetPixel(x+x0,-y+y0,RGB(0,0,255)); pDC->SetPixel(-x+x0,y+y0,RGB(0,0,255)); pDC->SetPixel(-x+x0,-y+y0,RGB(0,0,255)); if(delta<0) { delta1=2*(delta+y)-1; if(delta<=0)direction=1; else direction=2; } else if(delta>0) { delta2=2*(delta-x)-1; if(delta2<=0)direction=2; else direction=3; } else direction=2; switch(direction) { case 1:x++; delta+=2*x+1; break; case 2:x++;y--; delta+=2*(x-y+1); break; case 3:y--; delta+=(-2*y+1); break; } } } 由以上代碼繪出的圖形如下: (3)以上是本次實(shí)驗(yàn)的基本部分,利用中點(diǎn)畫圓和Bresenham畫圓算法實(shí)現(xiàn)的基本圖形的繪制。能不能利用該算法,完成一些復(fù)雜圖形的生成,比如利用基本的畫圓算法繪制一個(gè)奧運(yùn)五環(huán)。甚至根據(jù)畫圓算法,實(shí)現(xiàn)二次曲線的生成,如橢圓的生成等等。請(qǐng)同學(xué)們認(rèn)真考慮,完成這部分的內(nèi)容,上機(jī)調(diào)試。 四、思考 1.如何實(shí)現(xiàn)圓心為任意位置的圓的繪制; 2.兩種畫圓算法的比較。 《3D游戲圖形學(xué)》 實(shí)驗(yàn)指導(dǎo)書(shū) 浙江理工大學(xué) 二0一五年十月 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 課程實(shí)驗(yàn)指導(dǎo) 一、實(shí)驗(yàn)總體方案 1.教學(xué)目標(biāo)與基本要求 1)掌握本書(shū)所介紹的圖形算法的原理。 2)掌握通過(guò)具體的平臺(tái)實(shí)現(xiàn)圖形算法的方法,培養(yǎng)學(xué)生使用現(xiàn)代圖形系統(tǒng)API的能力。 3)通過(guò)實(shí)驗(yàn)培養(yǎng)具有開(kāi)發(fā)一個(gè)基本圖形軟件包的能力。2.實(shí)驗(yàn)平臺(tái) 實(shí)驗(yàn)主要結(jié)合OpenGL設(shè)計(jì)程序,實(shí)現(xiàn)各種課堂教學(xué)中講過(guò)的圖形算法。程序設(shè)計(jì)語(yǔ)言主要以C/C++為主,開(kāi)發(fā)平臺(tái)是Visual C++。 3.實(shí)驗(yàn)步驟 1)預(yù)習(xí)教材與實(shí)驗(yàn)指導(dǎo)的實(shí)驗(yàn)具體方案部分相關(guān)的算法理論及原理。2)仿照教材與實(shí)驗(yàn)指導(dǎo)提供的算法,利用VC++ OpenGL進(jìn)行實(shí)驗(yàn)。 3)調(diào)試、編譯、運(yùn)行程序,運(yùn)行通過(guò)后,可考慮對(duì)程序進(jìn)行修改或改進(jìn)。 二、實(shí)驗(yàn)預(yù)備知識(shí) OpenGL作為當(dāng)前主流的圖形API之一,在一些場(chǎng)合具有比DirectX更優(yōu)越的特性。 (1)與C語(yǔ)言緊密結(jié)合 OpenGL命令最初就是用C語(yǔ)言函數(shù)來(lái)進(jìn)行描述的,對(duì)于學(xué)習(xí)過(guò)C語(yǔ)言的人來(lái)講,OpenGL很容易理解和學(xué)習(xí)。 (2)強(qiáng)大的可移植性 微軟的Direct3D雖然也是十分優(yōu)秀的圖形API,但它只適用于Windows系統(tǒng),而OpenGL不僅適用于Windows,還可以用于Unix/Linux等其他系統(tǒng),它甚至在大型計(jì)算機(jī)、各種專業(yè)計(jì)算機(jī)上都有應(yīng)用。并且,OpenGL的基本命令都做到了硬件無(wú)關(guān),甚至是平臺(tái)無(wú)關(guān)。 (3)高性能的圖形渲染 OpenGL是一個(gè)工業(yè)標(biāo)準(zhǔn),它的技術(shù)緊跟時(shí)代,現(xiàn)今各個(gè)顯卡廠家無(wú)一不對(duì)OpenGL提供強(qiáng)力支持,激烈的競(jìng)爭(zhēng)中使得OpenGL性能一直領(lǐng)先。 總之,OpenGL是一個(gè)非常優(yōu)秀的圖形軟件接口。 下面對(duì)Windows下的OpenGL編程進(jìn)行簡(jiǎn)單介紹。以下幾點(diǎn)是學(xué)習(xí)OpenGL前的準(zhǔn)備工作。 1.選擇一個(gè)編譯環(huán)境 現(xiàn)在Windows系統(tǒng)的主流編譯環(huán)境有Visual C++,C++Builder,Dev-C++等,它們都支持OpenGL。這里選擇Visual C++作為學(xué)習(xí)OpenGL的實(shí)驗(yàn)環(huán)境。 2.安裝OpenGL工具包 1)將OpenGL工具包dll文件夾中的*.dll文件放到操作系統(tǒng)目錄下面的system32文件夾(其路徑一般為:C:WindowsSystem32)。 2)打開(kāi)VC,在VC中選擇Tools→Options→Directories,然后在Show directories for中選擇Include files,在下面添加OpenGL工具包中Include文件夾的路徑,如下圖所示: 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 3)類似地,在Show directories for中選擇library files,在下面添加OpenGL工具包中l(wèi)ib文件夾的路徑,然后按OK。如下圖所示: 3.建立一個(gè)OpenGL工程 打開(kāi)VC后,在VC中選擇File→New→Project,然后選擇Win32 Console Application, 選擇一個(gè)名字,然后按“OK”。在彈出的對(duì)話框中點(diǎn)An empty project,選擇Finish。然后向該工程添加一個(gè)源文件,選擇一個(gè)名字。 三、實(shí)驗(yàn)報(bào)告要求 (1)有實(shí)驗(yàn)報(bào)告封面 (2)給出簡(jiǎn)要的設(shè)計(jì)思路(原理)。(3)給出實(shí)現(xiàn)代碼。 (4)給出實(shí)驗(yàn)結(jié)果的屏幕截圖。(5)實(shí)驗(yàn)的心得體會(huì)或建議。 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 實(shí)驗(yàn)一VC++6.0+OpenGL繪圖環(huán)境及基本圖形學(xué)算法 實(shí)驗(yàn)項(xiàng)目性質(zhì):驗(yàn)證性實(shí)驗(yàn) 所屬課程名稱:3D游戲圖形學(xué) 實(shí)驗(yàn)計(jì)劃學(xué)時(shí):3學(xué)時(shí) 一. 實(shí)驗(yàn)?zāi)康?/p> 1、熟悉OpenGL的主要功能; 2、掌握OpenGL的繪圖流程和原理; 3、掌握OpenGL核心函數(shù)的使用; 4、理解基本圖形元素光柵的基本原理; 5、掌握直線和圓的多種生成算法。 二. 實(shí)驗(yàn)內(nèi)容 1、創(chuàng)建一個(gè)OpenGL工程,利用OpenGL庫(kù)函數(shù)進(jìn)行簡(jiǎn)單圖形設(shè)計(jì)與繪制; 2、編程實(shí)現(xiàn)DDA算法和Bresenham算法生成直線; 3、編程實(shí)現(xiàn)中點(diǎn)算法生成圓。 三. 實(shí)驗(yàn)原理 1、基本語(yǔ)法(C版本下的OpenGL語(yǔ)法) OpenGL基本函數(shù)均使用gl作為函數(shù)名的前綴,如glClearColor();實(shí)用函數(shù)則使用glu作為函數(shù)名的前綴,如gluSphere()。OpenGL基本常量的名字以GL_開(kāi)頭,如GL_LINE_LOOP;實(shí)用常量的名字以GLU_開(kāi)頭,如GLU_FILL。一些函數(shù)如glColor*()(定義顏色值),函數(shù)名后可以接不同的后綴以支持不同的數(shù)據(jù)類型和格式,如glColor3b()、glColor3d()、glColor3f()和glColor3bv()等,這幾個(gè)函數(shù)在功能上是相似的,只是適用于不同的數(shù)據(jù)類型和格式,其中3表示該函數(shù)帶有三個(gè)參數(shù),b、d、f分別表示參數(shù)的類型是字節(jié)型、雙精度浮點(diǎn)型和單精度浮點(diǎn)型,v則表示這些參數(shù)是以向量形式出現(xiàn)的。 OpenGL定義了一些特殊標(biāo)識(shí)符,如GLfloat、GLvoid,它們其實(shí)就是C中的float和void。 2、程序的基本結(jié)構(gòu) OpenGL程序的基本結(jié)構(gòu)可分為三個(gè)部分: 第一部分是初始化,主要是設(shè)置一些OpenGL的狀態(tài)開(kāi)關(guān),如顏色模式(RGBA或ALPHA)的選擇,是否作光照處理(若有的話,還需設(shè)置光源的特性),深度檢驗(yàn)、裁剪等。這些狀態(tài)一般都用函數(shù)glEnable(?)、glDisable(?)來(lái)設(shè)置,數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) “?”表示特定的狀態(tài)。 第二部分設(shè)置觀察坐標(biāo)系下的取景模式和取景框位置大小,主要利用了三個(gè)函數(shù): 函數(shù)void glViewport(left, top, right, bottom)設(shè)置在屏幕上的窗口大小,四個(gè)參數(shù)描述屏幕窗口四個(gè)角上的坐標(biāo)(以像素表示); 函數(shù)void glOrtho(left, right, bottom, top, near, far)設(shè)置投影方式為正交投影(平行投影),其取景體積是一個(gè)各面均為矩形的六面體; 函數(shù)void gluPerspective(fovy, aspect, zNear, zFar)設(shè)置投影方式為透視投影,其取景體積是一個(gè)截頭錐體。 第三部分是OpenGL的主要部分,是使用OpenGL的庫(kù)函數(shù)構(gòu)造幾何物體對(duì)象的數(shù)學(xué)描述,包括點(diǎn)線面的位置和拓?fù)潢P(guān)系、幾何變換、光照處理等。 3、OpenGL狀態(tài)機(jī)制 OpenGL的工作方式是一種狀態(tài)機(jī)制,它可以進(jìn)行各種狀態(tài)或模式設(shè)置,這些狀態(tài)或模式在重新改變它們之前一直有效。例如,當(dāng)前顏色就是一個(gè)狀態(tài)變量,在這個(gè)狀態(tài)改變之前,繪制的每個(gè)像素都將使用該顏色,直到當(dāng)前顏色被設(shè)置為其他顏色為止。OpenGL中大量地使用了這種狀態(tài)機(jī)制,如顏色模式、投影模式、單雙顯示緩存區(qū)的設(shè)置、背景色的設(shè)置、光源的位置和特性等。許多狀態(tài)變量可以通過(guò)glEnabel()、glDisable()這兩個(gè)函數(shù)來(lái)設(shè)置成有效或無(wú)效狀態(tài),如是否設(shè)置光照、是否進(jìn)行深度測(cè)試等;在被設(shè)置成有效狀態(tài)之后,絕大部分狀態(tài)變量都有一個(gè)缺省值。 四. 實(shí)驗(yàn)代碼 1、如預(yù)備知識(shí)所述,安裝OpenGL工具包,創(chuàng)建一個(gè)OpenGL工程,在源文件上輸入如下代碼: #include //將背景置成黑色 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) { glClear(GL_COLOR_BUFFER_BIT);//清除緩存 glBegin(GL_LINES); //開(kāi)始畫一根白線 glColor3f(1.0f, 1.0f, 1.0f);//設(shè)置顏色為白色 //設(shè)置第一根線的兩個(gè)端點(diǎn),請(qǐng)注意:OpenGL坐標(biāo)系的原點(diǎn)是在屏幕左下角 glVertex2f(10.0f, 50.0f);glVertex2f(110.0f, 50.0f);glColor3f(1.0f, 0.0f, 0.0f);//設(shè)置顏色為紅色 //設(shè)置第二根線的兩個(gè)端點(diǎn) glVertex2f(110.0f, 50.0f);glVertex2f(110.0f, 150.0f);glEnd();//畫線結(jié)束 glFlush();//繪圖結(jié)束 } // //主過(guò)程: // 初始化Windows的窗口界面 // 并初始化OpenGL場(chǎng)景,繪圖 int main(int argc, char** argv){ glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);//初始化窗口的顯示模式 glutInitWindowSize(400,300);//設(shè)置窗口的尺寸 glutInitWindowPosition(100,120);//設(shè)置窗口的位置 glutCreatWindow(“”); //創(chuàng)建一個(gè)名為“”的窗口 glutDisplayFunc(Display);//設(shè)置當(dāng)前窗口的顯示回調(diào)函數(shù) myinit(); //完成窗口初始化 glutMainLoop();//啟動(dòng)主GLUT事件處理循環(huán) 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) return(0);} glaux.lib glu32.lib glut32.lib opengl32.lib 注:glShadeModel選擇平坦或光滑漸變模式。GL_SMOOTH為缺省值,為光滑漸變模式,GL_FLAT為平坦?jié)u變模式。 該程序是在一個(gè)黑色的窗口中畫兩條線,分別用白色和紅色繪制。首先,需要包含頭文件#include 函數(shù)glColor3f()以RGB方式設(shè)置顏色,格式為:glColor3f(red,green,blue),每種顏色值在(0.0, 1.0)之間。函數(shù)glVertex2f(x, y)設(shè)置二維頂點(diǎn)。函數(shù)glBegin(UINT State)、glEnd()是最基本的作圖函數(shù),下面對(duì)它作一介紹。 如上所述,OpenGL是一個(gè)狀態(tài)機(jī),glBegin(UINT State)可以設(shè)定如下?tīng)顟B(tài): GL_POINTS GL_LINES 畫點(diǎn) 畫線,每?jī)蓚€(gè)頂點(diǎn)(Vertex)為一組 畫線,把若干個(gè)頂點(diǎn)順次連成封閉折線 畫三角形,每三個(gè)頂點(diǎn)為一組 畫多邊形 GL_LINE_STRIP 畫線,把若干個(gè)頂點(diǎn)順次連成折線 GL_LINE_LOOP GL_TRIANGLES GL_QUADS GL_POLYGON 畫四邊形,每四個(gè)頂點(diǎn)為一組 還有GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS_STRIP 等等。大家把每一種狀態(tài)都試一試。另外,程序可以有多組glBegin()、glEnd()并列的形式,如: ......數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) glBegin(GL_LINES); glBegin(GL_QUADS);......glEnd();......除了上述的基本圖元外,函數(shù)glRectf(x1, y1, x2, y2)可以畫一個(gè)矩形,但這個(gè)函數(shù)不能放在glBegin()和glEnd()之間,下面的兩句程序是畫一個(gè)藍(lán)色的矩形。 glColor3f(0.0f, 0.0f, 1.0f);glRectf(10.0f, 10.0f, 50.0f,50.0f);......glEnd();要求:利用OpenGL庫(kù)函數(shù)繪制基本圖形,輸出繪制結(jié)果。 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) void display(void){ } glColor3f(0.0f, 0.0f, 1.0f);glRectf(10.0f, 10.0f, 50.0f, 50.0f);//畫線結(jié)束 glFlush();//繪圖結(jié)束 glClear(GL_COLOR_BUFFER_BIT);//清除緩存 glBegin(GL_LINES); //開(kāi)始畫一根白線 glColor3f(1.0f, 1.0f, 1.0f);//設(shè)置顏色為白色 //設(shè)置第一根線的兩個(gè)端點(diǎn),請(qǐng)注意:OpenGL坐標(biāo)系的原點(diǎn)是在屏幕左下角 glVertex2f(10.0f, 50.0f);glVertex2f(110.0f, 50.0f);glColor3f(1.0f, 0.0f, 0.0f);//設(shè)置顏色為紅色 //設(shè)置第二根線的兩個(gè)端點(diǎn) glVertex2f(110.0f, 50.0f);glVertex2f(110.0f, 150.0f);glEnd(); 2、創(chuàng)建一個(gè)新的OpenGL工程,在源文件上輸入如下代碼: //DDA算法 # include 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) void LineDDA(int x0, int y0, int x1, int y1){ } void myDisplay(void){ glPointSize(5);glBegin(GL_POINTS);glColor3f(0.0f,1.0f,0.0f);glVertex2f(0.0f,0.0f);int x, dy, dx, y;float m;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;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0f,0.0f,0.0f);glRectf(25.0,25.0,75.0,75.0); 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) } 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();void Init(){ } void Reshape(int w, int h){ } int main(int argc, char * argv[])glClearColor(0.0,0.0,0.0,0.0);glShadeModel(GL_FLAT);glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h); 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) { } 介紹一下glutReshapeFunc()函數(shù): 首次打開(kāi)窗口、移動(dòng)窗口和改變窗口大小時(shí),窗口系統(tǒng)都將發(fā)送一個(gè)事件,以通知程序員。如果使用的是GLUT,通知將自動(dòng)完成,并調(diào)用向glutReshapeFunc()注冊(cè)的函數(shù)。該函數(shù)必須完成下列工作: a. 重新建立用作新渲染畫布的矩形區(qū)域; b. 定義繪制物體時(shí)使用的坐標(biāo)系。如: void Reshape(int w, int h){ glViewport(0, 0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0,(GLdouble)w, 0.0,(GLdouble)h); } 在GLUT內(nèi)部,將給該函數(shù)傳遞兩個(gè)參數(shù):窗口被移動(dòng)或修改大小后的寬度和高度,單位為像素。glViewport()調(diào)整像素矩形,用于繪制整個(gè)窗口。接下來(lái)三個(gè)函數(shù)調(diào)整繪圖坐標(biāo)系,使左下角位置為(0,0),右上角為(w,h)。glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);glutInitWindowPosition(100,100);glutInitWindowSize(400,400);glutCreateWindow(“Hello World!”);Init();glutDisplayFunc(myDisplay);glutReshapeFunc(Reshape);glutMainLoop();return 0;要求: 1)根據(jù)所給的直線光柵化的示范源程序,在計(jì)算機(jī)上編譯運(yùn)行,輸出正確結(jié)果(示范代碼有錯(cuò)誤,指出并改正); 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 示范代碼展示: void LineDDA(intx0, inty0, intx1, inty1){ } float x, dy, dx, y;float m;dx = x1y0;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; 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 2)根據(jù)示范程序采用的算法,以此為基礎(chǔ)將其改造為Bresenham算法,寫入實(shí)驗(yàn)報(bào)告; void Bresenhamline(intx0, inty0, intx1, inty1, intcolor){ int x, y, dx, dy;float k, e;dx = x1y0, k = dy / dx;e =-0.5, x = x0, y = y0;for(int i= 0;i <= dx;i++){ glPointSize(2.0f);glBegin(GL_POINTS);glColor3f(1.0f, 1.0f, 1.0f);glVertex2f(x, y);glEnd(); 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) } } x = x + 1,e = e + k;if(e >= 0){ } y++, e = e4 * radius;float deltaE = 12;float deltaSE = 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; 數(shù)字圖像處理實(shí)驗(yàn)指導(dǎo)書(shū) 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();} } 學(xué)號(hào):姓名:班級(jí): 計(jì)算機(jī)圖形學(xué) 實(shí)驗(yàn)報(bào)告 2016年6月日 實(shí)驗(yàn)名稱:三維交互式圖形程序設(shè)計(jì) 一、實(shí)驗(yàn)?zāi)康模?/p> 1)掌握真實(shí)感圖形生成的基本原理,如消隱、光照、材質(zhì)等知識(shí); 2)學(xué)習(xí)使用OpenGL、GLUT等生成基本圖形,如球體、正方體、茶壺等; 3)學(xué)習(xí)使用OpenGL生成各種光源:點(diǎn)光源、平行光、聚光燈等; 4)學(xué)習(xí)使用OpenGL設(shè)置繪制對(duì)象的顏色、材質(zhì); 5)進(jìn)一步熟悉OpenGL圖形變換技術(shù):幾何變換、視圖變換、觀察變換等: (1)對(duì)模型實(shí)現(xiàn)各種幾何變換(測(cè)試代碼保留在程序中),包括對(duì) glLoadMatrix、glMultMatrix、glTranslate、glRotate、glScale 等的使用; (2)視口變換,測(cè)試不同大小的視口 glViewport ; (3)投影變換,要對(duì)對(duì)平行投影與透視投影分別測(cè)試,使用不同的觀察體參數(shù),觀察效果 二、實(shí)驗(yàn)任務(wù): 1)使用MFC AppWizard 建立一個(gè)SDI 程序,根據(jù)參考資料2 和3 中的步驟設(shè)置OpenGL 圖形繪制環(huán)境。增加繪制如下表圖形(選擇其中任意一個(gè),注意模型坐標(biāo)系的選擇和頂點(diǎn)坐標(biāo)的計(jì)算)、球體或茶壺等(使用glut 函數(shù))。環(huán)境中創(chuàng)建點(diǎn)光源、平行光、聚光燈(可利用對(duì)話框輸入?yún)?shù)創(chuàng)建)、設(shè)置所繪制對(duì)象的材質(zhì),呈現(xiàn)出塑料、金屬等材質(zhì)特性。對(duì)光源的位置、方向、類型進(jìn)行控制,改變材質(zhì)參數(shù),觀察效果(測(cè)試代碼保留在程序中); 三.實(shí)驗(yàn)過(guò)程: 1.觀察參數(shù)的設(shè)置 glViewport(0.0, 0.0, width, height)//視口大小設(shè)置 gluLookAt(0,0,10,0,0,0,0,1,0);//觀察點(diǎn)設(shè)置,參數(shù)分別為觀察點(diǎn)位置,向哪點(diǎn)(何處)觀察,上方向的定義 2.投影變換 glOrtho(-15.0*aspect, 15.0*aspect,-15.0,15.0,1,100);//平行投影,參數(shù)是投影面大小和投影的物體距離范圍 gluPerspective(45,aspect, 1, 100.0);//透視投影,參數(shù)為視角,長(zhǎng)寬比,投影距離范圍 3.幾何變換 glLoadMatrixf(a);//設(shè)置當(dāng)前矩陣為a glTranslatef(2,0,0);//當(dāng)前矩陣*偏移矩陣 glRotatef(45, 0.0, 0.0, 0.0);//旋轉(zhuǎn) glScalef(m_scalX,m_scalY,m_scalZ);//當(dāng)前矩陣*比例矩陣 4.光源參數(shù)的設(shè)置 glLightfv(GL_LIGHT0, Type, vlight);//light為float數(shù)組 glLightf(GL_LIGHT0, Type, light);//light為float Type=GL_LIGHT0, GL_AMBIENT //環(huán)境光 Type=GL_LIGHT0, GL_DIFFUSE //漫反射 Type=GL_LIGHT0, GL_SPECULAR //鏡面光 Type=GL_POSITION //光源位置 Type=GL_CONSTANT_ATTENUATION //常數(shù)衰減因 Type=GL_LINEAR_ATTENUATION //線性衰減因子 Type=GL_QUADRATIC_ATTENUATION //二次衰減因子 Type=GL_SPOT_DIRECTION //聚光方向矢量 Type=GL_SPOT_EXPONENT //聚光指數(shù) Type=GL_SPOT_CUTOFF //聚光截止角 光源類型控制 平行光源::設(shè)置AMBIENT,DIFFUSE,SPECULAR,GL_POSITION4個(gè)參數(shù)。其中GL_POSITION第4個(gè)參數(shù)為0,表示距離無(wú)限遠(yuǎn) 點(diǎn)光源:平行光源基礎(chǔ)上添加常數(shù)衰減,因線性衰減因子,二次衰減因,其中GL_POSITION第4個(gè)參數(shù)為1 表示光源位置為確切位置,聚光燈光源 :在點(diǎn)光源基礎(chǔ)上添加聚光方向矢量,聚光截止角,聚光指數(shù) 本實(shí)驗(yàn)使用了3個(gè)光源,分別作為平行光源,點(diǎn)光源和聚光燈光源,通過(guò)不同菜單選擇在輸入?yún)?shù)的同時(shí)啟用不同的光源,以達(dá)到光源控制的效果 四.實(shí)驗(yàn)結(jié)果 原圖: 材質(zhì)選擇: 光源基本參數(shù)設(shè)置 設(shè)置聚光燈光源(位置,方向,聚光指數(shù),聚光截止角,衰減因子) 聚光衰減屬性(聚光燈) 五.實(shí)驗(yàn)體會(huì) 通過(guò)此次實(shí)驗(yàn),基本掌握了真實(shí)圖形生成的基本原理,對(duì)于3D圖新的材質(zhì)變換,光源變換等有了更深層次的理解。初步學(xué)習(xí)并掌握了幾何變換、視圖變換、觀察變換等。對(duì)于對(duì)話框、組建的設(shè)置更是理解的透徹。深入掌握了課堂上的些許知識(shí)。但對(duì)于之后的圖形學(xué)設(shè)計(jì),還是有很多的不足之處。所以,需要繼續(xù)努力,掌握更多的圖形設(shè)計(jì)學(xué)習(xí)。 吉林大學(xué) 計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院 《計(jì)算機(jī)圖形學(xué)》實(shí)驗(yàn)報(bào)告 班級(jí): 211923班 學(xué)號(hào): 21190928 姓名: 林星宇 2021-2022學(xué)年第1學(xué)期 實(shí)驗(yàn)項(xiàng)目1 邊標(biāo)志算法的實(shí)現(xiàn) 實(shí)驗(yàn)性質(zhì) □演示性實(shí)驗(yàn) ?驗(yàn)證性實(shí)驗(yàn) □操作性實(shí)驗(yàn) ?綜合性實(shí)驗(yàn) 實(shí)驗(yàn)地點(diǎn) 計(jì)算機(jī)樓B212 機(jī)器編號(hào) 一、實(shí)現(xiàn)的功能 編寫應(yīng)用程序,采用鼠標(biāo)輸入頂點(diǎn)的方法確定待填充多邊形(多邊形最后一點(diǎn)雙擊);實(shí)現(xiàn)邊標(biāo)志算法完成對(duì)該多邊形的填充,要求 完成使用自己學(xué)號(hào)的后四位數(shù)字對(duì)多邊形內(nèi)部進(jìn)行填充。 二、采用的圖形學(xué)算法及實(shí)現(xiàn) (算法的實(shí)現(xiàn)函數(shù)是什么(函數(shù)名,參數(shù),返回值,函數(shù)功能等)以及采用了哪些數(shù)據(jù)結(jié)構(gòu)(數(shù)組,鏈表等)) 要求使用邊標(biāo)志算法的原理和實(shí) 現(xiàn)方法,所以使用了EdgeMarkFill函數(shù),即邊標(biāo)志算法: void CMFCDrawTestView::EdgeMarkFill(CDC* pDC, CArray pDC為設(shè)備環(huán)境變量指針,plist為多邊形點(diǎn)表,color為傳入的RGB()值。 int zima[16][32]為學(xué)號(hào)后4位二維數(shù)組。 X1,x2,y1,y2分別為多邊形上的最小最小大,y值 三、采用的交互方式及實(shí)現(xiàn) (采用了哪些交互方式來(lái)完成繪制,這些交互方式應(yīng)用到了哪些系統(tǒng)消息,是如何實(shí)現(xiàn)的) 邊填充的實(shí)現(xiàn):編寫應(yīng)用程序,采用鼠標(biāo)輸入頂點(diǎn)的方法確定待填充多邊形(多邊形最后一點(diǎn)雙擊);實(shí)現(xiàn)邊標(biāo)志算法完成對(duì)該多邊形的填充,要求 完成使用自己學(xué)號(hào)的后四位數(shù)字對(duì)多邊形內(nèi)部進(jìn)行填充。 易知,在畫完多邊形后,即雙擊左鍵(OnLButtonUp)后,使用EdgeMarkFill函數(shù)。 Type=2時(shí),在OnLButtonUp中,調(diào)用EdgeMarkFill(pDC,&(obj->points), RGB(r, 0, 0)); 四、實(shí)驗(yàn)結(jié)果 (程序的運(yùn)行結(jié)果) 應(yīng)用程序運(yùn)行后,標(biāo)志算法完成對(duì)該多邊形的填充的圖形結(jié)果如下: 五、遇到的問(wèn)題及解決辦法 問(wèn)題1:(在實(shí)現(xiàn)過(guò)程中遇到了什么樣的問(wèn)題,及采用了何種解決辦法) 在獲取下x1,x2,y1,y2時(shí),因?yàn)镈os界面x、y大小顛倒的原因,獲取時(shí)出現(xiàn)了問(wèn)題。 首先,通過(guò)for(int i = 1;i < plist->GetSize();i++){ CPoint p = plist->GetAt(i); if(x1 > p.x)x1 = p.x; if(x2 < p.x)x2 = p.x; if(y1 > p.y)y1 = p.y; if(y2 < p.y)y2 = p.y; } 獲取x1,x2,y1,y2.在遍歷多邊形過(guò)程中: int count = plist->GetSize(); for(int i = 0;i < count;i++){ CPoint p1 = plist->GetAt(i); CPoint p2 = plist->GetAt((i + 1)% count); if(p1.y == p2.y) continue; if(p1.y > p2.y) { CPoint p;p = p1;p1 = p2;p2 = p; } xs = p1.x; dxs =(p2.x-p1.x)/(double)(p2.y-p1.y); //dys = abs(p2.y-p1.y)/(p2.y-p1.y); for(ys = p1.y;ys!= p2.y;ys += 1) { Ixs = int(xs + 0.5); MARK[ys][Ixs] =!MARK[ys][Ixs]; xs = xs + dxs; } 黃線處即為處理x1,x2,y1,y2的大小。 問(wèn)題2:通過(guò)數(shù)組zima[][]來(lái)確定多邊形區(qū)域填充學(xué)號(hào)后4位時(shí),zima[y ][x ]未%其字長(zhǎng),即zima[y % 16][x % 32]。后改為: for(y = y1;y <= y2;y++) { bool inside = false; for(x = x1;x <= x2;x++) { if(MARK[y][x]) inside =!inside; if(inside) { if(zima[y % 16][x % 32]) pDC->SetPixel(x, y, RGB(255, 0, 0)); } } } 實(shí)驗(yàn)項(xiàng)目2 立方體的比例、平移、旋轉(zhuǎn)變換及投影顯示 實(shí)驗(yàn)性質(zhì) □演示性實(shí)驗(yàn) ?驗(yàn)證性實(shí)驗(yàn) □操作性實(shí)驗(yàn) ?綜合性實(shí)驗(yàn) 實(shí)驗(yàn)地點(diǎn) 計(jì)算機(jī)樓B212 機(jī)器編號(hào) 一、實(shí)現(xiàn)的功能 建立立方體的數(shù)據(jù)模型;編寫應(yīng)用程序,利用菜單和鍵盤結(jié)合的方式完成對(duì)立方體的移動(dòng)、比例和旋轉(zhuǎn)變換,并顯示透視或斜二測(cè)投影結(jié)果。要求應(yīng)用程序具有如下功能: 1、通過(guò)菜單選擇的方式,選擇對(duì)三維空間中的立方體作斜二測(cè)投 影或透視投影; 2、通過(guò)鍵盤按鍵或鼠標(biāo)移動(dòng)的方式,完成對(duì)三維空間中的立方體 進(jìn)行平移變換(上下左右前后),比例變換(放大或縮?。┮约?旋轉(zhuǎn)變換(繞 x,y,z 軸),并同時(shí)顯示變換后的投影結(jié)果 3、創(chuàng)建對(duì)話框,通過(guò)對(duì)話框設(shè)置透視投影時(shí)候的投影中心,以及旋轉(zhuǎn)變換時(shí)候的旋轉(zhuǎn)軸(可以設(shè)置成分別繞 x 軸,y 軸,z 軸進(jìn) 行旋轉(zhuǎn)) 二、采用的圖形學(xué)算法及實(shí)現(xiàn) (算法的實(shí)現(xiàn)函數(shù)是什么(函數(shù)名,參數(shù),返回值,函數(shù)功能等)以及采用了哪些數(shù)據(jù)結(jié)構(gòu)(數(shù)組,鏈表等)) 題目要求實(shí)現(xiàn)立方體的移動(dòng)、比例和旋轉(zhuǎn)變換,并顯示透視或斜二測(cè)投影結(jié)果。 對(duì)要求1:在菜單選TY項(xiàng)中選擇斜二測(cè)投影(斜二=1)或透視投影(透視=1)。然后在OnDraw中調(diào)用Draw_Cubic(CDC* pDC)畫出立方體。 對(duì)要求2:在OnKeyDown中調(diào)用函數(shù),即在鍵盤上按“S”使立方體變小,“B”使立方體變大,“←”“→”“↑”“↓”使立方體左右上下移動(dòng)。 對(duì)要求3:在菜單XYZ中選擇旋轉(zhuǎn)的x,y,z軸,即x=1或y=1或z=1,然后在OnKeyDown中調(diào)用函數(shù),即按鍵盤上的“T”或“P”. 三、采用的交互方式及實(shí)現(xiàn) (采用了哪些交互方式來(lái)完成繪制,這些交互方式應(yīng)用到了哪些系統(tǒng)消息,是如何實(shí)現(xiàn)的) 由題目要求1,易知需要一個(gè)函數(shù)Draw_Cubic(CDC* pDC)畫出立方體的斜二測(cè)投影或透視投影并且建立一個(gè)菜單欄TY(投影)。即在菜單選TY項(xiàng)中選擇斜二測(cè)投影(斜二=1)或透視投影(透視=1)。然后在OnDraw中調(diào)用Draw_Cubic(CDC* pDC)畫出立方體。 由題目要求2:易知直接在OnKeyDown函數(shù)上添加使立方體變大變小,前后左右平移的功能。即即在鍵盤上按“S”使立方體變小,“B”使立方體變大,“←”“→”“↑”“↓”使立方體左右上下移動(dòng)。 由題目要求3:建立一個(gè)菜單XYZ決定旋轉(zhuǎn)的軸。 四、實(shí)驗(yàn)結(jié)果 (程序的運(yùn)行結(jié)果) 斜二測(cè)投影: 斜二測(cè)投影平移到左上角: 斜二測(cè)投影平移到右下角: 斜二測(cè)投影變大: 斜二測(cè)投影變?。?/p> 斜二測(cè)投影變?yōu)橥敢曂队埃?/p> 斜二測(cè)投影繞z軸旋轉(zhuǎn): 五、遇到的問(wèn)題及解決辦法 (在實(shí)現(xiàn)過(guò)程中遇到了什么樣的問(wèn)題,及采用了何種解決辦法) 問(wèn)題1:一開(kāi)始建立立方體時(shí),沒(méi)有建立邊表,導(dǎo)致投影困難。 后來(lái)建立了點(diǎn)表和對(duì)應(yīng)的邊表。 問(wèn)題2:一開(kāi)始Draw_Cubic中x1, y1,z1, x2, y2,z2定義為了int型。 實(shí)驗(yàn)項(xiàng)目3 用矩形窗口對(duì)多邊形進(jìn)行裁剪 實(shí)驗(yàn)性質(zhì) □演示性實(shí)驗(yàn) ?驗(yàn)證性實(shí)驗(yàn) □操作性實(shí)驗(yàn) ?綜合性實(shí)驗(yàn) 實(shí)驗(yàn)地點(diǎn) 計(jì)算機(jī)樓B212 機(jī)器編號(hào) 一、實(shí)現(xiàn)的功能 編寫應(yīng)用程序?qū)崿F(xiàn)多邊形裁剪。要求首先采用鼠標(biāo)確定裁剪區(qū)域(矩形區(qū)域),然 后用鼠標(biāo)輸入待裁剪的多邊形(可分別使用鼠標(biāo)左鍵和右鍵來(lái)確定裁剪區(qū)域和待裁剪 的多邊形)。多邊形繪制完畢后進(jìn)行裁剪,以不同顏色顯示被裁剪對(duì)象位于窗口內(nèi)(此 部分應(yīng)保證多邊形的完整性)及外部的部分。 二、采用的圖形學(xué)算法及實(shí)現(xiàn) (算法的實(shí)現(xiàn)函數(shù)是什么(函數(shù)名,參數(shù),返回值,函數(shù)功能等)以及采用了哪些數(shù)據(jù)結(jié)構(gòu)(數(shù)組,鏈表等)) 因?yàn)橐帉憫?yīng)用程序?qū)崿F(xiàn)多邊形裁剪。要求首先采用鼠標(biāo)確定裁剪區(qū)域(矩形區(qū)域),然 后用鼠標(biāo)輸入待裁剪的多邊形(可分別使用鼠標(biāo)左鍵和右鍵來(lái)確定裁剪區(qū)域和待裁剪 的多邊形)。所以要使用多邊形裁剪算法,即Cut_Top(),Cut_Bottom(),Cut_Left(),Cut_Right()四個(gè)函數(shù)。 Cut()函數(shù)為用綠色顯示被裁剪對(duì)象位于窗口內(nèi)部分。 存在int type的變量; 當(dāng)type=1時(shí),在OnLButtonUp中畫出矩形框。 當(dāng)type=2時(shí),畫出多邊形,在左鍵雙擊后,在OnLButtonDblClk中調(diào)用如下函數(shù):Cut_Top();Cut_Right();Cut_Bottom();Cut_Left();Cut(); 裁剪多邊形在,并標(biāo)出在矩形內(nèi)部的部分。 三、采用的交互方式及實(shí)現(xiàn) (采用了哪些交互方式來(lái)完成繪制,這些交互方式應(yīng)用到了哪些系統(tǒng)消息,是如何實(shí)現(xiàn)的) 編寫應(yīng)用程序?qū)崿F(xiàn)多邊形裁剪。要求首先采用鼠標(biāo)確定裁剪區(qū)域(矩形區(qū)域),然 后用鼠標(biāo)輸入待裁剪的多邊形(可分別使用鼠標(biāo)左鍵和右鍵來(lái)確定裁剪區(qū)域和待裁剪 的多邊形)。多邊形繪制完畢后進(jìn)行裁剪,以不同顏色顯示被裁剪對(duì)象位于窗口內(nèi)(此 部分應(yīng)保證多邊形的完整性)及外部的部分。 根據(jù)以上繪制方法,可知需要處理WM_OnLButtonDblClk(左鍵雙擊)及WM_LButtonUp(左鍵抬起)消息,為了繪制橡皮線,還需處理調(diào)用WM_MouseMove(鼠標(biāo)移動(dòng))消息。 因?yàn)榭梢杂檬髽?biāo)畫出矩形和多邊形,所以這么規(guī)定,當(dāng)type=1時(shí)畫矩形,即: DDALine(pDC,lx,by,lx,ty,RGB(r, g, b)); DDALine(pDC, lx, by, rx, by, RGB(r, g, b)); DDALine(pDC, rx, by, rx, ty, RGB(r, g, b)); DDALine(pDC, lx, ty, rx, ty, RGB(r, g, b)); 當(dāng)type=2時(shí)畫多邊形,而后裁剪,即: for(int i = 0;i < pointList.GetSize();i++) { p1 = pointList.GetAt(i); p2 = pointList.GetAt((i+1)% count); DDALine(pDC, p1.x, p1.y, p2.x, p2.y, RGB(0,255,0)); } 四、實(shí)驗(yàn)結(jié)果 (程序的運(yùn)行結(jié)果) 裁剪結(jié)果如下圖所示,黑色為裁剪窗口,紅色為多邊形被裁剪的部分,綠色為多邊形裁剪后的部分: 五、遇到的問(wèn)題及解決辦法 (在實(shí)現(xiàn)過(guò)程中遇到了什么樣的問(wèn)題,及采用了何種解決辦法) 問(wèn)題1:我在裁剪使一開(kāi)始對(duì)多邊形做上下左右裁剪時(shí),這四個(gè)步驟是分別對(duì)原圖形裁剪,而不是對(duì)圖形接連進(jìn)行裁剪。后來(lái)在裁剪函數(shù)上先除去之前圖形,然后把已裁剪多邊形重新構(gòu)建。如下: pointList.RemoveAll(); for(int i = 0;i < m;i++) pointList.Add(CP[i]); 問(wèn)題2:在多邊形被矩形裁剪的部分顯現(xiàn)不同顏色花費(fèi)了挺多時(shí)間,后來(lái)我直接讓裁剪的部分顏色被覆蓋就可以了。如下: for(int i = 0;i < pointList.GetSize();i++) { p1 = pointList.GetAt(i); p2 = pointList.GetAt((i+1)% count); DDALine(pDC, p1.x, p1.y, p2.x, p2.y, RGB(0,255,0)); }第二篇:計(jì)算機(jī)圖形學(xué)實(shí)驗(yàn)
第三篇:3D游戲圖形學(xué)實(shí)驗(yàn)一
第四篇:計(jì)算機(jī)圖形學(xué) 實(shí)驗(yàn)六-西南交大
第五篇:《計(jì)算機(jī)圖形學(xué)》實(shí)驗(yàn)報(bào)告