編程開發(fā)opengl入門教程精_第1頁
編程開發(fā)opengl入門教程精_第2頁
編程開發(fā)opengl入門教程精_第3頁
編程開發(fā)opengl入門教程精_第4頁
編程開發(fā)opengl入門教程精_第5頁
已閱讀5頁,還剩89頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、OpenGL 入1.第一課 OpenGL 入1.第一課 是如何編寫出來的?就TC640*480 分辨率、OpenGL命令最初C語言函數(shù)來進(jìn)行描述的,對C語言的人來講,OpenGL是容易理解和學(xué)習(xí)的。如果你曾經(jīng)接觸過 TC graphics h,你會(huì)發(fā)現(xiàn),使用 OpenGL 作圖甚至比 TC 更加簡單。Direct3D雖然也是十分優(yōu)秀的圖API,但它只用Windows 系統(tǒng)(現(xiàn)在還要加上一XBOX游戲機(jī)OpenGLWindows,還Unix/Linux 等其它系統(tǒng),它甚至在大型計(jì)算機(jī)、各種專業(yè)計(jì)算機(jī)(如:醫(yī)療用顯示設(shè)備)上都有應(yīng)用。并且,OpenGL 的基本命令都做到了硬件無關(guān),甚至OpenGL

2、是一個(gè)工業(yè)標(biāo)準(zhǔn),它的技術(shù)緊跟時(shí)代,現(xiàn)今各個(gè)顯卡廠家無一不對OpenGL 提供強(qiáng)力支持,激烈的競爭中使得 OpenGL 性能一直領(lǐng)先。(英文學(xué)習(xí) OpenGL 前的準(zhǔn)備工作 + 第二步,安裝 GLUT 工具包 Windows環(huán)境下Windows 環(huán)境下安裝 GLUT 的步驟:是 得到的 裝4、把解壓得到的glut.dll 和 glut32.dll 放到操作系 4、把解壓得到的glut.dll 和 glut32.dll 放到操作系 框左邊ApplicationSettings,找Emptyproject 并勾上,選Finish然后向該工程添加一個(gè)代碼文件,取名為“OpenGL.c”,注意用.c來作

3、為文件結(jié)尾。#includeGL/glutvoidglRectf(-0.5f, -0.5f, 0.5f, 0.5f); glutInit(&argc, ition(100, return argcchar*argv),這個(gè)是帶命令行參數(shù)main函數(shù),各位應(yīng)該見過吧?沒見過的 1、glutInitGLUT進(jìn)行初始化,這個(gè)函 1、glutInitGLUT進(jìn)行初始化,這個(gè)函數(shù)必須在其它GLUT使用之前調(diào)用一次。其格式比較死板,一般照抄這句 glutInit(&argc, argv)就可以了。 glutDisplayFunc 設(shè)置了“當(dāng)需要畫圖時(shí),請myDisplay函數(shù)”myDisplay用來畫圖。

4、觀察 myDisplay 中的三個(gè)函數(shù)調(diào)用,發(fā)現(xiàn)它們都以gl 開頭。這種以 gl 開頭的函數(shù)都是 3、glFlush,保證前面OpenGL 命令立即執(zhí)行(而不是讓它們在緩沖區(qū)中等待。其作用2.第二課)enL (是無窮小。同一像素上,OpenGL 可以繪制許多坐標(biāo)只有稍微不同的點(diǎn),但該像素的具體顏色將取決 同樣的,數(shù)學(xué)上的直線沒有寬度OpenGL 的直線則是有寬度的。同時(shí),OpenGL 的直線必須是有限長效果是未定義的OpenGL 為了效率,放寬了檢查,這可能導(dǎo)致顯示錯(cuò)誤。要避免這個(gè)錯(cuò)誤,盡量使用由以上如何指定一個(gè)點(diǎn)呢?OpenGL 提供了一系列函數(shù)。它們都以 glVertex 開頭,后面跟一個(gè)

5、數(shù)字和 12 個(gè)字母。例 字母表示參數(shù)的類型,s16位整數(shù)(OpenGL中將這GLshort v 表示傳遞的幾個(gè)參數(shù)將使用指針的方式,見下面的例子。, , , 用 么 成 void 當(dāng) n 大到一定程度后,人眼將無法把它跟真正的圓相區(qū)別這已經(jīng)成功的畫出了一個(gè)“圓當(dāng) 當(dāng) GL_POLYGON GL_LINE_LOOP、 n =const GLfloat R=constGLfloatPi=3.1415926536f; voidmyDisplay(void)for(i=0;i“屬性” s icGLubyteMask128; FILE*fp;fp=fopen(mask.bmp,rb); if( !fp

6、 )讀 注意-( )sizeof(Mask)雖然不是什么好的寫法,但這里它確實(shí)是正確有效 if(fseek(fp,-( )sizeof(Mask),SEEK_END) sizeof(Mask)個(gè)字節(jié)到if(!fread(Mask, sizeof(Mask), 1,fp) #include #include voidmyDisplay(void)s icGLubyteMask128; FILE*fp;fp =fopen(mask.bmp,if(!fp if(fseek(fp,-( )sizeof(Mask),SEEK_END) if(!fread(Mask, sizeof(Mask),1,fp)

7、glRectf(-0.5f0.5f0.0f0.0f在左下方繪制一個(gè)有鏤空效果的正方glRectf(0.0f0.0f0.5f0.5f); / / 在右上方繪制一個(gè)無鏤空效4.第四課無論哪種顏色模式,計(jì)算機(jī)都必須為每一個(gè)像素保存一些數(shù)據(jù)。不同的是,RGBA模式中,數(shù)據(jù)直接就代1. RGBA顏RGBA 模式中,每一個(gè)像素會(huì)保存以下數(shù)據(jù):R 值(紅色分量、G 值(綠色分量、B 值(藍(lán)色分量)RGBA 模式中,每一個(gè)像素會(huì)保存以下數(shù)據(jù):R 值(紅色分量、G 值(綠色分量、B 值(藍(lán)色分量) glColor*系列函數(shù)可以用于設(shè)置顏色,其中三個(gè)參數(shù)的版本可R、G、B的值,而A值采用默認(rèn);四個(gè)參數(shù)的版本可以分

8、別指定 R、G、B、A 的值。例如:voidglColor3f(GLfloatred,GLfloatgreen,GLfloatvoidglColor4f(GLfloatred,GLfloatgreen,GLfloatblue,GLfloat 于 glColor3f(1.0f,0.0f,glColor3f(0.0f,1.0f,glColor3f(0.5f,0.5f,果 中 voidglColor3f(0.0f, 1.0f, 1.0f);注意:glColor系列函數(shù),在參數(shù)類型不同時(shí),表示“最大”顏色的值也不同。采用 f 和 d 做后綴的函數(shù),以 1.0 表示最大的使用。采用 b 做后綴的函數(shù),以

9、 127 表示最大的使用。ub做后綴的函數(shù)255表示最大的使用。penL顏色?!拔倚枰?k 種顏色來畫圖”,那么就用畫筆去蘸一下第 k 格調(diào)色板。 void glIndexi(GLOpenGL 并直接沒有提供設(shè)置顏色表的方法,OpenGL 并直接沒有提供設(shè)置顏色表的方法,因此設(shè)置顏色表需要使用操作系統(tǒng)的支持Windows和其他大多數(shù)圖形操作系統(tǒng)都具有這個(gè)功能,但所使用的函數(shù)卻不相同。正如我沒有講述如何自己寫代碼在 Windows 下建立一個(gè)窗口,這里我也不會(huì)講述如何在 Windows 下設(shè)置顏色表。 #include #include #pragmacomment(lib,#pragmaco

10、mment(lib,const=voidfor(i=0;i8; glVertex2f(0.0f, 0.0f);for(i=0;i=8; ition(0,0,400,Sleep(10 * 1000);return 的 但實(shí)際上什么才叫“空”呢?在宇宙中,黑色代表了“空”;在一張白紙上,白色代表了“空”;在信封上,信 在索引顏色模式下,使glClearIndex來指定“空”的顏色所在的索引,它需要一個(gè)參數(shù),其意義glIndexivoidglClearColor(1.0f, 0.0f, 0.0f, 0.0f); const=void/ glColor3f(1.0f, 1.0f, 1.0f); glV

11、ertex2f(0.0f, 0.0f);for(i=0;i=8; 的索引值是接近的,如果將顏色表中接近的項(xiàng)設(shè)置成接近的顏色,則看起來也是漸變的效果。但如(GL_SMOOTH); / 平滑方式,這也是默認(rèn)方可以設(shè)置 glClear 清除后屏幕所剩的顏色。5. 第五課軸向右,Y軸向上,Z軸垂直屏幕。這些 4 1在 OpenGL 中,實(shí)現(xiàn)這兩種功能甚至使用的是同樣的函數(shù)。視圖矩陣”。設(shè)置的方法是VIEWglMatrixMode函數(shù),像這樣 針旋轉(zhuǎn),參數(shù) angle 表示旋轉(zhuǎn)的角度。 矩陣,然后先乘以一個(gè)表示旋轉(zhuǎn)的矩陣R最后得到的矩陣再乘上每一個(gè)頂點(diǎn)的坐標(biāo)矩陣 v。所以,經(jīng)過變換得到的頂點(diǎn)坐標(biāo)就是(R

12、T)v)。實(shí)際變換的順序與代碼中寫的順序是相反的。由于“先移動(dòng)后旋轉(zhuǎn)”和“先旋轉(zhuǎn)后移動(dòng)”得到的結(jié)果OpenGL 之所以這樣設(shè)計(jì),是為了得到更高的效率。但在繪制復(fù)雜的三維圖形時(shí),如果每次讓 不再是-1.01.0了OpenGL 支持兩種類型的投影變換 介于是入調(diào)用 glPushMatrix 函數(shù),它相當(dāng)于把矩陣(相當(dāng)于盤子)放到堆棧上。當(dāng)需要恢復(fù)最近一次的保,調(diào)用 轉(zhuǎn)一圈。每個(gè)月,月亮圍著地球轉(zhuǎn)一圈。即一年360 天?,F(xiàn)在給出日期 讓 2500 倍),4345000(放大2500 倍。將地球到月亮的距離“修改”38000000(放大100 倍很近時(shí)為 還可以把觀察點(diǎn)往“上”方移動(dòng)一些,得到(020

13、0000000200000000),這樣可以得45 度 最遠(yuǎn)可視200000000*2=400000000(60,1,1,現(xiàn)所使用glut 實(shí)用工具中,正好 20。地球則要復(fù)雜一點(diǎn),需要變換坐標(biāo)。由于今年已經(jīng)經(jīng)過的天數(shù)已知為 day,則地球轉(zhuǎn)過的角度為 day/一年的天數(shù)*360 度。前面已經(jīng)假定每年都360 天,因此地球轉(zhuǎn)過的角度恰好day。所以glRo ef(day,0,0,-glTranslatef(地球軌道半徑, 0, 0);glutSolidSphere(地球半徑20glRo ef(月亮旋轉(zhuǎn)的角度, 0,0, glutSolidSphere(月亮半徑20但這個(gè)“月亮旋轉(zhuǎn)的角度”,并不

14、能簡單的理解glRo ef(月亮旋轉(zhuǎn)的角度, 0,0, glutSolidSphere(月亮半徑20但這個(gè)“月亮旋轉(zhuǎn)的角度”,并不能簡單的理解為 day/一個(gè)月的天數(shù) 30*360 度。在繪制地球前用 glPushMatrix 保存矩陣,繪制地球后用 glPopMatrix 恢復(fù)矩陣。再設(shè)計(jì)一個(gè)跟位置無關(guān)的月亮位置公式,來繪制月亮。通法比前一種要好,因?yàn)楦↑c(diǎn)的運(yùn)算是確的,即是計(jì)算地球本身的位置就是不精確的。拿這個(gè)不精確的數(shù)去計(jì)算月亮的位置導(dǎo)致“不精確”的成分累積,過多的“不精確”會(huì)造成錯(cuò)誤。還有一個(gè)需要注意的細(xì)節(jié):OpenGL 把三維坐標(biāo)中的物體繪制到二維屏幕,繪制的順序是按照代的“后面”也是

15、如此。使用深度測試可以解決這一問題。使用的方法是:1、以 用 這個(gè)小程序沒有去考慮這個(gè),但度緩沖, 即: glClear(GL_DEPTH_BUFFER_BIT); 其中, glClear(GL_COLOR_BUFFER_BIT) 與s day200day 的變0void (75,1,1,gluLookAt(0,-200000000,200000000, 0,0, 0,0, 0,”glColor3f(1.0f,0.0f,glutSolidSphere(69600000,20,繪制藍(lán)色的“地球glColor3f(0.0f,0.0f,glRo ef(day/360.0*360.0, 0.0f,0.

16、0f,- glutSolidSphere(15945000,”glColor3f(1.0f,0.0f,glutSolidSphere(69600000,20,繪制藍(lán)色的“地球glColor3f(0.0f,0.0f,glRo ef(day/360.0*360.0, 0.0f,0.0f,- glutSolidSphere(15945000,20,繪制黃色的“月亮glColor3f(1.0f,1.0f,glRo ef(day/30.0*360.0-day/360.0*360.0,0.0f,0.0f,- glutSolidSphere(4345000,20,正式進(jìn)入了三維OpenGL 數(shù) 可以縮放物體

17、,使用的函數(shù)是 glScale*。 視投影”的(glFrustum矩陣有自己的“ 堆?!保奖氵M(jìn)行保存和恢復(fù)。這在繪制復(fù)雜圖形時(shí)很有幫助。使用的函數(shù)6. 第六課過 6. 第六課過 2530 for(i=0;in;1讓如何解決這一問題設(shè)想有兩塊畫板,畫圖的人在旁邊畫,畫好以后把他手里畫板與掛在屏幕上的畫板相交換。這樣以來,觀眾就不會(huì)看到殘缺的畫了。這一技術(shù)應(yīng)用到計(jì)算機(jī)圖形中,稱為雙緩沖技術(shù)器(很有可能是顯存)中開辟兩區(qū)域,一塊作為發(fā)送到顯示器的數(shù)據(jù),一塊作為繪畫的區(qū)域,在適當(dāng)?shù)臅r(shí)候交換它們OpenGL 為了保證更好的可移植性,允許在實(shí)現(xiàn)時(shí)不PC 以前main 也可以很輕松的完成這一工作,只要在繪

18、制完成時(shí)簡單的調(diào)用glutSwapBuffers函數(shù)就可也可以很輕松的完成這一工作,只要在繪制完成時(shí)簡單的調(diào)用glutSwapBuffers函數(shù)就可for(i=0;in;的第一OpenGL 程序嗎? 意思是對系統(tǒng)說:如果你需要繪制窗口了,請調(diào)用myDisplay 這個(gè)函數(shù)。為什 熟悉一點(diǎn)的來說Windows X 窗口統(tǒng),都是支持同時(shí)顯示多個(gè)窗口的。假如你的程序窗口碰巧被別的窗口遮住了,后來用戶又 起來的工作是否也可以交給操作系統(tǒng)呢是肯定的先前的思路是:繪制,然后等段時(shí)間;再繪制,再等待一段時(shí)間。但如果去掉等待的時(shí)間,就變成了繪制,繪制,不mp3CPU這里的“CPU空閑的時(shí)間繪制” 的時(shí)間調(diào)用某

19、一函數(shù)。其GLUT還提供了一些別的函數(shù),例如“在鍵盤按下時(shí)做某事”等到現(xiàn)在#include= 360day =argc,char ition(100, ,地球和月亮); / 改了窗口標(biāo)return 。大家知道顯示器的刷新率是比較有限的,一般為60120Hz,也就是一秒鐘刷60120 次。僅能的浪費(fèi),還。大家知道顯示器的刷新率是比較有限的,一般為60120Hz,也就是一秒鐘刷60120 次。僅能的浪費(fèi),還可能帶來一影響(例如,顯示器只刷新到一半時(shí),需要繪制的內(nèi)顯示。這樣一來,計(jì)算機(jī)就不必去繪制大量的根本就用不到的圖象了。如果顯示器的刷新率為 85z85P空 過了 1/60 秒,則幀速將急劇下降。

20、如果繪制一幅圖畫的時(shí)間為 1/50,則在第一個(gè) 1/60 秒時(shí),顯示器需要刷新了,但由于新的圖畫沒有 上用了 1/30 秒,幀速為 30FPS(如果不采用垂直同步,則幀速應(yīng)該是 50FPS) 畫完時(shí),幀速為 60FPS,在 1/60 時(shí)間未完成時(shí),幀速為 30FPS,這就造成了幀速的跳動(dòng)。這是很。 。 doublessicdoublesicclock_t last,doubleif(count =50returncount =last =current =timegap =(current-save=return 但的圖形窗口背后,還有一個(gè)命令行窗口pr f 函數(shù)就可以輕易的輸出#includ

21、estdiopr f(FPS = %fn, FPS);#includeGL/glut#includestdio#includeGL/glut#includestdios day200day 的變0doublessicdoublesicclock_t last,doubleif(count = 360day =argc,char ition(100, voidif(day = 360day =argc,char ition(100, return OpenGL動(dòng)畫和傳統(tǒng)意義上的動(dòng)畫相似,都是把畫面一幅一幅的呈現(xiàn)在觀眾面前。一旦畫面變換通常都是利用 CPU 空閑的時(shí)候繪制動(dòng)畫,但也可以有其它的選擇

22、。7. 第七課請看圖 OpenGL 在處理光照時(shí)采用這樣一種近似:把光照系統(tǒng)分為三照的各種物體的表面,由于物體如何反射光線只由物體表面決定(OpenGL 中沒有考慮 個(gè)光源發(fā)出,這時(shí),指定一個(gè)“環(huán)境亮度”參數(shù),可以使最后形成的畫面更接近于真實(shí)情畫面。在 OpenGL 中,法線的方向是用一個(gè)向量來表示。不幸的是,OpenGL 并不會(huì)根據(jù)你所指定的多邊形各個(gè)頂點(diǎn)來計(jì)算出這些多邊形頂點(diǎn)的顏色,OpenGL 就可以自行計(jì)算頂點(diǎn)之間的其它點(diǎn)的顏色。并且,顏色一旦被指在指定法線向量時(shí),只需要指定每一個(gè)頂點(diǎn)的法線向量,OpenGL 會(huì)自行計(jì)算頂點(diǎn)之間后指定的所有頂點(diǎn)都將以這一向量作為自己glColor*函數(shù)

23、可以指定顏色,而使用 glNormal*函數(shù)則可以指定法線向量。注意:使glTranslate*glRo e*函數(shù)可以改變物體的外觀,但法線向量并不會(huì)隨之改變。然而,使用 glScale*函數(shù),對每一坐標(biāo)軸進(jìn)行不同程度的縮放,很有可能導(dǎo)致法線向量的不正確,雖OpenGL 提供了一些措施來修正這一問題,但由此也帶來了三. 控制光OpenGL 中,僅僅支持有限數(shù)量的光源。使用 GL_LIGHT0 表示第0 號(hào)光源,GL_LIGHT1 表示 以關(guān)閉光源。一OpenGL 實(shí)現(xiàn)可能致程序運(yùn)行速度的嚴(yán)重下降,玩3DMark的朋友可能多少也有些體會(huì)。一些場景中可能有成上千的電燈,這時(shí)可能需要采取一些近段來進(jìn)

24、行編程,否則以目前的計(jì)算機(jī)而言,是ltg(1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR 屬性。這三個(gè)屬性表示了光源所發(fā)出的光示該光源所發(fā)出的光,經(jīng)過非常多次的反射后,最終遺留在整個(gè)光照環(huán)境中的強(qiáng)度(顏色。 (2)相似,各種矩陣變換函數(shù)glTranslate*、glRo e*等在這里也同樣有效。方向性光源在計(jì)算(3)GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF屬性。表示將光源作些光源則是只向某個(gè)方向發(fā)射如手電筒,只向一個(gè)較小的角度發(fā)射光線。 大,聚光效果就越明顯。GL_SPOT_CUTOFF 屬性也只有一個(gè)值,表示一

25、個(gè)角度,它是光源發(fā)射 (4)、 屬性只對位置性光源有效?,F(xiàn)實(shí)生活中,光線的強(qiáng)度隨著距離的增加而減弱,OpenGL把這個(gè)減衰減1k1k2* dk3*k3*d表示距離,光線的初始強(qiáng)度乘以衰減因子,就得到對應(yīng)距離的光線強(qiáng)度。k1,k2k3分別就 四. 的,而材質(zhì)則是通過 glMaterial*函數(shù)來設(shè)置的。 glLight*函數(shù)的第二、三個(gè)參數(shù)作用類似。下面分別說明 glMaterial*函數(shù)可以指定的材 對應(yīng)屬性類似,每一屬性都由四個(gè)值組成。GL_AMBIENT 表示各種光線照射到該材質(zhì)上,經(jīng)過很多次反射后最終遺留在環(huán)境中的光線強(qiáng)度(顏色。GL_DIFFUSE 表示光線照射到該材質(zhì)上,經(jīng)過漫反射后

26、形成的光線強(qiáng)度(顏色。GL_SPECULAR表示光線照射到該材質(zhì)上,經(jīng)過鏡面反射后形成的光線強(qiáng)度(顏色。通常,GL_AMBIENT 對應(yīng)屬性類似,每一屬性都由四個(gè)值組成。GL_AMBIENT 表示各種光線照射到該材質(zhì)上,經(jīng)過很多次反射后最終遺留在環(huán)境中的光線強(qiáng)度(顏色。GL_DIFFUSE 表示光線照射到該材質(zhì)上,經(jīng)過漫反射后形成的光線強(qiáng)度(顏色。GL_SPECULAR表示光線照射到該材質(zhì)上,經(jīng)過鏡面反射后形成的光線強(qiáng)度(顏色。通常,GL_AMBIENT 和 GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE 可以同時(shí)設(shè)GL_AMBIENT GL_DIFFUSE屬性。(2) G

27、L_SHININESS 屬性。該屬性只有一個(gè)值,稱為“鏡面指數(shù)”,取值范圍是 0 比 。這里所說的“光照模型”O(jiān)penGL 的術(shù)語,它相當(dāng)面提到的“光照環(huán)境”。在 照、鏡面顏色(GL_SPECULAR 屬性所指定的顏色)的計(jì)算是否從其它光照計(jì)算中分離出來, 為 部分,待紋理操作完成后GL_SPECULAR。后者通??梢允巩嬅嫘Ч鼮?真(當(dāng)然,如到現(xiàn)在可以說是完事俱備了。不過,OpenGL 默認(rèn)是關(guān)閉光照處理的。要打開光照處理功能,使仍然、地球作為例子(這次就不考慮月亮了-),作為光源,模擬地球圍繞陽轉(zhuǎn)動(dòng)時(shí)光照的變化。于是,需要設(shè)置一個(gè)光源,設(shè)置兩種材質(zhì)的材質(zhì)和地果使用 數(shù)來繪制球體,則該函數(shù)

28、會(huì)自動(dòng)的指定這些法線向量,不必再手。如果是自己指定若干由函數(shù)來創(chuàng)建效果的視圖#include=360.0f) angle = 0.0f;argc,char*glutInit(&argc, ition(200, return 本課介紹OpenGL 光照的基argc,char*glutInit(&argc, ition(200, return 本課介紹OpenGL 光照的基本知識(shí)。OpenGL 把光照分解為光源、材質(zhì)、光照模式三個(gè)部分,來設(shè)置。使用 glLight*函數(shù)可設(shè)置光源的屬性,使用 glMaterial* 函數(shù)可設(shè)置材質(zhì)的屬性 的鏡面反射強(qiáng)度由兩個(gè) GL_SPECULAR 屬性共同決定。

29、可以使用多個(gè)光源來實(shí)現(xiàn)各種 真的效果,然而,光源數(shù)量的增加將造成程序運(yùn)行速度的明顯下OpenGL 光照過程中,屬性的種類和數(shù)量都非常繁多,通常,需要很多的經(jīng)驗(yàn)才可以熟的設(shè)置各種屬性,從而形成 真的光照效(各位也看到了,其實(shí)這個(gè)課程的示例程序中設(shè)以類似3DS MAX 之類8.第八課 是segments =const GLfloatpi= GLfloat tmp= 2 *pi*是segments =const GLfloatpi= GLfloat tmp= 2 *pi*i/glVertex2f(cos(tmp),過 在編寫程序時(shí),遇到重復(fù)的工作往往是將重復(fù)的工作編寫為函數(shù),在需要的地方調(diào)用它類似的

30、,在編OpenGL程序時(shí),遇到重復(fù)的工作,可以創(chuàng)建一個(gè)顯示列表,把重復(fù)的工作裝不同的函數(shù)用不同的名字來區(qū)分,而在 OpenGL 中,不同的顯示列表用不同的正整數(shù)來區(qū)分。一個(gè)顯示列表將另一個(gè)顯示列表覆蓋的情況。為了避免這一問題,使用glGenLists 函數(shù)。glGenLists函數(shù)有一個(gè)參數(shù)i,表示要分配i 個(gè)連續(xù)的未使用的顯示列干連中最小的一個(gè)。例如,glGenLists(3);如果返回 20,則表示分配了 20、21、22 這三個(gè)創(chuàng)建顯示列表實(shí)際上就是把各OpenGL函數(shù)的調(diào)用裝入到顯示列表中。使用glNewList 創(chuàng)建顯示列表實(shí)際上就是把各OpenGL函數(shù)的調(diào)用裝入到顯示列表中。使用g

31、lNewList 例如,需要把“設(shè)置顏色為紅色,并且指定一個(gè)坐標(biāo)為(0, 0)的頂點(diǎn)”這兩條命令裝入為 glColor3f(1.0f,0.0f,0.0f); glVertex2f(0.0f, 0.0f); i=if(i 20glVertex2f(0.0f, 0.0f); 另外,并非所有OpenGL函數(shù)都可以裝入到顯示列表中。例如,各種用于查詢的函數(shù),它們無 為 10 的顯示列表,直接使用 glCallList(10);就可以了。使用 G_UNIGND_BT(的GL_BYTE(每G_HOT,需要用 l1+kl2+kl3+k,。lists=1,3,4, ,111314,18的四個(gè)顯示列表 例如,使

32、用ists(20,4);將銷毀20,21,22,23這四個(gè)顯示列表1、明顯的減OpenGL函數(shù)的調(diào)用次數(shù)。如果函數(shù)調(diào)用是通過網(wǎng)絡(luò)進(jìn)行的(Linux等操作系統(tǒng)支持這樣的方式,即由應(yīng)用程序在客戶端發(fā)OpenGL 請求,由網(wǎng)絡(luò)上的另一臺(tái)服務(wù)器進(jìn)行實(shí)際的 已經(jīng)知道glTranslate*、glRo e*、glScale*等函數(shù)時(shí),實(shí)際上是執(zhí)行的 同時(shí),顯示列表也為程序的設(shè)計(jì)帶來方便在設(shè)置一些屬性時(shí),經(jīng)常把一些相關(guān)的函數(shù)量 (-0.5,-5*sqrt(5)/48, (0.5, -5*sqrt(5)/48, ( 0,-5*sqrt(5)/48, -( 0,2007424日修正:以上結(jié)果有誤,通ABACAD

33、BCBDCD的長度,發(fā)ADBDCDA 點(diǎn):( 0.5, -sqrt(6)/12,B點(diǎn):0.5, -sqrt(6)/12,C點(diǎn):( 0, -sqrt(6)/12, D 點(diǎn):( 0, #includegl/glut#include=360.0fangle=argc,char* glutInitDisplayMode(GLUT_RGBA|ition(200, return 感將 , voidsetNormal(GLfloat*Po 1, GLfloat*Po 2,GLfloat*Po GLfloatfor(i=0;i3;normali=(Po 1i+Po 2i+Po 3i)/的 OpenGL 函數(shù)。

34、顯示列表中除了存放對 OpenGL 函數(shù)的調(diào)用外,不會(huì)存放其它內(nèi)容。,把OpenGL函數(shù)調(diào)用裝入顯示列表的 9. 第九課今天介紹OpenGL混合的基本知識(shí)?;旌鲜且环N常用的技巧,通??梢杂脕韺?shí)現(xiàn)半透明。但要使OpenGL的混合功能,只需要調(diào)用:glEnable(GL_BLEND);即可。前處理后得到一種新的顏色。這里把將要畫上去的顏色稱為“源顏色”,把原來的顏色OpenGL會(huì)把源顏色和目標(biāo)顏色各自取出,并乘以一個(gè)系數(shù)(源顏色乘以的系數(shù)稱為“源可以不是相加,新版本OpenGL 可以設(shè)置運(yùn)算方式,包括加、減、取兩者中較大的色,alpha 值)是(Rs,GsBsAs),目標(biāo)顏色的四個(gè)分量是(RdGd

35、,BdAd),又設(shè)源因子為(Sr, Sg, Sb, Sa),目標(biāo)因子為(Dr, Dg, Db, Da)。則混合產(chǎn)生的新顏色可以表示為: (Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)GL_ZERO: 表示0.0作為因子,實(shí)際上相當(dāng)于不使用這種顏色參與混合運(yùn)算GL_SRC_ALPHA:表示使用源顏色的 alpha 值來作為因子。 GL_DST_ALPHA:表示使用目標(biāo)顏色的 alpha除此以外,還有 GL_SRC_COLOR(把源顏色的四個(gè)分量分別作為因子的四個(gè)分量、 GL_ONE_MINUS_SRC_COLOR、GL_DST_COLOR

36、、等,前OpenGL舊版本中只能用于除此以外,還有 GL_SRC_COLOR(把源顏色的四個(gè)分量分別作為因子的四個(gè)分量、 GL_ONE_MINUS_SRC_COLOR、GL_DST_COLOR、等,前OpenGL舊版本中只能用于設(shè)置目標(biāo)因子,后兩個(gè)OpenGL舊版本中只能用于設(shè)置源因子。新版本的 OpenGL 則沒有這個(gè)限制,并且支持新的 、 如果設(shè)置glBlendFunc(GL_ONEGL_ZERO);,則表示完全使用源顏色,完全不使用目如果設(shè)置glBlendFunc(GL_ZEROGL_ONE);,則表示完全不使用源顏色,因此無論你了 , 顏色乘以自身的 alpha 值,目標(biāo)顏色乘以 1.

37、0 減去源顏色的 alpha 值,這樣一來,源顏色alpha 值越大,則產(chǎn)生的新顏色中源顏色所占比例就越大,而目標(biāo)顏色所占比例則 的顏色實(shí)際上就是兩種顏色的簡單相加。例如紅色(1, 0, 0)和綠色(0, 1, 0)相加得到(1,10),結(jié)果為黃色。1,10.50.5);glRectf(-0.50.5,11);,這兩個(gè)矩形有一用 , void glColor4f(1,0,0,glRectf(-1,-1,0.5,glColor4f(0,1,0,glRectf(-0.5,-0.5,1,glColor4f(1,0,0,glRectf(-1,-1,0.5,glColor4f(0,1,0,glRectf

38、(-0.5,-0.5,1,嘗試把的參數(shù)修以改為及 , 制的圖形會(huì)覆蓋先繪制的圖形。第二種情況下,alpha 被當(dāng)作“,深度緩沖是這樣一段數(shù)據(jù)試的情況下,如果將要繪制的像素比原來的像素更近,則像素將被繪制。否則,像素體再繪制遠(yuǎn)的物體,還是先繪制遠(yuǎn)的物體再繪制近的物體,或者干脆的順序進(jìn)這個(gè)好辦,只需要把物體分為兩個(gè)部分,一部分全是半透明的,一部分全是不透明即使使用了以上技巧制的將成為“目標(biāo)顏色”,后繪制的將成為“源顏色”,所以繪制的順序?qū)?huì)對結(jié)果造成一調(diào)用 glDepthMask(GL_FALSE); ,包括大名鼎鼎的,都在使用三維混合時(shí)直接將深度緩沖用 的物體,再在其背后繪制半透明物體,本來后面

39、的半透明物體將不會(huì)被顯示(被不的物體,再在其背后繪制半透明物體,本來后面的半透明物體將不會(huì)被顯示(被不 void 感使用光照。在(111)處設(shè)置一個(gè)白色的光源。代碼如下 sicconstGLflo icconstGLflo icconst icconstition =1.0f, 1.0f,-1.0f, ight_ambient = 0.2f, 0.2f, 0.2f, ight_diffuse =1.0f,1.0f,1.0f,ight_specular=1.0f,1.0f,1.0f,glLightfv(GL_LIGHT0, ITION, glLightfv(GL_LIGHT0, GL_AMBIE

40、NT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); voidsetMatirial(constGLfloatmat_diffuse4,GLfloats icconstGLfloatmat_specular=0.0f,0.0f,0.0f,s icconstGLfloat=0.0f,0.0f,0.0f, glMaterialfv(GL_FRONT,GL_SPECULAR, , voidconst consts consticGLfloat red_color=1.0f,0.0f,0.0f,icGLfloatgre

41、en_color=0.0f,1.0f,0.0f,0.3333f; ic GLfloat blue_color = 0.0f, 0.0f, 1.0f, 0.5f; 以(00,0.5)為中心,繪制一個(gè)半徑為.3的不透明紅色球體(離觀察者最遠(yuǎn)setMatirial(red_color,30.0); glTranslatef(0.0f,0.0f,0.5f); glutSolidSphere(0.3,30,以(0.200.5)為中心,繪制一個(gè)半徑為.2的半透明藍(lán)色球體(離觀察者最近glutSolidSphere(0.2,30,以(0.100)為中心,繪制一個(gè)半徑為.15的半透明綠色球體glTransla

42、tef(0.1, 0, 0);glutSolidSphere(0.15,30,處 候,源顏色alpha值相當(dāng)于“10.第十課第十課、第十一課中的一個(gè)函數(shù)中的 buggrab 函數(shù)中, 應(yīng)該在最開頭加上一句息計(jì)算得到完整的息計(jì)算得到完整的圖象?!跋袼貓D”是將完整的圖分為若干的行、列,這些行列使得圖這兩種方法各有優(yōu)缺點(diǎn)。“矢量圖”在圖象進(jìn)行放大、縮小時(shí)很方便,不會(huì)失真,但如果圖象很復(fù)雜,那么就需要用非常多的幾何體,數(shù)據(jù)量和運(yùn)算量都很龐大。“像素圖”無論圖象多么復(fù)雜曾介紹了如何使用OpenGL 來繪制 16色或256色索引模式像素圖、24位真1/2 字節(jié),1 3 前最常見的是 MP 24 了像素保存

43、的幾種方法,包括不壓縮、RLE壓縮等。常見BMP文件大多是不壓縮的24 位色、不使用壓縮的BMP(如果你使用Windows 自帶的 24 位色不壓縮的BMP,所以文件 整數(shù),在文件中的地址分別0 x00120 x0016, / fseek(pFile,0 x0012, fread(&width,sizeof(width),1,pFile);fseek(pFile,0 x0016, 54 16 色或MP,則還有一個(gè)顏色24 MP 們這里不考慮。接下來就是實(shí)際的像素?cái)?shù)據(jù)了。24 位色BMP 文件中,每三個(gè)字節(jié)表示一個(gè)像eLBMPMP“對齊4417*5的24位P大小780,再加上文件開始54834字

44、節(jié)。分配內(nèi)存,不能直接使用“。 LineLengthImageWidth*while(LineLength%4!=0; / 。 LineLengthImageWidth*while(LineLength%4!=0; / 、繪制3、僅 則會(huì)依 色索引模式,則也可以使用 GL_COLOR_I 數(shù)據(jù)保存GLubyte,GL_FLOAT會(huì)把各種數(shù)據(jù)保存GLfloat 等RGB數(shù)據(jù),且每一數(shù)據(jù)被保存GLubyte,總大小就是:256*256*3 = 196608 用 文件格式相吻合了。即使你gl/gl.h頭文件中沒有定GL_BGR,也沒有關(guān)系,可以嘗試使Windows環(huán)境下OpenGL實(shí)現(xiàn)都GL_BGR

45、提供了支持,畢Windows中各種表示顏色的數(shù)據(jù)幾乎都是使BGRRGB的順序。這IBM-PC的硬件設(shè)計(jì) OpenGL也支持使用了這種“對齊”方式的像素?cái)?shù)據(jù)。只要通glPixelStore 修改“像素保存alignment = 4; 第一個(gè)參數(shù)表示“設(shè)置像素的對齊值”,第二個(gè)參數(shù)表示實(shí)際設(shè)置為多少。這里像素可以單字節(jié)對果長度不是四的倍數(shù),則補(bǔ)為四的倍數(shù)、八字節(jié)對齊。分別對alignment 的值1, 2, 4, 8。際上,默認(rèn)4,正好BMP 現(xiàn)在已經(jīng)可以把屏幕上的像到內(nèi)存了,如果需要的話還可以將內(nèi)存中的 54 個(gè)字節(jié),修改其中的寬度和高度信息,就可以得到新的文件頭了。假 FILE*pOrigin

46、File=fopen(dummy.bmp,rb); FILE* pGrabFile = fopen(grab.bmp, wb);char width, fread(BMP_Header,sizeof(BMP_Header),1, fseek(pGrabFile,0 x0012,fwrite(&width, sizeof(width), 1, pGrabFile); fseek(pGrabFile,0,fseek(pGrabFile,0 x0012,fwrite(&width, sizeof(width), 1, pGrabFile); fseek(pGrabFile,0, #defineWin

47、dowWidth #defineWindowHeight#includestdio#includestdlib#defineBMP_Header_LengthvoidFILE* FILE* GLubyte*GLubyte i,iWindowWidth*3; / 得到每一行的像素?cái)?shù)據(jù)長while(i%4!=0iWindowWidth*3; / 得到每一行的像素?cái)?shù)據(jù)長while(i%4!=0PixelDataLength=i*pPixelData=if(pPixelData=0pDummyFile=fopen(dummy.bmp, if(pDummyFile=0pWritingFile=fopen

48、(grab.bmp,if(pWritingFile=0 ixels(0,0,WindowWidth, 把dummy.bmp 的文件fread(BMP_Header,sizeof(BMP_Header),1, fseek(pWritingFile,0 x0012,i =j =fwrite(&i,sizeof(i),1,fwrite(&j,sizeof(j),1,fseek(pWritingFile,0, fwrite(&i,sizeof(i),1,fwrite(&j,sizeof(j),1,fseek(pWritingFile,0, 該#includegl/glutsic sic sic sic

49、 GLubyte* #includestdio void/ argc,char*FILE*pFile=fopen(Bliss.bmp,if(pFile= 0argc,char*FILE*pFile=fopen(Bliss.bmp,if(pFile= 0fseek(pFile,0 x0012, PixelLength=ImageWidth*while(PixelLength% 4!=0PixelLength*=PixelData=if(PixelData=0fseek(pFile,54,ixelData,PixelLength,1, ition(100, ition(100, return 于各

50、種 OpenGL 用 os*函數(shù)設(shè)置的“開始位置”不一定就是矩形的左下角)。 els 直接從像素?cái)?shù)操glCopyPixels 函數(shù)也通過glCopyPixels 函數(shù)也通過 用 示是GL_DEPTH或GL_STENCIL,分別表值得一提的是,glDrawPixels和 為 ndowWidth和WindowHeight是表示窗口寬度和高度的常量voidglColor3f(1.0f,0.0f, glColor3f(0.0f,1.0f, glColor3f(0.0f,0.0f, gtos2i(1, 像素、glDrawPixels繪制像素、 像素、glDrawPixels繪制像素、t11. 第十一課

51、的 但是這還不夠。雖可以將像素?cái)?shù)據(jù)按照矩形進(jìn)行縮小和放大,但是glPixelZoom 這樣的函數(shù)來進(jìn)放顯然是不夠的。OpenGL 紋功能支持將一些像素?cái)?shù)據(jù)經(jīng)過變換(即使是比較不規(guī)則的換)將其附著到各種形狀的多邊形表面。紋畫中的大多數(shù)效果,但是它也很復(fù)雜功能十分強(qiáng)大,利用它可以實(shí)現(xiàn)目前計(jì)算的完全講解。這里的課程只是關(guān)于 的 的 glEnable(GL_TEXTURE_2D啟用二維紋 用 ndowsBMP文件作為紋理時(shí),一般是藍(lán)色的像素在最前,其真實(shí)的格GL_BGR而不是 是 glGet egerv(GL_MAX_TEXTURE_SIZE, ixels glTexImage2D(GL_TEXTUR

52、E_2D,0,GL_RGB,width,height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,的圖象0.75M。把這些像素?cái)?shù)據(jù)從主內(nèi)存?zhèn)魉偷綄iT的圖形硬件,這個(gè)過程中還可能需當(dāng)在 ,則 需需, , 使用 用 , , glBegin(/*.*/glTexCoord2f(/*.*/); glVertex3f(/*.*/glTexCoord2f(/*.*/); glVertex3f(/*.*/*.當(dāng)?shù)奈恢脮r(shí),可以使glRo e*等函數(shù)來對坐標(biāo)進(jìn)行轉(zhuǎn)換用 講述)glRo e*,glScale*,glTranslate*等操作矩陣的函數(shù)就可以用來處理“對紋理坐標(biāo)進(jìn)使用 有 和 方式中

53、將被轉(zhuǎn)化為(1.0 , 為 , , 個(gè) 用 使用 為 指定為 。指定為 。 glGenTextures(/*.*/ , ); / , ); / 提示:紋理對象是OpenGL1.1版開始才有的,最舊版OpenGL1.0 OpenGL 的支持并不積極,Windows XP 1.1 Vista OpenGL 1.4 版。當(dāng)然了,如果安裝顯卡驅(qū)動(dòng)的話,現(xiàn)在的主流顯卡一般都附帶了適用于該顯卡的 OpenGL 1.4 版或更高版本),所以這個(gè)問題也就不算是問題了。編譯。如果要運(yùn)行的話,除了要保證有一個(gè)名稱為dummy.bmp,圖象大小為1*1的24位BMP文都轉(zhuǎn)成jpg 格式了,讀者 叫 1*1dummy

54、.bmp 文件仍然是必要的,參見第十課#defineWindowWidth #defineWindowHeight#defineWindowTitle OpenGL紋理測試#includegl/glut#includestdio#includestdlib#defineBMP_Header_LengthvoidFILE* FILE* GLubyte*GLubyte i,iWindowWidth*3; / 得到每一行的像素?cái)?shù)據(jù)長while(i%4!=0PixelDataLength=i*pPixelData=if(pPixelData=PixelDataLength=i*pPixelData=i

55、f(pPixelData=0pDummyFile= fopen(dummy.bmp,if(pDummyFile=0pWritingFile=fopen(grab.bmp,if(pWritingFile=0 ixels(0,0,WindowWidth, dummy.bmp 的文件 i =j =fwrite(&i,sizeof(i),1,fwrite(&j,sizeof(j),1, if(n= 0return return(n &(n-1) = * load_texture(constchar*width,height,GLubyte*pixels =last_texture_ID,texture

56、_ID=load_texture(constchar*width,height,GLubyte*pixels =last_texture_ID,texture_ID=FILE*pFile=fopen(file_name,if(pFile= 0return fseek(pFile,0 x0012,fread(&width,4,1,fread(&height,4,1, line_bytes =width*while(line_bytes % 4!= 0total_bytes= line_bytes *pixels=if(pixels =0return if(ixels,total_bytes, 1

57、,pFile) =0return return if(ixels,total_bytes, 1,pFile) |height maxconst new_width= const = new_line_bytes,GLubyte*new_pixels =new_line_bytes =new_width*while(new_line_bytes %4!=0new_line_bytes =new_width*while(new_line_bytes %4!=0new_total_bytes=new_line_bytes *new_pixels=if(new_pixels =0return pixe

58、ls=width = height = if(texture_ID =0return if(texture_ID =0return glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height, / return main 用 void void (75,1,1,gluLookAt(1, 5,5,0,0,0,0,0, glRo ef(-90, 0,0, argc,char*GLUT 初始 ition(100, texWall=return texWall=return 的 目前很多 OpenGL 的實(shí)現(xiàn)都還要求其值為 2 的整數(shù)次方,如果紋理圖象本身并不滿足

59、這個(gè)條件,可以使用 gluScaleImage 函數(shù)來進(jìn)行縮放。為了正確的使用紋理,需要設(shè)置紋理參數(shù)。幅紋理,則只在第一次使用前載入,以后不必重新載入。如果程序中要使用多幅紋理,不應(yīng)復(fù)載入它們,而應(yīng)該將每個(gè)紋理都用一個(gè)紋理對象來保存,并使用glBindTextures 在各個(gè)紋理之12. 用了 3這。); / glScissor(x,y,width, 還法可以保證像素只繪制到某一個(gè)特定的矩形區(qū)域內(nèi),這就是視口變換(在第五課第2、Alpha測 a測試。當(dāng)每個(gè)像素即將繪制時(shí),如果啟動(dòng)Alpha測試,OpenGL會(huì)檢查像素Alpha值,只有Alpha如,而這 glEnable(GL_ALPHA_TESTAlpha測 (小于則通過)GL_LEQUAL(小于過), GL_GEQUAL(大于等于則通 現(xiàn) 后可以WindowsXP自帶的畫圖工具打開,并另存24BMP格式 利用前面11 課的一段代碼Alpha值 voidtexture_colorkey(GLubyter, GLubyteg,GLubyteb,GLubytewidth,GLubyte*pixels = pixels=if(pixels =0 , pixels=if(pixels =0 , , / 分別表示i個(gè)像素的藍(lán)、綠、紅、Alpha四種分量,0表示最小

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論