1
votes

To create a uniform buffer object in OpenGL, why must I call both glBindBuffer and glBindBufferRange? According to documentation,

Think of glBindBufferRange as binding the buffer to two places: the particular index and the target​. glBindBuffer only binds to the target​, not the index.

So then glBindBuffer seems superfluous to me if you are already binding a buffer to that same target using glBindBufferRange.

I am reading Learning Modern 3D Graphics Programming and chapter 7 shows how to make uniform buffer objects. The code used in the book:

glGenBuffers(1, &g_GlobalMatricesUBO);
glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

glBindBufferRange(GL_UNIFORM_BUFFER, g_iGlobalMatricesBindingIndex, g_GlobalMatricesUBO, 0, sizeof(glm::mat4) * 2);

This code works until I comment out the call to glBufferData, in which case I get a black screen. This is surprising to me because afterwards we are binding g_GlobalMatricesUBO to the GL_UNIFORM_BUFFER binding target anyways. The documentation linked to earlier also says:

Do note that this does not replace standard buffer binding with glBindBuffer. It does in fact bind the buffer to the target​ parameter, thus unbinding whatever was bound to that target. But usually when you use glBindBufferRange, you are serious about wanting to use the buffer rather than just modify it.

Which seems to touch on what I'm confused about, but I do not understand this explanation. It says it unbinds whatever was previously bound to the target, which seems to reinforce my (wrong) idea that binding a buffer to the target beforehand is unnecessary.

1

1 Answers

4
votes

glBufferData does not only initialize the buffer, it creates the buffer object's data store with the specified size. You can think about it like memory allocation in c++.
glBufferData creates a data store for the buffer object which is currently bound to the specified target. In this case it creates a data store for the named buffer object g_GlobalMatricesUBO, because it is bound to the specified target GL_UNIFORM_BUFFER.

glBindBufferRange doesn't create any data store, it use the data store which has to exist. The buffer object with the data store is specified by the 3rd parameter.