好,就這樣定了?副標題爲“優化頂點數據”,這裏有一些算法上的建議用來"submit strip-ordered indexed triangles with per vertex data interleaved"。當蘋果給出這些建議的時候,他們通常有一些非常好的理由,讓我們看看如何使用它。
首先讓我們瞭解它的意思。讓我們把這句話分解開來:
Strip Ordered:換句話說,如果你的模型有相鄰的三角形,組成一個三角形帶提交而不是分別提交每一個三角形。我們早期教程講到過三角形帶,你應該多少知道一點該怎麼做。對於大多數物體來說你都可以使用這個方法,但不是所有時候都要用它。你什麼時候能夠使用?當你確定使用三角形帶可以有效減少推入OpenGL ES每幀的頂點數據的時候。
indexed:這裏仍然沒有什麼新內容。我們使用頂點索引有一段時間了。我們僅僅用12個頂點來創建旋轉的20面體。glDrawElements()是基於索引繪製而不是基於頂點。
見鬼,我們目前已經做的很棒了,不是嗎?我們眼下一直在做着正確的事情。讓我們來看最後一個建議,然而:
with per vertex data interleaved:好的,恩。。。。它到底是什麼意思?
好的,是時候考驗你的記憶力了。你還記得在過去幾個部分,也就是當我們討論glVertexPointer(),glNormalPointer(),glColorPointer(),glTexCoordPointer()的時候嗎?在前面的部分裏,我告訴你不用關注參數stride並把它設置爲0。
但是現在你要關注它(stride)了,因爲它是用來交叉存取每個頂點數據的關鍵。
Per Vertex Data
你也許想知道“per vertex data”是什麼,並且想知道如何交叉存取它。
你肯定知道,在OpenGL ES裏我們用頂點數組來表示幾何圖形,每一個數組包含3個定義頂點的GLfloat變量,來創造我們的物體。除了這些,我們有時也使用其它數據。舉例來說,如果我們用光效就需要頂點法線,我們不得不在法線數組裏定義每一個頂點的法線。如果我們使用紋理座標,我們不得不在紋理數組裏定義每一個頂點的紋理座標。如果我們用顏色數組,我們不得不指定每個點的顏色,你是否注意到我總是強調“per vertex data”?這些數據類型就是蘋果公司在它們技術說明裏提到的"per vertex data"。這就是你所有在OpenGL ES 中放入數組的任意一種適用於頂點的頂點數組。
Interleaving
這個系列到目前爲止,我們已經創造一個數組來存放頂點數據,並把它們與法線數據、顏色數據、紋理座標分開存在其他獨立數組中,像這樣:
我們將要學習如何把這所有的數據放在一起作爲一個整體數據來存儲:
如果你讀不懂上圖解裏面的代碼請不要擔心。 當那個變得重要的時候,我們會再次列出來講解的,這個給出的代碼列表僅僅是舉例說明在一個獨立的內存單元中我們可以存入所有的頂點數據。 我們所要做的只是把所有描述一個單一點的數據放在內存的同一個地方。
這樣做能夠使OpenGL快速的獲得讀取到每個頂點的信息。 在今天的例子裏面,我們要將交叉存儲頂點,法線,顏色(vertices, normals, color data),同樣的方法可以使用在紋理座標中,或者僅交叉存儲頂點和法線。事實上在一個Xcode工程裏面,會附帶着一些數據結構定義這三個交叉存儲的情況。
Defining a Vertex Node
爲了讓這個能夠工作起來,我們需要一個新的數據結構。下面的數據結構能夠讓我們把上面提到的頂點, 法線,顏色 交叉存儲到一起,
typedef struct {
Vertex3D vertex;
Vector3D normal;
Color3D color;
} ColoredVertexData3D;
啊哈哈,漂亮而簡潔不是嗎?你只用一個數據結構就包含了我們需要的一個頂點的所有屬性。
下一步,當然了,線面我們需要填充頂點數據,所以我們需要把三個static const數組合併成一個。這裏是相同的二十面體數據,指定使用了我們自己定義的新數據類型:
static const ColoredVertexData3D vertexData = ;
下面是我們如何傳遞信息到OpenGL。我們傳遞在這個數組裏面的每個數據成員的第一個頂點的地址,並且提供所傳遞的數據的長度大小作爲步長參數,而不是傳遞指針到合適的數組。
glVertexPointer(3, GL_FLOAT, sizeof(ColoredVertexData3D), &vertexData[0].vertex);
glColorPointer(4, GL_FLOAT, sizeof(ColoredVertexData3D), &vertexData[0].color);
glNormalPointer(GL_FLOAT, sizeof(ColoredVertexData3D), &vertexData[0].normal);
以上幾個方法中,最後一個參數調用了數據裏的第一個頂點,例如,&vertexData[0].color指向第一個頂點的顏色信息。stride(跨度)參數表明了在我們讀取下一個相同類型的數據時,我們要跳過多少比特的數據。如果你看了下面的圖解你也許就有那麼一點點感覺了(不好意思它有點寬,你需要適當的調整你的瀏覽器以便於看到這個圖解的所有部分)
變簡單了不是嗎?如果你一點也不喜歡打字,那麼你可以下載這個十二面的交叉存取版本spinning icosahedron。我也會使用新的數據類型更新我的OpenGL ES Xcode Template。
我們現在依然沒有使用triangle strips,但是混合三角形到triangle strips是下一步的教程,現在我要去參加WWDC了。
原文:iphonedevelopment,OpenGL ES from the Ground Up Part 8: Interleaving Vertex Data
iTyran翻譯討論地址:http://ityran.com/forum-36-1.html