我正在学习openGL,并试图理解VBO和VAO之间的关系。
据我所知,VBO是数据的缓冲区,就是这样。为了将该数据传递到OpenGL管道,我需要将VBO数据绑定到VAO。
这可以通过过多的glVertexAttrib*
函数来实现。
或者,您可以将VAO设置为通过一组glVertexArray*
函数自动从VBO上传数据,最后调用glEnableVertexArrayAttrib
。
现在,每当我更改一些VBO中的数据时,我所要做的就是在我的VAO上调用glBindVertexArray
以将数据从VBO上传到VAO。
右?
至少,这就是我理解会发生什么的方式。但是,当我尝试在代码中使用它时,我看不到预期的结果(屏幕周围出现三角形变形)。
以下是我创建VAO和VBO的代码:
void startup()
{
static const GLfloat positions[] =
{
1.00f, -0.25f, 0.0f, 1.0f,
1.00f, -0.25f, 0.0f, 1.0f ,
1.00f, -0.25f, 0.0f, 1.0f
};
m_renderingProgram = compile_shaders();
//Create VAO and VBO
glCreateVertexArrays(1, &m_VAO);
glCreateBuffers(1, &m_VBO);
//Set the VAO to automatically update it's data with VBO when it is bound
glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0);
glVertexArrayVertexBuffer(m_VAO, 0, m_VBO, 0, 4);
glVertexArrayAttribFormat(m_VAO, 0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(m_VAO, 0, 0);
glEnableVertexArrayAttrib(m_VAO, 0);
//Create a named buffer, so we can change the data within easily
glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT);
//Upload the data to the VAO
glBindVertexArray(m_VAO);
}
这是我的Update()函数代码:
void render(double currentTime)
{
const GLfloat red[] = { (float)sin(currentTime) * 0.5f + 0.5f,
(float)cos(currentTime) * 0.5f + 0.5f,
(float)sin(currentTime) * 0.5f + 0.5f,
1.0f };
const GLfloat newPosition[] =
{
sin(currentTime) * 1.00, sin(currentTime) * -0.25, 0.0, 1.0,
tan(currentTime) * 1.00, tan(currentTime) * -0.25, 0.0, 1.0 ,
cos(currentTime) * 1.00, cos(currentTime) * -0.25, 0.0, 1.0
};
const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glViewport(sin(currentTime) * 0.4f, cos(currentTime) * 0.5f, 800, 600);
glClearBufferfv(GL_COLOR, 0, black);
//Copy the new position to the buffer
glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition);
//Use the shader program program
glUseProgram(m_renderingProgram);
glVertexAttrib4fv(1, red);
//Update the VAO with the updated VBO
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
我希望看到的是一个三角形在屏幕周围变形并改变颜色,但我看到的是一个静态三角形改变颜色。
答案 0 :(得分:2)
据我所知,VBO是数据的缓冲区,而且全部都是。
buffer object是数据的缓冲区。术语" VBO"指的是(当前)用作顶点属性的源的缓冲区对象。 Buffer objects can be used for many other things,您可以通过多种不同的方式使用相同的缓冲区。
为了将该数据传递到OpenGL管道,我需要将VBO数据绑定到VAO。
技术术语是"附加"缓冲区对象为VAO。你"附上"一个对象到另一个;你"绑定" context 的对象。
现在我们已经制定了我们的术语,让我们谈谈代码出错的地方。
//Create a named buffer, so we can change the data within easily glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT);
你不能这样做。您已使用glNamedBufferStorage
为该缓冲区对象创建了存储空间。更重要的是,您为它创建了不可变存储。这意味着一旦为缓冲区对象创建了不可变存储,就无法返回并创建新存储。
哪个好;实际上,这条线是完全多余的,因为您已经创建了存储并上传到它。只需删除此冗余行。
//Copy the new position to the buffer glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition);
这是我们开始遇到更严重问题的地方。
请参阅,您创建了缓冲区的存储空间,如下所示:
glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0);
那个0有标志字段;它指定the ways in which you can modify the contents of the storage from the CPU(除其他外)。也就是说,不可变存储并不意味着您无法再将内容复制到其中。它只是意味着您无法重新分配存储空间。
但是你通过了0.这意味着你创建的缓冲区是完全静态的。您告诉OpenGL您不希望通过CPU进程更改缓冲区的内容。这对静态缓冲区来说很好,但这显然不是你想要的。
因此,您应该传递适当的标志而不是0。允许glNamedBufferSubData
工作的标记称为GL_DYNAMIC_STORAGE_BIT
。