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

问题描述

在使用OpenGl时,我通常会创建一个VBO并使用

将顶点数据传递给它
glBufferData();

我最近一直在阅读this的资料,请让我引用其中的一部分:

在创建新存储时,将删除所有先前存在的数据存储。将使用指定的大小(以字节为单位)和使用情况创建新的数据存储。如果data不为NULL,则使用该指针中的数据初始化数据存储。在初始状态下,新数据存储区未映射,它具有NULL映射指针,其映射访问权限为GL_READ_WRITE。

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

我了解attrib指针的用途-它们告诉OpenGL状态机如何在VBO中组织数据。
但是,将指针既传递给VBO又传递给glVertexAttribPointer函数似乎是多余的,因为VAO始终会保存attrib指针配置,并且调用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);