1.顶点着色器中的颜色属性的输入问题
//***********************不使用顶点缓冲区对象时******************//
//设置顶点着色器中的颜色属性
GLfloat color[4 * 4] = {
1.0f, 0.0f, 0.0f, 1.0f, // c0
};
//顶点着色器读取颜色,这里的1对应顶点着色器中color对应的location
glVertexAttrib4fv(1, color);
//************************使用顶点缓冲区对象时******************//
GLfloat color[4 * 4] = {
1.0f, 0.0f, 0.0f, 1.0f, // c0
0.0f, 1.0f, 0.0f, 1.0f, // c1
0.0f, 0.0f, 1.0f, 1.0f // c2
};
//初始化操作,将颜色值读取到缓冲区对象中
glGenBuffers(3, userData->vboId);
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, color, GL_STATIC_DRAW);
//渲染图像时,从缓冲区洪读取数据操作
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[1]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
GL_ARRAY_BUFFER:标志指定的数组缓冲区对象用于创建保存顶点数据的缓冲区对象;
GL_ELEMENT_ARRAY_BUFFER:标志指定的元素数组缓冲区对象,用于创建保存图元索引的缓冲区对象;
GL_STATIC_DRAW:缓冲区对象数据将被修改一次,使用多次,以绘制图元或者指定图像;
GL_STATIC_READ:缓冲区对象数据将被修改一次,使用多次,以从opengl es读回数据;从opengl es读回的数据将从应用程序中查询;
GL_STATIC_COPY:缓冲区对象数据将被修改一次,使用多次,以从opengl es读回数据;从opengl es读回的数据将直接用作绘制图元或者修改图像信息的来源;
GL_DYNAMIC_DRAW:缓冲区对象数据将被重复修改,使用多次,以绘制图元或者指定图像;
GL_STREAM_DRAW:缓冲区对象数据将被修改一次,只使用少数几次,以绘制图元或者指定图像;
如果使用缓冲区模式来读取颜色值,那么颜色对应的数据大小必须和顶点数据大小一致(即假设有三个顶点,那么就必须有三个颜色与其对应,否则系统将自动默认颜色为黑色,补齐),这种操作会出现两个顶点的中间位置处出现颜色的渐变现象。
使用顶点缓冲区对象可以减少CPU和GPU之间复制的数据量,从而获得更好的性能。
opengl es 3.0推出了顶点数组对象(VAO),VAO提供包含在顶点数组/顶点缓冲区对象配置之间切换所需要的所有状态的单一变量;使用顶点缓冲区对象设置绘图操作需要多次调用glBindBuffer,glVertexAttribPointer,glEnableVertexAttribArray等,而VAO正是解决这个问题的,提高整体运行效率!!
//初始化部分
glGenBuffers(3, userData->vboId);
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 24, vertexPos, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 32, color, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->vboId[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 24, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &userData->vaoId);
glBindVertexArray(userData->vaoId);
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
glBindBuffer(GL_ARRAY_BUFFER, userData->vboId[1]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->vboId[2]);
//glDisableVertexAttribArray(0);
//glDisableVertexAttribArray(1);
glBindVertexArray(0);
//绘图部分
glBindVertexArray(userData->vaoId);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
glEnableVertexAttribArray:默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的,意味着数据在着色器端是不可见的,哪怕数据已经上传到GPU,由glEnableVertexAttribArray启用指定属性,才可在顶点着色器中访问逐顶点的属性数据。glVertexAttribPointer或VBO只是建立CPU和GPU之间的逻辑连接,从而实现了CPU数据上传至GPU。但是,数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。