iOS開發(fā)OpenGL ES教程(1)構(gòu)成復(fù)雜物體基本繪圖要素
圖元是構(gòu)成復(fù)雜物體的基本繪圖要素。在OpenGL ES中,你可以使用的圖元有點(diǎn),線,三角形。它們都有非常強(qiáng)的自我解釋性,我覺得你需要有些例子讓你看到它們。
首先,讓我們來看看一些代碼,然后我們可以談?wù)撨@是怎么回事,這樣您就可以使用它來創(chuàng)建一些自己的代碼。
三角形是最“復(fù)雜”的圖元,但是很容易使用,并且非常實用,這將是你可以繪制的第一個OpenGL的圖元。當(dāng)我們繪制一個三角形的時候,我們需要告訴OpenGL在3d空間中的三角形的3系坐標(biāo),并且,OpenGL將非常順利的渲染這個三角形。
在開始之前,復(fù)制00教程中的項目代碼或者從這里下載下項目代碼: AppleCoder-OpenGLES-00.tar.gz .在XCode中打開,開啟EAGLView.m文件,找到drawView函數(shù)。這里就是施展魔法的地方。
首先,我們需要定義一個三角形。要做到這點(diǎn),我們需要知道在我們要處理的坐標(biāo)的兩種類型:模型和世界。模型坐標(biāo)是指我們正在繪制的實際圖元,世界坐標(biāo)告訴OpenGL觀察者在哪里。(在世界坐標(biāo)中,觀察者一般在(0.0,0.0,0.0)的地方)
第一個例子將說明這點(diǎn)。首先,我們定義這個三角形在模型空間使用3 x 3d 坐標(biāo)(x,y,z):
- const GLfloat triangleVertices[] = {
- 0.0, 1.0, -6.0,// Triangle top centre
- -1.0, -1.0, -6.0,// bottom left
- 1.0, -1.0, -6.0,// bottom right
- };
如上所示,這里使用了3個坐標(biāo)來表示一個三角形,需要注意的是,我們定義三角形頂點(diǎn)是逆時針來顯示的。雖然描述三角形的可以用逆時針也可以用順時針,但是 我們必須和上述一樣用逆時針來描述三角形。不過,我建議你用逆時針來描述三角形,因為我們以后可以用逆三角形來達(dá)到一些先進(jìn)的功能。
(補(bǔ)充:逆三角形在3d中被認(rèn)為是正面,而順三角形則被認(rèn)為是反面。在紋理渲染中被使用到)
雖然本教程應(yīng)該是純粹的iPhone OpenGL ES的,對于初學(xué)者來說,我會簡要的描述三維坐標(biāo)系統(tǒng)??纯催@張圖片:
對于我的繪畫技巧,我深表遺憾。不過這個圖代表了模型空間和世界空間。 試想一下,這是您的計算機(jī)屏幕, X和Y的橫向和縱向的,你應(yīng)該預(yù)料到, Z表示深入。這個中心位置就是(0.0,0.0,0.0).
所以,看我們的三角形中所描述的頂點(diǎn)上述情況,第一點(diǎn)( 0.0 , 1.0 , -6.0 )中心將在的Y軸,上漲1點(diǎn),在屏幕的深度為6點(diǎn)。 第二個坐標(biāo)是右邊的Y軸1.0點(diǎn),低于X軸(因此-1.0的Y值) ,仍然回到屏幕-6.0點(diǎn)。這同樣適用于第三個坐標(biāo)。
為此,我們確定目標(biāo)在我們眼睛之前(z值是負(fù)的),所以這個目標(biāo)是可見的(記得嗎,觀察者或者說照相機(jī)是在(0.0,0.0,0.0)的位置上)所以說OpenGL的深度測試是失敗的并且它沒有被渲染。
我可以聽到你尖叫“嘿,我還以為你說,這是模型坐標(biāo)不是世界坐標(biāo)! ” 。 是的,這是對的,但是,當(dāng)我們?nèi)ヤ秩具@個三角形之前, OpenGL的將只是把對象放在( 0.0 , 0.0 , 0.0 ) 的位置上。 因此,我們將它放到屏幕內(nèi)才可見。 當(dāng)我們進(jìn)入轉(zhuǎn)換(移動,旋轉(zhuǎn)等) ,您會看到,您將不必設(shè)置對象Z值為負(fù),也可以使之可見。在此之前,讓目標(biāo)的Z坐標(biāo)在-6.0的位置上。
繪制函數(shù):
所以我們這樣做是為了說明目前的三角形。我們現(xiàn)在需要告訴OpenGL,數(shù)據(jù)保存在哪里,以及如何去繪制它。這個過程只需要很少的幾行代碼?;氐絛rawView函數(shù),并且實行以下的代碼:
- - (void)drawView {
- const GLfloat triangleVertices[] = {
- 0.0, 1.0, -6.0, // Triangle top centre
- -1.0, -1.0, -6.0, // bottom left
- 1.0, -1.0, -6.0 // bottom right
- };
- [EAGLContext setCurrentContext:context];
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
- glViewport(0, 0, backingWidth, backingHeight);
- // -- BEGIN NEW CODE
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- // -- END NEW CODE
- glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
- [context presentRenderbuffer:GL_RENDERBUFFER_OES];
- [self checkGLError:NO];
- }
如你所見,這4行代碼就是我們渲染一個三角形的。讓我們從上往下一行行的打斷這些代碼來分析,你會發(fā)現(xiàn)它們是非常的簡單。
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
這行代碼只是簡單的清除了屏幕。這個控制位告訴OpenGL,我們使用上次教程里面setupView函數(shù)中設(shè)置的顏色(黑色)來清除屏幕,并且清除了深度 緩沖。 請注意,如果我們沒有創(chuàng)建深度緩沖和開啟深度緩沖(如我們應(yīng)該做的),這個屏幕將不會渲染。如果我們不使用深度緩沖,我們將不需要通過glClear() 里的 GL_DEPTH_BUFFER_BIT.
因此,我們無論是清除以前繪制的這個緩沖區(qū)(請記住,這是雙重緩沖動畫;利用一個緩沖區(qū)而另一個緩沖區(qū)顯示) 。
- glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
此函數(shù)告訴OpenGL的情況下我們的數(shù)據(jù)是什么格式,它是有4個參數(shù),這個功能是很簡單細(xì)分:
1.Size-這個值表示了每個坐標(biāo)有幾個數(shù)字。我們現(xiàn)在是3,是因為是3d坐標(biāo)(x,y,z).如果我們使用2d繪制,不加入深度(就是z),我們只要在這里寫2就可以了。
2.Data Type- GL_FLOAT 意味著我們用float點(diǎn)值。 您也可以使用整數(shù)值,但如果你想你需要習(xí)慣于使用浮點(diǎn)值的3D世界的浮點(diǎn)運(yùn)算。
3.Stride - 這個stride告訴OpenGL 在每個坐標(biāo)之間忽略哪幾個點(diǎn)。別對這個表示疑惑,保持它是0就行了。你使用它
當(dāng)您載入頂點(diǎn)數(shù)據(jù)文件的格式有更多的填充數(shù)據(jù)或膚色的數(shù)據(jù),也就是說,一個3D程序像攪拌機(jī)。
4.Pointer to the Data – 數(shù)據(jù)本身,正是因為它,三角形才會出現(xiàn)。
因此,我們告訴OpenGL清除緩沖區(qū),告訴它的數(shù)據(jù)是我們的目標(biāo)和它的格式,現(xiàn)在我們需要告訴OpenGL的東西很重要:
- glEnableClientState(GL_VERTEX_ARRAY);
OpenGL 是一個狀態(tài)機(jī)。 這意味著你打開和關(guān)閉功能的要求就是啟用和禁用命令。之前,我們使用過glEnable(),這影響到OpenGL的服務(wù)。 glEnableClientState ()影響到我們的程序方面(就是客戶端面)。所以我們要做的就是告訴OpenGL我們頂點(diǎn)數(shù)據(jù)是一個頂點(diǎn)數(shù)組并且轉(zhuǎn)換到OpenGL的繪制頂點(diǎn)功能。在這 個情況下,頂點(diǎn)可以是一個顏色數(shù)組,我們將呼叫 glEnableClientState (GL_COLOR_ARRAY)或者一個紋理坐標(biāo)數(shù)組如同紋理映射。(別垂涎三尺,你需要掌握所有的基本知識包括紋理映射)
隨著我們進(jìn)一步的研究OpenGL ,我們會使用不同的客戶端狀態(tài),這將使用變得更為清晰。
現(xiàn)在命令OpenGL渲染一個三角形。
- glDrawArrays(GL_TRIANGLES, 0, 3);
一旦這個方法被調(diào)用,OpenGL將用我們之前的兩個函數(shù)的信息開始執(zhí)行。屏幕中間出現(xiàn)一個白色的實心的三角形(白色是默認(rèn)的繪制顏色)?,F(xiàn)在的三角形是一個實心的,如果你需要一個鏤空的三角形,你將要用不同的繪制方法。
分析這個方法里的三個參數(shù):
1.Drawing Method- 在這種情況下,我們已通過GL_TRIANGLES這似乎相當(dāng)明顯,因為我們畫一個三角形。然而,這一方法的第一個參數(shù)將變得很明顯,當(dāng)我們使用此功能,來繪制一個平面體。
2.First Vertex- 我們陣列只有3點(diǎn),所以我們想要的OpenGL提請第一坐標(biāo)的數(shù)組,這里指定零就像進(jìn)入一個標(biāo)準(zhǔn)數(shù)組。 如果我們有多種原始的頂點(diǎn)數(shù)組,我們可以在這里處理。我會在以后的教程教你,當(dāng)我告訴您該如何建立復(fù)雜的物體的時候?,F(xiàn)在,這里只要使用0。
3.Vertex Count-這將告訴OpenGL在我們的數(shù)組中有多少頂點(diǎn)需要被繪制。比如說,我們繪制一個三角形,所以至少要3點(diǎn),一個平方形需要4點(diǎn),一個線需要2點(diǎn)(或更多),一個點(diǎn)需要一個(或者多點(diǎn))
當(dāng)你把這些代碼都輸入到你的drawView函數(shù)里面以后。點(diǎn)擊“Build and Go”運(yùn)行這個程序在模擬器里面。你的模擬器應(yīng)該看起來象如下的圖:
如我們所說的,有一個實心的白色的三角形出現(xiàn)在屏幕的中間。
在我們做其他的圖元之前,嘗試修改z值,你就會明白我所說的是什么意思。如果你把z改為0,你將什么也看不到。
如果你自己輸入幾行代碼,我希望你可以來發(fā)現(xiàn)OpenGL ES 是如何工作的。如果你學(xué)習(xí)過“標(biāo)準(zhǔn)”的OpenGL的教程,我希望你可以發(fā)現(xiàn)OpenGL與OpenGL ES的不同。
期待。。。
下個教程將著重于擴(kuò)大代碼量并生產(chǎn)一個平方形。