資料來源:html
OpenGL ES3.0編程指南java
https://www.cnblogs.com/gaofengworking/p/4943204.htmlc++
https://blog.csdn.net/tianxiawuzhei/article/details/46639553編程
頂點數據也稱做頂點屬性,指定每一個頂點的數據。這種逐頂點數據能夠爲每一個頂點指定,也能夠用於全部的頂點的常量。數組
想要繪製一個固定顏色的三角形,能夠指定一個常量用於三角形的所有三個頂點緩存
常量頂點屬性對於一個圖元的全部頂點都相同,因此對一個圖元的全部頂點只須要採用一個值:ide
void glVertexAttrib1f(GLuint index, GLfloat x); void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y); void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void glVertexAttrib1fv(GLuint index, const GLfloat * values); void glVertexAttrib2fv(GLuint index, const GLfloat * values); void glVertexAttrib3fv(GLuint index, const GLfloat * values); void glVertexAttrib4fv(GLuint index, const GLfloat * values);
上面這些命令用來給由index指定的頂點屬性加載數據。其中glVertexAttrib1f和glVertexAttrib1fv會加載(x, 0.0, 0.0, 1.0),glVertexAttrib2f和glVertexAttrib2fv會加載(x, y, 0.0, 1.0),glVertexAttrib3f和glVertexAttrib3fv會加載(x, y, z, 1.0),glVertexAttrib4f和glVertexAttrib4fv會加載(x, y, z, w)。在實際中,常量頂點屬性提供了和使用標量/向量統一變量等價的功能,二者均可以選用。性能
頂點數組指定每一個頂點的屬性,是保存在應用程序地址空間的緩衝區。頂點數組用glVertexAttribPointer()
或者glVertexAttribIPointer()
來指定:ui
GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES30.GL_FLOAT, false, vertexStride, vertexBuffer); //參數一:通用屬性的句柄,在上個demo中指的是mPositionHandle //參數二,指的是一個頂點的屬性包含的size的值,在demo中設置爲3 //參數三:數據格式,與數組的type一致 //參數四:標識非浮點數據在轉換成浮點時是否規範化 //參數五:每一個頂點由size指定的定點屬性份量的順序存儲,即告訴程序對應每一個頂點的位置 //參數六:頂點數組
當使用頂點數組的時候,頂點數據是保存在客戶內存中(通常指cpu),在進行glDrawArray()
或者glDrawElements()
等繪圖調用時候,這些數據會從客戶內存複製到圖形內存(指gpu)。**若是咱們沒有必要再繪圖調用時都複製頂點數據,則能夠在圖形內存中緩存這些數據,這種方法能夠改善渲染性能,也會下降內存和電力的消耗。**這就是頂緩衝區對象的意義。.net
頂點緩衝區對象讓opengl es應用程序在圖像內存中分配和緩存數據,而且在這個內存中渲染,避免每次繪製圖元時候從新發送數據
3.0中支持兩類緩衝區對象,用於指定頂點和圖元數據:
數組緩衝區用於保存一個或者多個圖元的頂點屬性數據,而元素數組緩衝區對象保存了一個或者多個圖元的索引,以數組緩衝區作例子:
private void createVertextBuffer(){ int[] value = new int[1]; GLES30.glGenBuffers(1, value,0); GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, value[0]); GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexBuffer.position(),vertexBuffer,GLES30.GL_STATIC_DRAW); }
glGenBuffers()
用來獲取未使用的緩衝對象,其中參數一標識須要返回的緩衝對象數量,參數二標識返回分配的緩衝對象的位置句柄。注意:glGenBuffers()返回的句柄是0之外的無符號整數,0值由opengl es保留
glBindBuffer()
用於指定當前緩衝區對象,參數一使用GL_ARRAY_BUFFER
或者GL_ELEMENT_ARRAY_BUFFER
來標識緩衝對象,參數二表示須要使用的緩衝區對象句柄。glBufferData()
用來綁定緩衝區數據,參數一與上相同,參數二標識緩衝區的數據存儲大小(以字節數表示),,參數三爲數據,參數四爲使用緩衝區存儲的數據對象的提示。若是參數三是一個有效數據,則內容會被複制且分配到緩衝區對象中。在Android中的使用(居於http://www.javashuo.com/article/p-rapaesnz-kq.html Demo改進):
private void createVertextBuffer(){ int[] value = new int[1]; GLES30.glGenBuffers(1, value,0); GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, value[0]); GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexBuffer.capacity()*4,vertexBuffer,GLES30.GL_STATIC_DRAW); } public void onDraw(){ // Add program to OpenGL ES environment GLES30.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition"); createVertextBuffer(); // Enable a handle to the triangle vertices GLES30.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES30.GL_FLOAT, false, 0, 0);//這裏注意最後兩個參數須要改爲0,0標明不從cpu中拿數據了,從gpu拿數據,因此方法是不同的 // get handle to fragment shader's vColor member mColorHandle = GLES30.glGetAttribLocation(mProgram, "aColor"); // Set color for drawing the triangle GLES30.glVertexAttrib4fv(mColorHandle, color, 0); // Draw the triangle GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexCount); // Disable vertex array GLES30.glDisableVertexAttribArray(mPositionHandle); }
總而言之,使用頂點緩衝區對象可以減小cpu和gpu之間複製的數據量,從而得到更好的性能。
這個特性是在opengl es3.0 中引入的,提供包含在頂點數組/頂點緩衝區對象配置之間切換所須要的全部狀態的單一對象.只須要在設置緩衝區數據的時候glGenVertexArrays一個頂點數組對象ID,而後調用glBindVertexArray綁定已經生成數組對象的ID,在繪製圖元的時候調用glBindVertexArray切換相應緩衝區內的數據並進行繪製.glDeleteVertexArray刪除一個或者多個頂點數組對象.
應用程序設置緩衝區對象數據調用glBufferData的時候,能夠將緩衝區對象數據存儲映射到應用程序的內存地址空間,優勢:減小應用程序的內存佔用,只須要存儲數據的一個副本.避免數據複製步驟經過映射出的GPU存儲緩衝區對象的內存地址. 調用glMapBufferRange返回緩衝區存儲數據範圍的指針,出現錯誤則反悔NULL,glUnmapBuffer取消以前緩衝區映射。