请先阅读你好,三角形
OpenGL
中绘制一个图形的话大致分为以下几步
- 准备顶点数据
- 将数据送到GPU内存;
- 告诉
OpenGL
如何解析那段内存 - 绑定
VAO
- 构造着色器程序
- 绘制
根据想画的图形的形状来定义顶点,坐标系为[-1,1]之间
现在想画个三角形
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
上面的顶点数据是cpu内存里面的,要想把数据送到GPU
内存,需要用到VBO
unsigned int VBO;
glGenBuffers(1,&VBO);// 创建一个索引
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); // 将顶点数据放到GPU内存
上面只是在GPU
中开辟了一段内存空间,但是现在OpenGL
并不知道如何使用那段内存,由于在你好三角形中已经有了详细的解释,这里不做过多的解释了
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
内存本身没有任何意义,我们通过glVertexAttribPointer
赋予每隔一段内存以特殊的含义
OpenGL为了简化渲染部分的代码,引入了VAO
,它的结构如下,本来想重新画的,但是这张图已经画的很好了
使用如下
unsigned int VAO;
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
这个感觉没什么可说的,大家看下你好三角形
就能看懂了
- 顶点数组绘制
- 索引绘制
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
这个问题主要和VBO
和EBO
的存放位置有关,VBO
的数据和VAO
没有关系,尽管引入了VAO
,但是数据任然放在VBO
中,但是EBO
的数据是和VAO
是有关系的,可以理解为
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
伪代码的数据结构(实际上复杂的多,可以hooper查看下GLEngine(对应mac的/System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle)这个文件,我已经放到了02-基本图元绘制
文件夹下)
struct VertexArrayObject {
BufferObject *pElementArrayBufferObject = NULL;
VertexAttribute attributes[GL_MAX_VERTEX_ATTRIB];
}
而 glBindBuffer
方法类似与
void glBindBuffer(enum target, uint buffer) {
if (target == GL_ELEMENT_ARRAY_BUFFER) {
vao->pElementArrayBufferObject = pBuffer;
}
}
实际是操作VAO
中执行EBO
的数据的,所以不能在VAO
解绑之前解绑EBO
,也就是下面这段代码的解释
// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
如何在VAO
解绑之前解绑EBO
就相当于将vao->pElementArrayBufferObject = 0;
,所以到绘制的时候取得的vao->pElementArrayBufferObject
为0。
枚举值 | 含义 |
---|---|
GL_POINTS | 点 |
GL_TRAINGLES | 三角形 |
GL_LINE_STRIP | 线带 |
GL_LINE_LOOP | 循环线带 |
GL_TRAINGLE_STRIP | 连续填充三角形线带 |
GL_TRAINGLE_FAN | 以第一个顶点为中三角形线带 |
glPointSize(80.0f);
glUniform4f(location,0.0f,1.0f,0.0f,1.0f);
glDrawArrays(GL_POINTS,0,1);
glDrawArrays(GL_LINE_STRIP,1,6);
glUniform4f(location,0.0f,0.0f,1.0f,1.0f);
glDrawArrays(GL_LINE_LOOP,7,4);
三角形相关的请自行测试下
代码请参考Primitive_line_strip.cpp