vao 是vertex array object, 从名字上看,是顶点数组的对象
其创建是glGenVertexArrays(1, &mTriangleVao); 这样的方式创建的
vbo 是 vertex buffer object, 其是具体数据(buffer)的对象,
通过glGenBuffers(1, &mPosVbo) 类似这样的方式创建
vbo是绑在vao上的,一个vao可以绑定多个vbo
比如,为一个三角形创建一个vao, 然后为这个vao绑定具体的vbo,
一个vbo负责存储顶点数据,一个vbo存储颜色数据
glGenVertexArrays(1, &mTriangleVao); glBindVertexArray(mTriangleVao); glGenBuffers(1, &mPosVbo); glBindBuffer(GL_ARRAY_BUFFER, mPosVbo); glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(m_posAttr, 4, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(m_posAttr); glGenBuffers(1, &mColVbo); glBindBuffer(GL_ARRAY_BUFFER, mColVbo); glBufferData(GL_ARRAY_BUFFER,sizeof(colors), colors, GL_STATIC_DRAW); glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(m_colAttr); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0);
这么搞的好处在于,我们在每一帧去draw的时候:
使用vao就可以直接绑定 vao 就行
glBindVertexArray(mTriangleVao); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0);
否则,就要按照以往的那种做法,非常麻烦,而且会有性能问题,因为这样会导致CPU不断的向GPU同步数据
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors); glEnableVertexAttribArray(m_posAttr); glEnableVertexAttribArray(m_colAttr); glDrawArrays(GL_TRIANGLES, 0, 3);//0是顶点数组的起始索引,3是我们打算绘制多少个顶点 glDisableVertexAttribArray(m_colAttr); glDisableVertexAttribArray(m_posAttr);
========================================================================================================
update @ 2021.8.30
========================================================================================================
继续深入的学习一下VBO
我们通过glBufferData给到vbo的数据,其实是把用户的在DDR中的数据复制到GPU的专用内存中(也就是显存)
最后一个参数指定了我们希望显卡如何管理给定的数据
GL_STATIC_DRAW :数据不会或几乎不会改变。
GL_DYNAMIC_DRAW:数据会被改变很多。
GL_STREAM_DRAW :数据每次绘制时都会改变
我们通过顶点缓冲对象(Vertex Buffer Objects, VBO)管理这个内存,它会在GPU内存(通常被称为显存)中储存大量顶点。使用这些缓冲对象的好处是我们可以一次性的发送一大批数据到显卡上,而不是每个顶点发送一次。从CPU把数据发送到显卡相对较慢,所以只要可能我们都要尝试尽量一次性发送尽可能多的数据。当数据发送至显卡的内存中后,顶点着色器几乎能立即访问顶点,这是个非常快的过程。