gpt4 book ai didi

c++ - glBindVertexArray 时 VAO 未更新

转载 作者:行者123 更新时间:2023-11-28 01:59:58 24 4
gpt4 key购买 nike

我目前正在学习 openGL,并试图了解 VBO 和 VAO 之间的关系。

据我所知,VBO 就是一个数据缓冲区,仅此而已。为了将该数据传递到 OpenGL 管道,我需要将该 VBO 数据绑定(bind)到 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);
}

我希望看到的是一个三角形围绕屏幕变形并改变颜色,但我看到的只是一个静态三角形改变颜色。

最佳答案

As far as I know, a VBO is a buffer of data and that's all.

A buffer object是数据缓冲区。术语“VBO”指的是(当前)用作顶点属性源的缓冲区对象。 Buffer objects can be used for many other things , 你可以用多种不同的方式使用同一个缓冲区。

In order to pass that data into the OpenGL Pipeline, I need to bind that VBO data to a VAO.

技术术语是将缓冲区对象“附加”到 VAO。您将一个对象“附加”到另一个对象;您将对象“绑定(bind)”到上下文

现在我们已经弄清楚了我们的术语,让我们来谈谈您的代码哪里出错了。

//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就是flags字段;它指定 the ways in which you can modify the contents of the storage from the CPU (除其他事项外)。也就是说,不可变存储并不意味着您不能再次将内容复制到其中。这只是意味着您无法重新分配存储空间。

但是您传递了 0。这意味着您创建的缓冲区是完全静态的。您告诉 OpenGL 您不想通过 CPU 进程更改缓冲区的内容。这对于静态缓冲区来说很好,但这显然不是您想要的。

因此,您应该传递一个适当的标志,而不是 0。允许 glNamedBufferSubData 工作的标志称为 GL_DYNAMIC_STORAGE_BIT

关于c++ - glBindVertexArray 时 VAO 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39946386/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com