PDA

View Full Version : Order of function calls



dcox1776
10-03-2012, 07:52 PM
I have a question about the order of these function calls:

glBindBuffer(GL_ARRAY_BUFFER, buf1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

Is it really necessary to bind a buffer before calling glVertexAttribPointer? glVertexAttribPointer sets the size, type, stride, normalization, and pointer (essentially an offset) into a buffer. It seems to me that these state values could be set without binding a buffer. Is this the case?

Alfonse Reinheart
10-03-2012, 08:06 PM
Is it really necessary to bind a buffer before calling glVertexAttribPointer?

Yes, it really is. (http://www.opengl.org/wiki/Vertex_Specification#Vertex_Buffer_Object) Or, if you don't want to read that:


Think of it like this. glBindBuffer​ sets a global variable, then glVertexAttribPointer​ reads that global variable and stores it in the VAO. Changing that global variable after it's been read doesn't affect the VAO. You can think of it that way because that's exactly how it works.

mhagain
10-03-2012, 09:00 PM
Or from the classic documentation: http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml


If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target (see glBindBuffer) while a generic vertex attribute array is specified, pointer is treated as a byte offset into the buffer object's data store.

GL4.3 or the GL_ARB_vertex_attrib_binding extension (http://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt) will remove the dependency on the currently bound buffer when specifying vertex formats and layouts.

dcox1776
10-04-2012, 06:19 AM
Thanks for the replies. I did some experimenting last night on my mac. If I place the calls to glVertexAttribPointer before binding my buffers, I get garbage on the screen. No errors, just garbage. This doesn't happen if the binding occurs before the calls to glVertexAttribPointer.

Let me see if I understand the implications. glBindBuffer does not affect the VAO. However, glVertexAttribPointer does affect the VAO. In addition to storing the size, type, stride, and normalization state information, does glVertexAttribPointer also store the address of the buffer in the VAO? In the example that I gave, buf1 is associated with the target GL_ARRAY_BUFFER. I'll represent this conceptually as GL_ARRAY_BUFFER = ADDRESS(buf1). The pointer parameter to glVertexAttribPointer is an offset. So, I am thinking that glVertexAttribPointer is storing GL_ARRAY_BUFFER + pointer in the VAO which is the address of buf1 plus the offset passed to the function.

dcox1776
10-04-2012, 06:36 AM
Another quick question about this topic. Let's say I make multiple calls to bind three different buffers to the same target (GL_ARRAY_BUFFER). glVertexAttribPointer is called for each and in each case the index parameter (the first parameter) to glVertexAttribPointer is different:

glBindBuffer(GL_ARRAY_BUFFER, buf1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, buf2);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, buf3);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);


Will the state information for all three be stored in the VAO? Or will the latest calls to glBindBuffer/glVertexAttribPointer overwrite what was previously saved in the VAO? I assume that all three are stored because the index parameter differs for each even though the target (GL_ARRAY_BUFFER) is the same in each case.

Dan Bartlett
10-04-2012, 08:07 AM
Yes, all 3 are stored since you used different attribute indices.

dcox1776
10-04-2012, 11:14 AM
Thanks Dan!

arekkusu
10-04-2012, 12:48 PM
Search for "ARRAY_BUFFER_BINDING" in the specification and you'll see this explained in the "Vertex Arrays in Buffer Objects" section.

And in the "Vertex Array Object State" table, showing exactly what state is tracked where.

dcox1776
10-04-2012, 07:33 PM
arekkusu, thanks for the tip.

I found ARRAY_BUFFER_BINDING in section 2.9.6 of the 3.2core spec. The spec isn't very clear. ARRAY_BUFFER_BINDING is mentioned only once: "For example, the VertexAttribPoint command copies the value of ARRAY_BUFFER_BINDING (the queriable name of the buffer binding corresponding to the target ARRAY_BUFFER) to the client state variable VERTEX_ATTRIB_ARRAY_BUFFER_BINDING for the specified index."

This is the only place that I could find ARRAY_BUFFER_BINDING mentioned in the text of the spec. It has a value which apparently corresponds to the "queriable name of the buffer binding corresponding to the target ARRAY_BUFFER."

I know what a buffer is. But what is a buffer binding? It is first mentioned on the top of page 44 but the term is not defined. I searched Google but also came up short for a definition. Whatever it is, it is an integer and apparently has a name.

Table 6.6 does include ARRAY_BUFFER_BINDING and says that it is a positive integer, has an initial value of 0, and is described as the "current buffer binding."

Section 2.9.1 describes creating and binding buffer objects. I am guessing that a call to BindBuffer creates a buffer binding. However, the spec doesn't explicitly say if this is the case. Table 6.6 provides some hints. The caption of table 6.6 says, "Vertex Array Data (not in Vertex Array objects)." There are four rows in the table. As already mentioned, one of the four rows contains ARRAY_BUFFER_BINDING. So, it appears that ARRAY_BUFFER_BINDING is the name of a state variable that is not stored in a VAO. Its value is the name of the current buffer binding. Now, GenBuffers reserves and returns buffer object names. Let's see if we can put this all together.

A call to GenBuffers returns one or more buffer object names. At the time GenBuffers is called, a buffer object name is reserved but no buffer has been bound. To bind a buffer we need to call BindBuffer and pass a target (in this case the value ARRAY_BUFFER) and a buffer object name. At this point a buffer has been created, associated with a name, and bound to the target.

A side effect of calling BindBuffer is the setting of state variable(s). One state variable is referred to as ARRAY_BUFFER_BINDING. Its value is set to the name of the buffer object that was passed to BindBuffer. The state variable appears to have global scope because it is not stored in any VAO according to table 6.6.

It seems that this scenario could be represented as follows:

// The function BindBuffer
BindBuffer(target, name)
{
...
IF (target == ARRAY_BUFFER)
GlobalState[ARRAY_BUFFER_BINDING] = name;
...
}

// get a bunch of buffer object names
GenBuffers(n, buffers);

// get one of the buffer object names
name = buffers[i];

// bind the buffer object name to the target ARRAY_BUFFER
BindBuffer(ARRAY_BUFFER, name);