作者:星隕
來源
音視訊開發進階 回顧一下之前提到的繪制類型: 假設要繪制一個立方體,以GL_TRIANGLES
的類型進行繪制,那麼六個面,每個面由兩個三角形組成,就得向渲染管線傳入 36 個頂點,36 個頂點按照順序進行繪制,而實際上,一個矩形也就才 8 個頂點而已。
為了優化繪制的效率,減少資料的傳遞,于是就有了
glDrawElements
繪制方法。 glDrawElements 繪制方法
glDrawElements
方法還是需要傳遞頂點資料,但隻需要傳遞物體實際上的頂點資料,也就是最少的,不重複的頂點資料。
然後再向渲染管線傳遞要繪制的頂點資料的索引,根據索引從頂點資料中取出對應的頂點,然後再按照指定的方式進行繪制。
如下圖所示,圖檔截自《OpenGL ES 3.x 遊戲開發上卷》:
由三個三角形組成的倒置的梯形,實際上隻有五個頂點
,是以也隻傳遞了五個頂點,接下來就是确定這個五個頂點的索引順序。
索引順序和我們要繪制的方式有很大的關系,不同繪制方式的索引順序不同。
采用
GL_TRIANGLE_STRIP
的類型繪制,那麼索引順序就是
。
具體方法調用情況代碼:
1 // 函數原型
2 public static native void glDrawElements(
3 int mode, // 繪制方式
4 int count, // 繪制數量
5 int type, // 索引的資料類型
6 java.nio.Buffer indices // 索引緩沖
7 );
8 // 定義頂點的索引資料
9 private byte[] front = {
10 // 前面索引
11 0, 1, 2, 3
12 };
13 // 索引資料傳遞到緩沖區
14 private ByteBuffer frontBuffer = ByteBuffer.allocateDirect(indices.length *Constants.BYTES_PRE_BYTE)
15 .put(indices)
16 frontBuffer.position(0)
17 // glDrawElements 繪制
18 GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,front.size,GLES20.GL_UNSIGNED_BYTE, frontBuffer)
19 // glDrawArrays 繪制
20 // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
在函數原型中定義了要傳入的參數,根據要繪制的方法和索引緩沖區,找到對應的點進行繪制。
對于繪制時有重複點,采用這種方式,就可以減少向渲染管線中傳遞重複的點了。
而且,在定義一個頂點時,大都是
float
類型,它是四個位元組,而對于繪制量比較小,頂點數量在
byte
所能表達整數範圍内,可以采用
byte
類型定義索引順序,它隻占一個位元組,減少了記憶體的使用。
glDrawElements 和 glDrawArrays 的對比
glDrawElements
方法的
count
的參數定義了要取多少個索引出來繪制,而且這個繪制是連續的,必須要把
count
數量的頂點繪制完。
這裡就有一個很有意思的地方了,有一些小遊戲是這樣的:要求一筆繪制完一個形狀,而且不允許交叉。
比如,要求一筆繞過立方體的六個面,而且不允許交叉,這就很難做到的了。
而使用
glDrawElements
方法同樣會這樣,采用索引不能一次不交叉的把圖形全部繪制完,得采取兩次繪制。
比如在實踐繪制一個立方體時,采用了如下的方式:
1 // 前面索引
2 private byte[] front = {0, 1, 2, 3};
3 // 後面索引
4 private byte[] back = { 4, 5, 6, 7};
5 // 上面索引
6 private byte[] top = {0, 1, 4, 5};
7 // 下面索引
8 private byte[] bottom = { 2, 3, 6, 7};
9 // 左面索引
10 private byte[] left = {0, 4, 2, 6};
11 // 右側索引
12 private byte[] right = {1, 5, 3, 7};
把立方體分解成了六個面的内容進行繪制,也就是采用了六個索引緩存。
而對于使用
glDrawArrays
的方式,可以一次性把所有頂點傳到渲染管線,并且可以選擇繪制的開始和結尾點,這樣就隻要一個緩沖區就好了,不過代碼就是要多占用記憶體空間了。
是以說,能用 glDrawElements 方式的還是要采用的。
具體代碼詳情,可以參考我的 Github 項目:
https://github.com/glumes/AndroidOpenGLTutorial OpenGL 系列文章:「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。