为什么必须同时使用 glBindBuffer 和 glBindBufferRange 在 OpenGL 中创建统一缓冲区?

Dav*_*oia 3 c++ opengl

要在 OpenGL 中创建统一的缓冲区对象,为什么我必须同时调用glBindBufferglBindBufferRange?根据文件

\n\n
\n

将 glBindBufferRange 视为将缓冲区绑定到两个位置:特定索引和目标\xe2\x80\x8b。glBindBuffer 仅绑定到目标\xe2\x80\x8b,而不是索引。

\n
\n\n

因此,glBindBuffer如果您已经使用将缓冲区绑定到同一目标,那么对我来说似乎是多余的glBindBufferRange

\n\n

我正在阅读学习现代 3D 图形编程,第 7 章展示了如何制作统一的缓冲区对象。书中使用的代码:

\n\n
glGenBuffers(1, &g_GlobalMatricesUBO);\nglBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);\nglBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, NULL, GL_STREAM_DRAW);\nglBindBuffer(GL_UNIFORM_BUFFER, 0);\n\nglBindBufferRange(GL_UNIFORM_BUFFER, g_iGlobalMatricesBindingIndex, g_GlobalMatricesUBO, 0, sizeof(glm::mat4) * 2);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这段代码一直有效,直到我注释掉对 glBufferData 的调用,在这种情况下我会得到黑屏。这让我感到惊讶,因为之后我们无论如何都会绑定g_GlobalMatricesUBOGL_UNIFORM_BUFFER绑定目标。之前链接的文档还说:

\n\n
\n

请注意,这不会用 glBindBuffer 取代标准缓冲区绑定。事实上,它确实将缓冲区绑定到 target\xe2\x80\x8b 参数,从而解除绑定到该目标的任何内容。但通常当你使用 glBindBufferRange 时,你是认真想要使用缓冲区而不是仅仅修改它。

\n
\n\n

这似乎触及了我的困惑,但我不明白这个解释。它说它会解除之前绑定到目标的任何内容的绑定,这似乎强化了我的(错误)想法,即事先将缓冲区绑定到目标是不必要的。

\n

Rab*_*d76 5

glBufferData不仅初始化缓冲区,还创建具有指定大小的缓冲区对象的数据存储。你可以把它想象成c++中的内存分配。
glBufferData为当前绑定到指定目标的缓冲区对象创建数据存储。在本例中,它为指定的缓冲区对象创建一个数据存储g_GlobalMatricesUBO,因为它绑定到指定的目标GL_UNIFORM_BUFFER

glBindBufferRange不创建任何数据存储,它使用必须存在的数据存储。具有数据存储的缓冲区对象由第三个参数指定。