一、前言
前面說了VBO和EBO。這里面會導(dǎo)致一個(gè)問題,當(dāng)頂點(diǎn)屬性不多的時(shí)候,直接使用VBO、EBO比較好,但是對于有很多頂點(diǎn)屬性的時(shí)候,太多的VBO會導(dǎo)致操作錯(cuò)誤。為此出現(xiàn)了VAO,頂點(diǎn)數(shù)組對象。

VAO
對于一個(gè)VAO,可以綁定多個(gè)VBO和一個(gè)EBO數(shù)據(jù)。這樣所有的操作就從EBO轉(zhuǎn)入到VAO了,便于操作和管理。
下面就看下VAO管理VBO的例子。
二、VAO的使用
- 1、創(chuàng)建VAO
glGenVertexArrays是創(chuàng)建VAO對象的句柄的方法。
GLES30.glGenVertexArrays(1,vaos,0);
- 2、創(chuàng)建VBO
將頂點(diǎn)和顏色數(shù)據(jù)放入到同一個(gè)數(shù)組triangleCoords中。
然后再創(chuàng)建一個(gè)VBO,將triangleCoords中的數(shù)據(jù)放入到VBO緩沖區(qū)中。
// 三維的頂點(diǎn)坐標(biāo),有方向的
private static final float triangleCoords[] = {
// 位置 // 顏色
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 頂部
};
// 創(chuàng)建VBO
int[] vbos = new int[1];
GLES20.glGenBuffers(vbos.length, vbos, 0);
vboId = vbos[0];
int[] ebos = new int[1];
GLES20.glGenBuffers(ebos.length, ebos, 0);
eboId = ebos[0];
// 綁定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//賦值
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,triangleCoords.length * 4,vertexBuffer,GLES20.GL_STATIC_DRAW);
//獲取頂點(diǎn)著色器的vPosition成員句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
- 3、VBO綁定到VAO中
在glBindVertexArray綁定到VAO中,后期執(zhí)行 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);這樣就把VBO依附于VAO中了。
因?yàn)轫旤c(diǎn)數(shù)據(jù)和顏色數(shù)據(jù)都存在同一個(gè)數(shù)據(jù)當(dāng)中,我們需要分別的處理,就需要偏移量。
下面的例子中,設(shè)置頂點(diǎn)句柄和顏色句柄的時(shí)候就分別的從緩存中讀取數(shù)據(jù)。
//準(zhǔn)備三角形的坐標(biāo)數(shù)據(jù)
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
24,0);
//啟用三角形頂點(diǎn)的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//設(shè)置繪制三角形的顏色
GLES20.glVertexAttribPointer(mColorHandle, 3,
GLES20.GL_FLOAT, false,
24,12);
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES30.glBindVertexArray(0);
三、代碼
代碼整合在github