为什么我需要为 VBO 和调用 glVertexAttribPointer 时指定数据?

Why do I need to specify data for both the VBO and while calling glVertexAttribPointer?

在使用 OpenGl 时,我通常会创建一个 VBO 并将顶点数据传递给它

glBufferData();

我最近一直在阅读this源代码,请允许我引用其中的一部分:

While creating the new storage, any pre-existing data store is deleted. The new data store is created with the specified size in bytes and usage. If data is not NULL, the data store is initialized with data from this pointer. In its initial state, the new data store is not mapped, it has a NULL mapped pointer, and its mapped access is GL_READ_WRITE.

据此我得出结论,当设置缓冲区数据功能时,缓冲区中的数据被复制到 VBO。
现在,当调用 glVertexAttribPointer() 时,我必须再次传递一个指向数据的指针。

我了解属性指针的用途 - 它们告诉 OpenGL 状态机数据在 VBO 中的组织方式。
然而,将指针传递给 VBO 然后传递给 glVertexAttribPointer 函数似乎是多余的,因为 VAO 无论如何都会保存属性指针配置,并且要调用 glVertexAttribPointer 必须将顶点数据存储在程序内存中无论如何 - 所以内存被复制(一个原始副本和 glBufferData() 制作的副本)。

为什么会出现这种明显的冗余?或者也许我理解错误的方式? 也许我误解了文档,数据没有复制到 VBO,但是 VBO 的目的是什么?

你不必。如果命名缓冲区对象绑定到 ARRAY_BUFFER 目标,则处理 glVertexAttribPointer 的最后一个参数(pointer)作为缓冲区对象数据存储中的字节偏移量。

两者之一(仅兼容性配置文件):

float *data;
glBindBuffer(GL_ARRAY_BUFFER, 0); // 0 is default
glVertexAttribPointer(..., data);

float *data;
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, ..., data, ...);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(..., (void*)0);