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