1. OpenGL ES 2.+ 流程中,每次绘制时数据操作都有如下流程:
sharder代码中已定义顶点坐标和纹理坐标变量,并在GLES代码获取其变量location:posLoc、texLoc;
顶点着色器代码:
"attribute vec4 aPosition;\n" + // 顶点坐标
"attribute vec4 aTextureCoord;\n" + // 纹理坐标
GLES代码:
int positionLoc = GLES20.glGetAttribLocation(wrapper.cameraProgramId, "aPosition");
int textureCoordLoc = GLES20.glGetAttribLocation(wrapper.cameraProgramId, "aTextureCoord");
绘制时:
- 设置顶点坐标VA location: glVertexAttribPointer(positionLoc, size, type, normalized, stride, data);
- 设置纹理坐标VA location: glVertexAttribPointer(textureCoordLoc, size, type, normalized, stride,data);
GLES20.glEnableVertexAttribArray(positionLoc);
GLES20.glEnableVertexAttribArray(textureCoordLoc);- 设置shader location参数
- 设置绘制索引数据(indices)引并绘制图像: glDrawElements(mode, indicesSize, type, indicesBuffer)
2.使用VAO优化绘制流程
VBO将顶点信息放到GPU中,GPU在渲染时去缓存中取数据,二者中间的桥梁是GL-Context。GL-Context整个程序一般只有一个,所以如果一个渲染流程里有两份不同的绘制代码,GL-context就负责在他们之间进行切换。这也是为什么要在渲染过程中,在每份绘制代码之中会有glBindbuffer、glEnableVertexAttribArray、glVertexAttribPointer。那么优化的方法来了,把这些都放到初始化时候完成吧!VAO记录该次绘制所需要的所有VBO所需信息,把它保存到VBO特定位置,绘制的时候直接在这个位置取信息绘制。
VAO的全名是Vertex Array Object,首先,它不是Buffer-Object,所以不用作存储数据;其次,它针对“顶点”而言,也就是说它跟“顶点的绘制”息息相关。(VAO和VA没有任何关系)
VAO记录的是一次绘制中所需要的信息,这包括“数据在哪里glBindBuffer”、“数据的格式是怎么样的glVertexAttribPointer”、shader-attribute的location的启用glEnableVertexAttribArray。
OpenGL ES 3.+ 中, 使用VAO (VertexArrayObject)绑定VBO(VertexBufferObject)、EBO(ElementBufferObject,另作IBO,IndexBufferObject)的绘制流程:
sharder代码中,定义顶点坐标和纹理坐标变量及其变量location序号,并在GLES代码中通过location序号绑定到VAO内的VBO上
顶点着色器代码:
layout (location = 0) in vec3 aPos; //opengl世界点坐标
layout (location = 1) in vec2 aTexCoord; //opengl纹理坐标
GLES代码
初始化 :
// 1.创建VAO(顶点数组对象)、VBO(顶点数据对象)、EBO(索引数据对象)
GLES32.glGenVertexArrays(,vao,);
GLES32.glGenBuffers(,vbo,);
GLES32.glGenBuffers(,ebo,);
// 绑定VAO并设置VBO、EBO数据,绑定VBO到顶点坐标location和纹理坐标location
GLES32.glBindVertexArray(vao);
// 绑定顶点VBO,类型为GL_ARRAY_BUFFER
GLES32.glBindBuffer(GLES32.GL_ARRAY_BUFFER, vbo);
GLES32.glBufferData(GLES32.GL_ARRAY_BUFFER, vertices.length * Float.BYTES, BufferUtils.floatToBuffer(vertices), GLES32.GL_STATIC_DRAW);
// 绑定索引EBO,类型为GL_ELEMENT_ARRAY_BUFFER
GLES32.glBindBuffer(GLES32.GL_ELEMENT_ARRAY_BUFFER, ebo);
GLES32.glBufferData(GLES32.GL_ELEMENT_ARRAY_BUFFER, index.length * Integer.BYTES, BufferUtils.intToBuffer(index), GLES32.GL_STATIC_DRAW);
// 按location序号绑定并启用VBO到顶点坐标VA location和纹理坐标VA location
GLES32.glVertexAttribPointer(0, 3, GLES32.GL_FLOAT, false, 5 * Float.BYTES, 0);
GLES32.glEnableVertexAttribArray(0);
GLES32.glVertexAttribPointer(1, 2, GLES32.GL_FLOAT, false, 5 * Float.BYTES, 3 * Float.BYTES);
GLES32.glEnableVertexAttribArray(1);
// 解除VAO绑定
GLES32.glBindVertexArray(0);
// 重置VBO,EBO
GLES32.glBindBuffer(GLES32.GL_ARRAY_BUFFER, 0);
GLES32.glBindBuffer(GLES32.GL_ELEMENT_ARRAY_BUFFER, 0);
绘制时 :
- 绑定VAO(VAO包含了当前绘制所需的信息):
glBindVertexArray- 设置 sharder location参数
- 绘制图像:
glDrawElements(mode, indicesSize, type, offset)- 解绑VAO:
glBindVertexArray(0)
参考: https://www.cnblogs.com/BigFeng/p/5117311.html