创建缓冲区并设置其数据时,需要先将其绑定到target
,然后使用一些数据填充绑定到target
的缓冲区:
GLenum target = GL_ARRAY_BUFFER;
glGenBuffers(1, &bufferId);
glBindBuffer(target, bufferId);
glBufferData(target, m_capacity*sizeof(value_type), m_data, GL_STREAM_DRAW);
glBindBuffer(target, 0);
但根据我的理解,如果我在GL_ARRAY_BUFFER
目标上填充的缓冲区稍后用于例如{ GL_UNIFORM_BUFFER
目标。但如果是这种情况,为什么我们需要target
来填充缓冲区,为什么glBufferData
的签名不是:
void glBufferData( GLint bufferId,
GLsizeiptr size,
const GLvoid * data,
GLenum usage);
这只是一个历史原因还是因为opengl是一个状态机,或者我错过了什么,target
还有其他目的。
答案 0 :(得分:3)
这是一个常见的OpenGL API事项 - OpenGL对象(纹理,缓冲区......)的大部分工作都是通过将它们绑定到特定的目标然后使用此来完成的。 target 引用当前绑定的对象(更多关于此here)。不幸的是,我不知道这个的确切原因,但它现在看起来似乎是历史性的 - 我已经看到了一些建议的扩展,用于通过对象id(UPD:用户ratchet freak
says进行直接对象访问是 direct_state_access 扩展,核心在4.5)。
glBindBuffer 上的documentation表示
当缓冲区对象绑定到目标时,该目标的先前绑定将自动中断。
我认为更改缓冲区的绑定类型并期望保持缓冲区的状态不是一个好主意。
<强>更新强>
目标定义了您打算如何使用缓冲区对象的此绑定。当您只是使用数据创建和/或填充缓冲区对象时,您使用的目标在技术上并不重要。
所以,似乎目标只对你如何使用缓冲区很重要,你可以安全地将它绑定到任何随机类型并用数据填充它,但它似乎仍然是一种不好的做法。
答案 1 :(得分:0)
要使用glBufferData
,您需要某种方式来指示要上传的数据的目标。 target
参数(第一个参数)允许此调用知道数据的目标。如果您的唯一目的是上传数据然后解除绑定,正如您所说,使用哪个缓冲区绑定并不重要。您可以在以后将该缓冲区绑定到任何其他绑定。
但是,在GL_ARRAY_BUFFER
数据初始化时间(使用glVertexAttribPointer
/ glEnableVertexArray
)设置顶点属性也很常见,这可能是使用GL_ARRAY_BUFFER
的另一个原因绑定任何其他任意绑定。此外,如果您打算实际使用您在后续绘图调用中上传的缓冲区数据,并且不需要破坏绑定,则保留绑定更有效。