版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、二維游戲程序部分1、 VC中的繪圖類(CBitmap,CBrush,CFont,CPen)的使用。(1)CPen類是CGdiObject類的一個派生類,它封裝了Windows圖形設(shè)備接口(GDI)中有關(guān)畫筆的操作。CPen pen; CPen(Int style,int width ,COLORREF color);style:畫筆的樣式width:畫筆的寬度color:畫筆的顏色(顏色用RGB值來描述)Pen.CreatePen(PS_SOLID,1,RGB(255,0,0);/定義一個CPen對象,用其成員函數(shù)CreatePen或 CreatePenIndirect對其進行初始化。CPen
2、 pen(PS_SOLID,1,RGB(255,0,RGB(255,0,0);/定義一個CPen對象,并一次性地初始化它的所有參數(shù)。(2)CBrush類是CGdiObject類的一個派生類,它封裝了Windows圖形設(shè)備界面(GDI)中有關(guān)畫刷的操作。CBrush類的用法與CPen類似。CBrushbrush(RGB(255,0,0);/定義CBrush類對象,并利用構(gòu)造函數(shù)對對象的參數(shù)進行初始化。(3)CFont類是CGdiObject類的一個派生類,它封裝了邏輯字體及方法。CFont類只有一個構(gòu)造函數(shù),在定義了一個CFont類對象之后,必須用成員函數(shù)CreateFont或CreateFon
3、tIndirect來初始化CFont對象的參數(shù)。(4)CBitmap類和Cpen、CBrush類一樣,是CGdiObject類的派生類,它封裝了使用Windows GDI進行圖形繪制中關(guān)于位圖的操作。在CBitmap類中重載了兩個LoadBitmap函數(shù),用于加載位圖資源:BOOL LoadBitmap( LPCTSTR lpszResourceName );BOOL LoadBitmap( UINT nIDResource ) 2 、VC中顯示位圖的過程,需要掌握的函數(shù)包括:GetClientRect( &rect);/取得客戶區(qū)域大小CreateCompatibleDC(&
4、dc);/創(chuàng)建適合指定pDC內(nèi)存設(shè)備環(huán)境 mdc->CreateCompatibleDC(&dc);LoadImage(); /將位圖裝入內(nèi)存mi->m_hObject(HBITMAP):LoadImage(NULL,str,IMAGE_BITMAP,440,74,LR_LOADFROMFILE);SelectObject(); /恢復(fù)設(shè)備環(huán)境mdc1->SelectObject(bgbmp);BitBlt();/顯示位圖dc.BitBlt(0,0,rect.right,rect.bottom,mdc,0,0,SRCCOPY); mdc2->BitBlt(0,0
5、,112,64,mdc1,x,160,SRCCOPY);/從x,160位置開始貼3 鏤空圖的原理及相關(guān)函數(shù)實現(xiàn)。(1) 獲取圖片,前景色置為黑色0,0,0,背景色置為白色255,255,255,利用BitBlt函數(shù)將蒙版與背景圖做AND運算,并貼圖到目的DC,將要鏤空的圖與背景圖做OR運算,貼圖到目的DC將蒙版與背景圖做AND運算。再將要鏤空的圖與背景圖做OR運算:(2)相關(guān)函數(shù): GetClientRect(&rect);/取得客戶取大小mdc->CreateCompatibleDC(pDC);/建立內(nèi)存DCbgbmp->m_hObject=(HBITMAP):LoadI
6、mage(NULL,"b1.bmp",IMAGE_BITMAP,rect.right,rect.bottom,LR_LOADFROMFILE);/加載背景位圖bitmap->m_hObject=(HBITMAP):LoadImage(NULL,"man.bmp",IMAGE_BITMAP,208,154,LR_LOADFROMFILE);/加載人物位圖(人物及蒙版同在一張圖上)mdc->SelectObject(m_bgBmp);/取得背景圖mdc->BitBlt(0,0,rect.right,rect.bottom,mdc,0,0,S
7、RCCOPY);/貼背景圖mdc->SelectObject(m_manBmp);mdc->BitBlt(250,150,104,154,mdc,104,0,SRCAND);/將蒙版與背景圖做AND運算mdc->BitBlt(250,150,104,154,mdc,0,0,SRCPAINT);/將要鏤空的圖與背景圖做OR運算4、 定時器的使用方法。(1)在WM_CREATE中啟動定時器( SetTimer)。(2)在WM_TIMER消息中設(shè)置定時器UINT_PTR SetTimer(HWND hWnd, / 窗口句柄UINT_PTR nIDEvent, / 定時器ID,多 個
8、定時器時,可以通過該ID判斷是哪個定時器UINT uElapse, / 時間間隔,單位為毫秒TIMERPROC lpTimerFunc / 回調(diào)函數(shù));例如: UINT SetTimer(1,100,NULL); 設(shè)置并啟動一個時間間隔為100ms的定時器,消息響應(yīng)函數(shù)是onTimer();(3)調(diào)用KillTimer來取消定時器。 BOOL KillTimer(HWND hWnd, / 窗口句柄UINT_PTR uIDEvent / ID);在MFC程序中我們可以直接調(diào)用KillTimer(int nIDEvent)來取消定時器。5. 粒子系統(tǒng)的實現(xiàn)。 粒子系統(tǒng)都由大量的粒子構(gòu)成,每個粒子都
9、有一組屬性,如位置、大小以及紋理,還比如顏色、透明度、運動速度、加速度、自旋周期,生命周期等等屬性。粒子屬性的初始值常常都是隨機值,而粒子的產(chǎn)生也常常是由位于空間中某個位置的粒子源產(chǎn)生的。我們會根據(jù)預(yù)定的要求,產(chǎn)生一定數(shù)目的新粒子。粒子的各項初始屬性都可以用rand函數(shù)來在一定的范圍內(nèi)賦上隨機的值。粒子有位置和移動速度,自旋速度等等屬性,這就需要在每一幀當(dāng)中根據(jù)原來的粒子的位置、移動速度和自旋速度重新進行計算和賦值更新。struct snowint x;int y;BOOL exist;int i,count;snow drop50;void canvasFrame:OnTimer(UINT
10、nIDEvent) if(count<50)dropcount.x = rand()%rect.right;dropcount.y = 0;dropcount.exist = true;count+;貼圖6、 鍵盤交互的實現(xiàn)。首先在相關(guān)類中建立起消息響應(yīng)函數(shù),選擇該消息與函數(shù)對應(yīng),在消息響應(yīng)函數(shù)中對于每個鍵寫相關(guān)代碼.void canvasFrame:OnKeyDown(UINT nChar按得哪個鍵 ,UINT nRepCnt, UINT nFlags) 用鍵盤在人機交互中完成對屏幕中物體位置移動的控制功能時常會用到上、下、左、右?guī)讉€方向鍵。下面的程序可以完成對某一可視控件Object
11、1的位置進行控制(分別按下上、下左、右鍵使其分別向上、下、左、右方向移動5個屏幕單位):CWnd:OnKeyDown(UINT nChar, UINT nRecpCnt, UNIT nFlages);Switch(nChar)case VK_LEFT;Object1.left=Object1.left-5; 按下左鍵控件左移5個單位break;case VK_RIGHT;Object1.left=Object1.left+5; /按下右鍵控件右移5個單位break;case VK_UP;Object1.top=Object1.top-5;/按下上鍵控件上移5個單位break;case VK_D
12、OWN;Object1.top=Object1.top+5; /按下下鍵控件下移5個單位break;defult: break;7、 鼠標(biāo)交互的實現(xiàn)。void canvasFrame:OnMouseMove(UINTnFlags,CPointpoint);當(dāng)鼠標(biāo)移動時調(diào)用此函數(shù) 。參數(shù):nFlags指示各種虛擬按鍵是否按下 ,此參數(shù)可以是任何下列值的組合:MK_CONTROL當(dāng)CTRL鍵按下時。MK_LBUTTON當(dāng)鼠標(biāo)左鍵按下時。MK_MBUTTON當(dāng)鼠標(biāo)中鍵按下時。MK_RBUTTON當(dāng)鼠標(biāo)右鍵按下時.MK_SHIFT當(dāng)SHIFT按下時。point:鼠標(biāo)的X,Y坐標(biāo):該坐標(biāo)為 鼠標(biāo)距離截獲
13、該消息的窗口左上角的位置 是一個相對位置而不是在屏幕像素上的絕對位置。較高要求:物體間碰撞檢測方法及相關(guān)實現(xiàn)。(1) 像素檢測hmask->GetObject(sizeof(BITMAP),&bm);unsigned char *px1 = new unsigned charbm.bmHeight*bm.bmWidthBytes;hmask->GetBitmapBits(bm.bmHeight*bm.bmWidthBytes,px1);int rgb_b,PixelBytes,tx,ty; PixelBytes = bm.bmBitsPixel / 8;for (ty=0;
14、ty<bm.bmHeight;ty+)for (tx=0;tx<bm.bmWidth;tx+)rgb_b = ty*bm.bmWidthBytes+tx*PixelBytes;if(pxrgb_b != 255 && pxrgb_b+1 != 255 && pxrgb_b+2 !=255)b = pxrgb_b & px1rgb_b; g = pxrgb_b+1 & px1rgb_b+1;r = pxrgb_b+2 & px1rgb_b+2;if(b = 0 && g=0 &&r=0) 撞上了!
15、 delete px1;(2) 坐標(biāo)檢測:if(point.x>=poscount.x)&&(point.y>=poscount.y-40)&&(point.x<=poscount.x+bm.bmWidth)&&(point.y<=poscount.y+(bm.bmHeight/8-40)撞上了!OpenGL部分1 利用Glut函數(shù)需要的設(shè)置有哪些?1)、將下載的壓縮包解開,將得到5個文件2)、在“我的電腦”中搜索“gl.h”,并找到其所在文件夾。把解壓得到的glut.h放到這個文件夾。3)、把解壓得到的glut.lib和
16、glut32.lib放到靜態(tài)函數(shù)庫所在文件夾(如果是Visual C+,則應(yīng)該是其安裝目錄下面的“VClib”文件夾)。4)、把解壓得到的glut.dll和glut32.dll放到操作系統(tǒng)目錄下面的system32文件夾內(nèi)。(典型的位置為:C:WindowsSystem32) 2 圖元的繪制方法(1)OpenGL 函數(shù)通常以gl開頭,中間是函數(shù)相關(guān)功能單詞,后面跟一個數(shù)字和12個字母。glVertex2d數(shù)字表示參數(shù)的個數(shù),字母表示參數(shù)的類型 (s表示16位整數(shù),i表示32位整數(shù),f表示32位浮點數(shù),d表示64位浮點數(shù)) glBegin(GL_POINTS); glVertex2f(0.0f,
17、 0.0f); glVertex2f(0.5f, 0.0f); glEnd();(2)字母表示參數(shù)的類型: s表示16位整數(shù)(OpenGL中將這個類型定義為GLshort); i表示32位整數(shù)(OpenGL中將這個類型定義為GLint和GLsizei); f表示32位浮點數(shù)(OpenGL中將這個類型定義為GLfloat和GLclampf);d表示64位浮點數(shù)(OpenGL中將這個類型定義為GLdouble和GLclampd)。v表示傳遞的幾個參數(shù)將使用指針的方式,見下面的例子。這些函數(shù)除了參數(shù)的類型和個數(shù)不同以外,功能是相同的。例如,以下五個代碼段的功能是等效的:glVertex2i(1, 3
18、);glVertex2f(1.0f, 3.0f);glVertex3f(1.0f, 3.0f, 0.0f);glVertex4f(1.0f, 3.0f, 0.0f, 1.0f);GLfloat VertexArr3 = 1.0f, 3.0f,0.0f;glVertex3fv(VertexArr3);(3)OpenGL要求:指定頂點的命令必須包含在glBegin函數(shù)之后,glEnd函數(shù)之前(否則指定的頂點將被忽略)。并由glBegin來指明如何使用這些點。例如:glBegin(GL_POINTS);glVertex2f(0.0f, 0.0f);glVertex2f(0.5f, 0.0f);glE
19、nd();則這兩個點將分別被畫出來。如果將GL_POINTS替換成GL_LINES,則兩個點將被認(rèn)為是直線的兩個端點,OpenGL將會畫出一條直線。(4) glBegin支持的方式除了GL_POINTS和GL_LINES,還有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN等,每種方式的大致效果見下圖:程序代碼:void myDisplay(void) glClear(GL_COLOR_BUFFER_BIT);
20、160; glBegin( /* 在這里填上你所希望的模式 */ ); /* 在這里使用glVertex*系列函數(shù) */ /* 指定你所希望的頂點位置 */ glEnd(); glFlush();3 圖元繪制中的深入設(shè)置方法1.關(guān)于點點的大小默認(rèn)為1個像素,但也可以改變之。改變的命令為glPointSize,其函數(shù)
21、原型如下:void glPointSize(GLfloat size);size必須大于0.0f,默認(rèn)值為1.0f,單位為“像素”。注意:對于具體的OpenGL實現(xiàn),點的大小都有個限度的,如果設(shè)置的size超過最大值,則設(shè)置可能會有問題。void myDisplay(void) glClear(GL_COLOR_BUFFER_BIT); glPointSize(5.0f); glBegin(GL_POINTS);
22、160; glVertex2f(0.0f, 0.0f); glVertex2f(0.5f, 0.5f); glEnd(); glFlush(); 2、關(guān)于直線(1)直線可以指定寬度:void glLineWidth(GLfloat width);其用法跟glPointSize類似。(2)畫虛線。首先,使用glEnable(GL_LINE_STIPPLE);來
23、啟動虛線模式(使用glDisable(GL_LINE_STIPPLE)可以關(guān)閉之)。然后,使用glLineStipple來設(shè)置虛線的樣式。void glLineStipple(GLint factor, GLushort pattern);pattern是由1和0組成的長度為16的序列,從最低位開始看,如果為1,則直線上接下來應(yīng)該畫的factor個點將被畫為實的;如果為0,則直線上接下來應(yīng)該畫的factor個點將被畫為虛的。void myDisplay(void) glClear(GL_COLOR_BUFFER_BIT);
24、 glEnable(GL_LINE_STIPPLE); glLineStipple(2, 0x0F0F); glLineWidth(10.0f); glBegin(GL_LINES); glVertex2f(0.0f, 0.0f); glVertex2f(0.5f, 0.5f);
25、0; glEnd(); glFlush(); 3、關(guān)于多邊形(1)多邊形的兩面以及繪制方式。雖然我們目前還沒有真正的使用三維坐標(biāo)來畫圖,但是建立一些三維的概念還是必要的。從三維的角度來看,一個多邊形具有兩個面。每一個面都可以設(shè)置不同的繪制方式:填充、只繪制邊緣輪廓線、只繪制頂點,其中“填充”是默認(rèn)的方式??梢詾閮蓚€面分別設(shè)置不同的方式。glPolygonMode(GL_FRONT, GL_FILL);
26、160; / 設(shè)置正面為填充方式glPolygonMode(GL_BACK, GL_LINE); / 設(shè)置反面為邊緣繪制方式glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); / 設(shè)置兩面均為頂點繪制方式(2)反轉(zhuǎn)一般約定為“頂點以逆時針順序出現(xiàn)在屏幕上的面”為“正面”,另一個面即成為“反面”。生活中常見的物體表面,通常都可以用這樣的“正面”和“反面”,“合理的”被表現(xiàn)出來(請找一個比較透明的礦泉水瓶子,在正對你的一
27、面沿逆時針畫一個圓,并標(biāo)明畫的方向,然后將背面轉(zhuǎn)為正面,畫一個類似的圓,體會一下“正面”和“反面”。你會發(fā)現(xiàn)正對你的方向,瓶的外側(cè)是正面,而背對你的方向,瓶的內(nèi)側(cè)才是正面。正對你的內(nèi)側(cè)和背對你的外側(cè)則是反面。這樣一來,同樣屬于“瓶的外側(cè)”這個表面,但某些地方算是正面,某些地方卻算是反面了)??梢酝ㄟ^glFrontFace函數(shù)來交換“正面”和“反面”的概念。glFrontFace(GL_CCW); / 設(shè)置CCW方向為“正面”,CCW即CounterClockWise,逆時針glFrontFace(GL_CW); / 設(shè)置CW方向為“正
28、面”,CW即ClockWise,順時針void myDisplay(void) glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT, GL_FILL); / 設(shè)置正面為填充模式 glPolygonMode(GL_BACK, GL_LINE); / 設(shè)置反面為線形模式 glFrontFace(GL_CCW);
29、; / 設(shè)置逆時針方向為正面 glBegin(GL_POLYGON); / 按逆時針繪制一個正方形,在左下方 glVertex2f(-0.5f,
30、 -0.5f); glVertex2f(0.0f, -0.5f); glVertex2f(0.0f, 0.0f); glVertex2f(-0.5f, 0.0f); glEnd(); glBegin(GL_POLYG
31、ON); / 按順時針繪制一個正方形,在右上方 glVertex2f(0.0f, 0.0f); glVertex2f(0.0f, 0.5f);
32、glVertex2f(0.5f, 0.5f); glVertex2f(0.5f, 0.0f); glEnd(); glFlush();(3)剔除多邊形表面在三維空間中,一個多邊形雖然有兩個面,但我們無法看見背面的那些多邊形,而一些多邊形雖然是正面的,但被其他多邊形所遮擋。如果將無法看見的多邊形和可見的多邊形同等對待,無疑會降低我們處理圖形的效率。在這種時候,可以將不必要的面剔除。首先,使用glEnable
33、(GL_CULL_FACE);來啟動剔除功能(使用glDisable(GL_CULL_FACE)可以關(guān)閉之)然后,使用glCullFace來進行剔除。glCullFace的參數(shù)可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK,分別表示剔除正面、剔除反面、剔除正反兩面的多邊形。注意:剔除功能只影響多邊形,而對點和直線無影響。例如,使用glCullFace(GL_FRONT_AND_BACK)后,所有的多邊形都將被剔除,所以看見的就只有點和直線。(4)鏤空多邊形直線可以被畫成虛線,而多邊形則可以進行鏤空。首先,使用glEnable(GL_POLYGON_STIPPLE)
34、;來啟動鏤空模式(使用glDisable(GL_POLYGON_STIPPLE)可以關(guān)閉之)。然后,使用glPolygonStipple來設(shè)置鏤空的樣式。void glPolygonStipple(const GLubyte *mask);其中的參數(shù)mask指向一個長度為128字節(jié)的空間,它表示了一個32*32的矩形應(yīng)該如何鏤空。其中:第一個字節(jié)表示了最左下方的從左到右(也可以是從右到左,這個可以修改)8個像素是否鏤空(1表示不鏤空,顯示該像素;0表示鏤空,顯示其后面的顏色),最后一個字節(jié)表示了最右上方的8個像素是否鏤空。 4 顏色設(shè)置及指定清除屏幕用顏色的方法OpenGL支持兩種顏色模式:一
35、種是RGBA,一種是顏色索引模式。無論哪種顏色模式,計算機都必須為每一個像素保存一些數(shù)據(jù)。不同的是,RGBA模式中,數(shù)據(jù)直接就代表了顏色;而顏色索引模式中,數(shù)據(jù)代表的是一個索引,要得到真正的顏色,還必須去查索引表。1. RGBA顏色RGBA模式中,每一個像素會保存以下數(shù)據(jù):R值(紅色分量)、G值(綠色分量)、B值(藍(lán)色分量)和A值(alpha分量)。其中紅、綠、藍(lán)三種顏色相組合,就可以得到我們所需要的各種顏色,而alpha不直接影響顏色,它將留待以后介紹。在RGBA模式下選擇顏色是十分簡單的事情,只需要一個函數(shù)就可以搞定。glColor*系列函數(shù)可以用于設(shè)置顏色,其中三個參數(shù)的版本可以指定R、
36、G、B的值,而A值采用默認(rèn);四個參數(shù)的版本可以分別指定R、G、B、A的值。例如:void glColor3f(GLfloat red, GLfloat green, GLfloat blue);void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);將浮點數(shù)作為參數(shù),其中0.0表示不使用該種顏色,而1.0表示將該種顏色用到最多。例如:glColor3f(1.0f, 0.0f, 0.0f); 表示不使用綠、藍(lán)色,而將紅色使用最多,于是得到最純凈的紅色。glColor3f(0
37、.0f, 1.0f, 1.0f); 表示使用綠、藍(lán)色到最多,而不使用紅色?;旌系男Ч褪菧\藍(lán)色。glColor3f(0.5f, 0.5f, 0.5f); 表示各種顏色使用一半,效果為灰色。注意:浮點數(shù)可以精確到小數(shù)點后若干位,這并不表示計算機就可以顯示如此多種顏色。實際上,計算機可以顯示的顏色種數(shù)將由硬件決定。如果OpenGL找不到精確的顏色,會進行類似“四舍五入”的處理。 void myDisplay(void) glClear(GL_COLOR_BUFFER_BIT);&
38、#160; glColor3f(0.0f, 1.0f, 1.0f); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); glFlush();注意:glColor系列函數(shù),在參數(shù)類型不同時,表示“最大”顏色的值也不同。采用f和d做后綴的函數(shù),以1.0表示最大的使用。采用b做后綴的函數(shù),以127表示最大的使用。采用ub做后綴的函數(shù),以255表示最大的使用。采用s做后綴的函數(shù),以32767表示最大的使用。采用us做后綴的函數(shù),以65535表示最大的使
39、用。2、索引顏色在索引顏色模式中,OpenGL需要一個顏色表。這個表就相當(dāng)于畫家的調(diào)色板:雖然可以調(diào)出很多種顏色,但同時存在于調(diào)色板上的顏色種數(shù)將不會超過調(diào)色板的格數(shù)。試將顏色表的每一項想象成調(diào)色板上的一個格子:它保存了一種顏色。在使用索引顏色模式畫圖時,我說“我把第i種顏色設(shè)置為某某”,其實就相當(dāng)于將調(diào)色板的第i格調(diào)為某某顏色。“我需要第k種顏色來畫圖”,那么就用畫筆去蘸一下第k格調(diào)色板。顏色表的大小是很有限的,一般在2564096之間,且總是2的整數(shù)次冪。在使用索引顏色方式進行繪圖時,總是先設(shè)置顏色表,然后選擇顏色。(1)選擇顏色使用glIndex*系列函數(shù)可以在顏色表中選擇顏色。其中最常
40、用的可能是glIndexi,它的參數(shù)是一個整形。void glIndexi(GLint c);3、指定清除屏幕用的顏色glClear(GL_COLOR_BUFFER_BIT);意思是把屏幕上的顏色清空。使用glClearColor來指定“空”的顏色,它需要四個參數(shù),其參數(shù)的意義跟glColor4f相似。在索引顏色模式下,使用glClearIndex來指定“空”的顏色所在的索引,它需要一個參數(shù),其意義跟glIndexi相似。void myDisplay(void) glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
41、; glClear(GL_COLOR_BUFFER_BIT); glFlush();4、指定著色模型OpenGL允許為同一多邊形的不同頂點指定不同的顏色。例如:#include <math.h>const GLdouble Pi = 3.1415926536;void myDisplay(void) int i; / glShadeModel(GL_FLAT);
42、0; glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLE_FAN); glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(0.0f, 0.0f); for(i=0; i<=8; +i)
43、0; glColor3f(i&0x04, i&0x02, i&0x01); glVertex2f(cos(i*Pi/4), sin(i*Pi/4); glEnd(); glFlush();相關(guān)函數(shù):glShadeModel();OpenGL允許為同一多邊形的不同頂點指定不同的顏色,使用glShadeModel函數(shù)可以關(guān)閉這種計算,如
44、果頂點的顏色不同,則將頂點之間的其它點全部設(shè)置為與某一個點相同。(直線以后指定的點的顏色為準(zhǔn),而多邊形將以任意頂點的顏色為準(zhǔn),由實現(xiàn)決定。)為了避免這個不確定性,盡量在多邊形中使用同一種顏色。glShadeModel的使用方法:glShadeModel(GL_SMOOTH); / 平滑方式,這也是默認(rèn)方式glShadeModel(GL_FLAT); / 單色方式glMatrixMode(GL_MODELVIEW);由于模型和視圖的變換都通過矩陣運算來實現(xiàn),在進行變換前,應(yīng)先設(shè)置當(dāng)前操作的矩陣為“模型
45、視圖矩陣”。glMatrixMode(GL_PROJECTION);/ 投影變換就是定義一個可視空間,可視空間以外的物體不會被繪制到屏幕上。(注意,從現(xiàn)在起,坐標(biāo)可以不再是-1.0到1.0了?。㎡penGL支持兩種類型的投影變換,即透視投影和正投影。投影也是使用矩陣來實現(xiàn)的。如果需要操作投影矩陣,如果需要操作投影矩陣,需要以GL_PROJECTION為參數(shù)調(diào)用glLoadIdentity();/把當(dāng)前矩陣設(shè)置為單位矩陣。glTranslate*();/把當(dāng)前矩陣和一個表示移動物體的矩陣相乘。三個參數(shù)分別表示了在三個坐標(biāo)上的位移值。glRotate*();/把當(dāng)前矩陣和一個表示旋轉(zhuǎn)物體的矩陣相乘
46、。物體將繞著(0,0,0)到(x,y,z)的直線以逆時針旋轉(zhuǎn),參數(shù)angle表示旋轉(zhuǎn)的角度。glScale*();/把當(dāng)前矩陣和一個表示縮放物體的矩陣相乘。x,y,z分別表示在該方向上的縮放比例。glFrustum();將當(dāng)前的可視空間設(shè)置為透視投影空間。其參數(shù)的意義如下圖:glOrtho();/將當(dāng)前的可視空間設(shè)置為正投影空間。其參數(shù)的意義如下圖:使用glViewport來定義視口。其中前兩個參數(shù)定義了視口的左下腳(0,0表示最左下方),后兩個參數(shù)分別是寬度和高度。較高要求:建立光照的過程1.建立光照模型對于光源發(fā)出的光線,可以分別設(shè)置其經(jīng)過鏡面反射和漫反射后的光線強度。對于被光線照射的材質(zhì)
47、,也可以分別設(shè)置光線經(jīng)過鏡面反射和漫反射后的光線強度。這些因素綜合起來,就形成了最終的光照效果。2.使用glColor*函數(shù)可以指定顏色,而使用glNormal*函數(shù)則可以指定法線向量。glEnable(GL_LIGHT0);可以開啟第0號光源3.每一個光源都可以設(shè)置其屬性,這一動作是通過glLight*函數(shù)完成的。glLight*函數(shù)具有三個參數(shù),第一個參數(shù)指明是設(shè)置哪一個光源的屬性,第二個參數(shù)指明是設(shè)置該光源的哪一個屬性,第三個參數(shù)則是指明把該屬性值設(shè)置成多少. (1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR屬性。這三個屬性表示了光源所發(fā)出的光的反射特性(以及顏色
48、)。每個屬性由四個值表示,分別代表了顏色的R, G, B, A值。GL_AMBIENT表示該光源所發(fā)出的光,經(jīng)過非常多次的反射后,最終遺留在整個光照環(huán)境中的強度(顏色)。GL_DIFFUSE表示該光源所發(fā)出的光,照射到粗糙表面時經(jīng)過漫反射,所得到的光的強度(顏色)。GL_SPECULAR表示該光源所發(fā)出的光,照射到光滑表面時經(jīng)過鏡面反射,所得到的光的強度(顏色)。(2)GL_POSITION屬性。表示光源所在的位置。由四個值(X, Y, Z, W)表示。如果第四個值W為零,則表示該光源位于無限遠(yuǎn)處,前三個值表示了它所在的方向。這種光源稱為方向性光源,通常,太陽可以近似的被認(rèn)為是方向性光源。如果
49、第四個值W不為零,則X/W, Y/W, Z/W表示了光源的位置。這種光源稱為位置性光源。對于位置性光源,設(shè)置其位置與設(shè)置多邊形頂點的方式相似,各種矩陣變換函數(shù)例如:glTranslate*、glRotate*等在這里也同樣有效。方向性光源在計算時比位置性光源快了不少,因此,在視覺效果允許的情況下,應(yīng)該盡可能的使用方向性光源。(3)GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF屬性。表示將光源作為聚光燈使用(這些屬性只對位置性光源有效)。很多光源都是向四面八方發(fā)射光線,但有時候一些光源則是只向某個方向發(fā)射,比如手電筒,只向一個較小的角度發(fā)射光線
50、。GL_SPOT_DIRECTION屬性有三個值,表示一個向量,即光源發(fā)射的方向。GL_SPOT_EXPONENT屬性只有一個值,表示聚光的程度,為零時表示光照范圍內(nèi)向各方向發(fā)射的光線強度相同,為正數(shù)時表示光照向中央集中,正對發(fā)射方向的位置受到更多光照,其它位置受到較少光照。數(shù)值越大,聚光效果就越明顯。GL_SPOT_CUTOFF屬性也只有一個值,表示一個角度,它是光源發(fā)射光線所覆蓋角度的一半(見圖2),其取值范圍在0到90之間,也可以取180這個特殊值。取值為180時表示光源發(fā)射光線覆蓋360度,即不使用聚光燈,向全周圍發(fā)射。4.控制材質(zhì)材質(zhì)與光源相似,也需要設(shè)置眾多的屬性。不同的是,光源是
51、通過glLight*函數(shù)來設(shè)置的,而材質(zhì)則是通過glMaterial*函數(shù)來設(shè)置的。glMaterial*函數(shù)有三個參數(shù)。第一個參數(shù)表示指定哪一面的屬性??梢允荊L_FRONT、GL_BACK或者GL_FRONT_AND_BACK。分別表示設(shè)置“正面”“背面”的材質(zhì),或者兩面同時設(shè)置。(關(guān)于“正面”“背面”的內(nèi)容需要參看前些課程的內(nèi)容)第二、第三個參數(shù)與glLight*函數(shù)的第二、三個參數(shù)作用類似。下面分別說明glMaterial*函數(shù)可以指定的材質(zhì)屬性。(1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR屬性。這三個屬性與光源的三個對應(yīng)屬性類似,每一屬性都由四個值組成。G
52、L_AMBIENT表示各種光線照射到該材質(zhì)上,經(jīng)過很多次反射后最終遺留在環(huán)境中的光線強度(顏色)。GL_DIFFUSE表示光線照射到該材質(zhì)上,經(jīng)過漫反射后形成的光線強度(顏色)。GL_SPECULAR表示光線照射到該材質(zhì)上,經(jīng)過鏡面反射后形成的光線強度(顏色)。通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,可以達(dá)到比較真實的效果。使用GL_AMBIENT_AND_DIFFUSE可以同時設(shè)置GL_AMBIENT和GL_DIFFUSE屬性。(2)GL_SHININESS屬性。該屬性只有一個值,稱為“鏡面指數(shù)”,取值范圍是0到128。該值越小,表示材質(zhì)越粗糙,點光源發(fā)射的光線照射到上
53、面,也可以產(chǎn)生較大的亮點。該值越大,表示材質(zhì)越類似于鏡面,光源照射到上面后,產(chǎn)生較小的亮點。 (3)GL_EMISSION屬性。該屬性由四個值組成,表示一種顏色。OpenGL認(rèn)為該材質(zhì)本身就微微的向外發(fā)射光線,以至于眼睛感覺到它有這樣的顏色,但這光線又比較微弱,以至于不會影響到其它物體的顏色。(4)GL_COLOR_INDEXES屬性。該屬性僅在顏色索引模式下使用,由于顏色索引模式下的光照比RGBA模式要復(fù)雜,并且使用范圍較小,這里不做討論。5、 選擇光照模型 這里所說的“光照模型”是OpenGL的術(shù)語,它相當(dāng)于我們在前面提到的“光照環(huán)境”。在OpenGL中,光照模型包括四個部分的內(nèi)容:全局環(huán)
54、境光線(即那些充分散射,無法分清究竟來自哪個光源的光線)的強度、觀察點位置是在較近位置還是在無限遠(yuǎn)處、物體正面與背面是否分別計算光照、鏡面顏色(即GL_SPECULAR屬性所指定的顏色)的計算是否從其它光照計算中分離出來,并在紋理操作以后在進行應(yīng)用。以上四方面的內(nèi)容都通過同一個函數(shù)glLightModel*來進行設(shè)置。該函數(shù)有兩個參數(shù),第一個表示要設(shè)置的項目,第二個參數(shù)表示要設(shè)置成的值。GL_LIGHT_MODEL_AMBIENT表示全局環(huán)境光線強度,由四個值組成。GL_LIGHT_MODEL_LOCAL_VIEWER表示是否在近處觀看,若是則設(shè)置為GL_TRUE,否則(即在無限遠(yuǎn)處觀看)設(shè)置
55、為GL_FALSE。GL_LIGHT_MODEL_TWO_SIDE表示是否執(zhí)行雙面光照計算。如果設(shè)置為GL_TRUE,則OpenGL不僅將根據(jù)法線向量計算正面的光照,也會將法線向量反轉(zhuǎn)并計算背面的光照。GL_LIGHT_MODEL_COLOR_CONTROL表示顏色計算方式。如果設(shè)置為GL_SINGLE_COLOR,表示按通常順序操作,先計算光照,再計算紋理。如果設(shè)置為GL_SEPARATE_SPECULAR_COLOR,表示將GL_SPECULAR屬性分離出來,先計算光照的其它部分,待紋理操作完成后再計算GL_SPECULAR。后者通常可以使畫面效果更為逼真(當(dāng)然,如果本身就沒有執(zhí)行任何紋理
56、操作,這樣的分離就沒有任何意義)。6.要打開光照處理功能,使用下面的語句:glEnable(GL_LIGHTING);要關(guān)閉光照處理功能,使用glDisable(GL_LIGHTING);即可。紋理映射過程:1、啟用紋理和載入紋理就像我們曾經(jīng)學(xué)習(xí)過的OpenGL光照一樣。在使用紋理前,必須啟用它。OpenGL支持一維紋理、二維紋理和三維紋理,這里我們僅介紹二維紋理??梢允褂靡韵抡Z句來啟用和禁用二維紋理:glEnable(GL_TEXTURE_2D); / 啟用二維紋理 glDisable(GL_TEXTURE_2D); / 禁用二維紋理 使用紋理前,還必須載入紋理。利用
57、glTexImage2D函數(shù)可以載入一個二維的紋理,該函數(shù)有多達(dá)九個參數(shù)(雖然某些參數(shù)我們可以暫時不去了解),現(xiàn)在分別說明如下:第一個參數(shù)為指定的目標(biāo),對于二維紋理這個參數(shù)使用GL_TEXTURE_2D。第二個參數(shù)為“多重細(xì)節(jié)層次”,現(xiàn)在我們并不考慮多重紋理細(xì)節(jié),因此這個參數(shù)設(shè)置為零。 第三個參數(shù)有兩種用法。在OpenGL 1.0,即最初的版本中,使用整數(shù)來表示顏色分量數(shù)目,例如:像素數(shù)據(jù)用RGB顏色表示,總共有紅、綠、藍(lán)三個值,因此參數(shù)設(shè)置為3,而如果像素數(shù)據(jù)是用RGBA顏色表示,總共有紅、綠、藍(lán)、alpha四個值,因此參數(shù)設(shè)置為4。而在后來的版本中,可以直接使用GL_RGB或GL_RGBA
58、來表示以上情況,顯得更直觀。 第四、五個參數(shù)是二維紋理像素的寬度和高度。使用紋理時要特別注意其大小。盡量使用大小為2的整數(shù)次方的紋理,當(dāng)這個要求無法滿足時,使用gluScaleImage函數(shù)把圖象縮放至所指定的大小 。無論舊版本還是新版本,都限制了紋理大小的最大值,例如,某OpenGL實現(xiàn)可能要求紋理最大不能超過1024*1024??梢允褂萌缦碌拇a來獲得OpenGL所支持的最大紋理:GLint max; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); 第六個參數(shù)是紋理邊框的大小,我們沒有使用紋理邊框,因此這里設(shè)置為零。第七個參數(shù)表示讀取的內(nèi)容,例如
59、:GL_RGB就會依次讀取像素的紅、綠、藍(lán)三種數(shù)據(jù),GL_RGBA則會依次讀取像素的紅、綠、藍(lán)、alpha四種數(shù)據(jù),GL_RED則只讀取像素的紅色數(shù)據(jù)(類似的還有GL_GREEN,GL_BLUE,以及GL_ALPHA)。第八個參數(shù)表示讀取的內(nèi)容保存到內(nèi)存時所使用的格式,例如:GL_UNSIGNED_BYTE會把各種數(shù)據(jù)保存為GLubyte,GL_FLOAT會把各種數(shù)據(jù)保存為GLfloat等。第九個參數(shù)表示一個指針,像素數(shù)據(jù)被讀取后,將被保存到這個指針?biāo)硎镜牡刂贰?舉個例子,如果有一幅大小為width*height,格式為Windows系統(tǒng)中使用最普遍的24位BGR,保存在pixels中的像素
60、圖象。則把這樣一幅圖象載入為紋理可使用以下代碼:glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels); 注意,載入紋理的過程可能比較慢,原因是紋理數(shù)據(jù)通常比較大,例如一幅512*512的BGR格式的圖象,大小為0.75M。把這些像素數(shù)據(jù)從主內(nèi)存?zhèn)魉偷綄iT的圖形硬件,這個過程中還可能需要把程序中所指定的像素格式轉(zhuǎn)化為圖形硬件所能識別的格式(或最能發(fā)揮圖形硬件性能的格式),這些操作都需要較多時間。2、紋理坐標(biāo)指定每一個頂點在紋理圖象中所對應(yīng)的像素位置,OpenGL
61、就會自動計算頂點以外的其它點在紋理圖象中所對應(yīng)的像素位置。 我們可以這樣類比一下:在繪制一條線段時,我們設(shè)置其中一個端點為紅色,另一個端點為綠色,則OpenGL會自動計算線段中其它各像素的顏色,如果是使用glShadeMode(GL_SMOOTH);,則最終會形成一種漸變的效果(例如線段中點,就是紅色和綠色的中間色)。類似的,在繪制一條線段時,我們設(shè)置其中一個端點使用“紋理圖象中最左下角的顏色”作為它的顏色,另一個端點使用“紋理圖象中最右上角的顏色”作為它的顏色,則OpenGL會自動在紋理圖象中選擇合適位置的顏色,填充到線段的各個像素(例如線段中點,可能就是選擇紋理圖象中央的那個像素的顏色)。
62、在類比時,使用了“紋理圖象中最左下角的顏色”這種說法。但這種說法在很多時候不夠精確,我們需要一種精確的方式來表示我們究竟使用紋理中的哪個像素。紋理坐標(biāo)也就是因為這樣的要求而產(chǎn)生的。以二維紋理為例,規(guī)定紋理最左下角的坐標(biāo)為(0, 0),最右上角的坐標(biāo)為(1, 1),于是紋理中的每一個像素的位置都可以用兩個浮點數(shù)來表示(三維紋理會用三個浮點數(shù)表示,一維紋理則只用一個即可)。 使用glTexCoord*系列函數(shù)來指定紋理坐標(biāo)。這些函數(shù)的用法與使用glVertex*系列函數(shù)來指定頂點坐標(biāo)十分相似。例如:glTexCoord2f(0.0f, 0.0f);指定使用(0, 0)紋理坐標(biāo)。通常,每個頂點使用不同的紋理,于是下面這樣形式的代碼是比較常見的。glBegin( /* . */ ); glTexCoord2f( /* . */ ); glVertex3f( /* . */ ); glTexCoord2f( /* . */ ); glVertex3f( /* . */ ); /* . */glEnd(); 3、紋理參數(shù)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 樂清2022年事業(yè)編招聘考試模擬試題及答案解析16
- 2026屆遼寧省葫蘆島市高三上學(xué)期期末考試歷史試題(含答案)
- 邵陽職院考試題庫及答案
- 鉗工知識競賽試題及答案
- 辯論培訓(xùn)課件
- 北師大版數(shù)學(xué)三年級上冊期末評價(A卷)(含答案)
- 四川省綿陽市游仙區(qū)2024-2025學(xué)年八年級上學(xué)期期末地理試題(含答案)
- 輔警特色培訓(xùn)課程
- 2025 小學(xué)三年級科學(xué)下冊保護植物的重要性教育課件
- 2026年深圳中考語文考前15天沖刺試卷(附答案可下載)
- 虛擬電廠的分布式能源協(xié)同調(diào)度與彈性運行機制
- 蘭州水務(wù)冬季安全培訓(xùn)課件
- 陜西交控集團招聘筆試題庫2026
- 山東省濟南市槐蔭區(qū)2024-2025學(xué)年四年級上學(xué)期期末考試語文試卷
- 零售門店銷售激勵方案設(shè)計與實施
- 口腔科智齒培訓(xùn)
- GB/T 26953-2025焊縫無損檢測滲透檢測驗收等級
- 2025年pmp項目管理考試試題及答案
- 湖南省懷化市2024-2025學(xué)年七年級上學(xué)期語文期末試卷(含答案)
- 合同款轉(zhuǎn)為借款協(xié)議
- 2026年高考作文備考之題目解析及范文:不是所有的鮮花都盛開在春天
評論
0/150
提交評論