顶点数组对象(Vertex Array Object 即VAO)是一个包含一个或数个顶点缓冲区对象(Vertex Buffer Object, 即 VBO)的对象,一般存储一个可渲染物体的所有信息。VAO的编号最多在0 to GL_MAX_VERTEX_ATTRIBS - 1.之间。
顶点缓冲区对象(Vertex Buffer Object VBO)是你显卡内存中的一块高速内存缓冲区,用来存储顶点的所有信息。
There is always a VAO bound to the context. The default VAO has the name 0 and is created along with the context, similar to textures 0 and framebuffer 0. When you bind a VAO, all the state stored in it will become active. Calls to glVertexAttribPointer, or glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...), modify the currently bound VAO.
一个VAO通常绑定到一个上下文中,默认的VAO编号是0,这个是随着上下文创建时而创建的,还有textures 0、framebuffer 0 。当你绑定一个VAO 它的所有的状态将会激活,调用glvertexAttribPointer 或者glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...),将会改变当前的绑定的VAO
VAO 对象
struct VertexAttributeState
{
bool bIsEnabled = false;
int iSize = 4; //This is the number of elements in each attrib, 1-4.
unsigned int iStride = 0;
VertexAttribType eType = GL_FLOAT;
bool bIsNormalized = false;
bool bIsIntegral = false;
void * pPtrOrBufferObjectOffset = 0;
BufferObject * pBufferObj = 0;
};
struct VertexArrayObjectState
{
BufferObject *pElementArrayBufferObject = NULL;
VertexAttributeState attributes[MAX_VERTEX_ATTRIB];
}
static VertexArrayObjectState *pContextVAOState = new VertexArrayObjectState();
static BufferObject *pCurrentArrayBuffer = NULL;
VertexArrayObjectState 中存储的就是一个VAO存储的所有状态。
void glBindBuffer(enum target, uint buffer)
{
BufferObject *pBuffer = ConvNameToBufferObj(buffer);
switch(target)
{
case GL_ARRAY_BUFFER:
pCurrentArrayBuffer = pBuffer;
break;
case GL_ELEMENT_ARRAY_BUFFER:
pContextVAOState->pElementArrayBufferObject = pBuffer;
break;
...
}
}
void glEnableVertexAttribArray(uint index)
{
pContextVAOState->attributes[index].bIsEnabled = true;
}
void glDisableVertexAttribArray(uint index)
{
pContextVAOState->attributes[index].bIsEnabled = false;
}
void glVertexAttribPointer(uint index, int size, enum type, boolean normalized, sizei stride, const void *pointer)
{
VertexAttributeState &currAttrib = pContextVAOState->attributes[index];
currAttrib.iSize = size;
currAttrib.eType = type;
currAttrib.iStride = stride;
currAttrib.bIsNormalized = normalized;
currAttrib.bIsIntegral = true;
currAttrib.pPtrOrBufferObjectOffset = pointer;
currAttrib.pBufferObj = pCurrentArrayBuffer;
}
从上面可以看出(glBindBuffer函数),GL_ARRAY_BUFFER 不是VAO的状态!,事实上连接属性索引和一个缓冲区的是glVertexAttribPointer.
This works just like any other state object. Allocated Vertex Array Objects will have their state set by these functions
上面这些工作原理和其他状态对象一样,分配的VAO将通过这些函数来用他们的状态集。
glDrawElements将会用你所设置的当前OpenGL的状态上下文来渲染你的物体。