opengl es3.0学习篇四:顶点属性,顶点数组和缓冲区对象

资料来源: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指定的顶点属性加载数据。其中glVertexAttrib1fglVertexAttrib1fv会加载(x, 0.0, 0.0, 1.0),glVertexAttrib2fglVertexAttrib2fv会加载(x, y, 0.0, 1.0),glVertexAttrib3fglVertexAttrib3fv会加载(x, y, z, 1.0),glVertexAttrib4fglVertexAttrib4fv会加载(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指定的定点属性份量的顺序存储,即告诉程序对应每一个顶点的位置
//参数六:顶点数组

顶点缓冲区对象(VBOS)

当使用顶点数组的时候,顶点数据是保存在客户内存中(通常指cpu),在进行glDrawArray()或者glDrawElements()等绘图调用时候,这些数据会从客户内存复制到图形内存(指gpu)。**若是咱们没有必要再绘图调用时都复制顶点数据,则能够在图形内存中缓存这些数据,这种方法能够改善渲染性能,也会下降内存和电力的消耗。**这就是顶缓冲区对象的意义。.net

顶点缓冲区对象让opengl es应用程序在图像内存中分配和缓存数据,而且在这个内存中渲染,避免每次绘制图元时候从新发送数据

3.0中支持两类缓冲区对象,用于指定顶点和图元数据:

  • **数组缓冲区对象。**标识GL_ARRAY_BUFFER指定数组缓冲区对象用于建立保存顶点数据的缓冲区对象
  • **元素数组缓冲区对象。**GL_ELEMENT_ARRAY_BUFFER标识指定的元素数组缓冲区对象用于建立保存图元索引的缓冲区对象。

数组缓冲区用于保存一个或者多个图元的顶点属性数据,而元素数组缓冲区对象保存了一个或者多个图元的索引,以数组缓冲区作例子:

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之间复制的数据量,从而得到更好的性能。

顶点数组对象(VAO)

这个特性是在opengl es3.0 中引入的,提供包含在顶点数组/顶点缓冲区对象配置之间切换所须要的全部状态的单一对象.只须要在设置缓冲区数据的时候glGenVertexArrays一个顶点数组对象ID,而后调用glBindVertexArray绑定已经生成数组对象的ID,在绘制图元的时候调用glBindVertexArray切换相应缓冲区内的数据并进行绘制.glDeleteVertexArray删除一个或者多个顶点数组对象.

映射缓冲区对象

应用程序设置缓冲区对象数据调用glBufferData的时候,能够将缓冲区对象数据存储映射到应用程序的内存地址空间,优势:减小应用程序的内存占用,只须要存储数据的一个副本.避免数据复制步骤经过映射出的GPU存储缓冲区对象的内存地址. 调用glMapBufferRange返回缓冲区存储数据范围的指针,出现错误则反悔NULL,glUnmapBuffer取消以前缓冲区映射。

相关文章
相关标签/搜索