资料来源: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取消以前缓冲区映射。