What is the role of glBindVertexArrays vs glBindBuffer and what is their relationship?

I am new to OpenGL and graphical programming. I read a textbook that has been really thorough and well written so far. However, I hit a point in the code that I do not quite understand, and I would like to understand these lines before I move on.

GLuint abuffer; glGenVertexArrays(1, &abuffer); glBindVertexArray(abuffer); 



 GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); 

The book explains that the first three lines create a vertex array object, which is used to associate the associated data with the vertex array. The second line finds the unused name (I assume that the unsigned integer identifier is stored in abuffer ), and the third line creates the object / makes it active.

The book explains that the 4th-7th line creates a buffer object for storing our data, and the 5th line gives us an unused identifier (similar to line 2 for the vertex array object?), The 6th line that creates the buffer, and 7- I line allocates sufficient memory to the CPU and creates a pointer to our data (points) for GL_STATIC_DRAW .

What does it mean that an object is active? When will you use abuffer ? What does it mean that a vertex array binds related data, and when was the data associated with this vertex array object?

I am confused about the relationship between abuffer and buffer . I am confused by the fact that the ratio of the vertex array to the buffer object, and at what point this relation is formed. I'm not sure if they are really connected, but they are presented in the textbook immediately after another.

Any help would be greatly appreciated. Thank.

+51
c ++ opengl
Feb 08 '14 at 10:25
source share
5 answers

From a low level point of view, you might think that an array has two parts:

  • Information about the size, shape, and type of the array (for example, 32-bit floating-point numbers containing strings of vectors with four elements each).

  • Array data that is slightly larger than a large number of bytes.

Despite the fact that the low-level concept has basically remained the same, then, as you point out, arrays have changed several times over the years.

OpenGL 3.0 / ARB_vertex_array_object

This is what you should probably do today. It is very rare to find people who cannot run OpenGL 3.x, but still have money spent on your software.

An OpenGL buffer object is a large bit bit. Think of the “active” buffer as a global variable, and there are many functions that use the active buffer instead of using a parameter. These global state variables are the ugly side of OpenGL (up to direct access to the state, which is described below).

 GLuint buffer; // Generate a name for a new buffer. // eg buffer = 2 glGenBuffers(1, &buffer); // Make the new buffer active, creating it if necessary. // Kind of like: // if (opengl->buffers[buffer] == null) // opengl->buffers[buffer] = new Buffer() // opengl->current_array_buffer = opengl->buffers[buffer] glBindBuffer(GL_ARRAY_BUFFER, buffer); // Upload a bunch of data into the active array buffer // Kind of like: // opengl->current_array_buffer->data = new byte[sizeof(points)] // memcpy(opengl->current_array_buffer->data, points, sizeof(points)) glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); 

Now your typical vertex shader accepts vertices as input rather than a large bit bit. Therefore, you need to specify how the blob bit (buffer) is decoded to the top. This is an array task. Similarly, there is an “active” array that can be thought of as a global variable:

 GLuint array; // Generate a name for a new array. glGenVertexArrays(1, &array); // Make the new array active, creating it if necessary. glBindVertexArray(array); // Make the buffer the active array buffer. glBindBuffer(GL_ARRAY_BUFFER, buffer); // Attach the active buffer to the active array, // as an array of vectors with 4 floats each. // Kind of like: // opengl->current_vertex_array->attributes[attr] = { // type = GL_FLOAT, // size = 4, // data = opengl->current_array_buffer // } glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0); // Enable the vertex attribute glEnableVertexAttribArray(attr); 

OpenGL 2.0 (old way)

OpenGL 2.x did not have vertex arrays, and the data was just global. You still had to call glVertexAttribPointer() and glEnableVertexAttribArray() , but you had to call them every time you used the buffer. In OpenGL 3.x, you just set up the array once.

Going back to OpenGL 1.5, you can really use buffers, but you used a separate function to bind each data type. For example, glVertexPointer() was for vertex data, and glNormalPointer() was for normal data. There were no buffers before OpenGL 1.5, but you could use pointers in your application memory.

OpenGL 4.3 / ARB_vertex_attrib_binding

In 4.3, or if you have the extension ARB_vertex_attrib_binding, you can specify the attribute format and attribute data separately. This is good because it allows you to easily switch between a single vertex array between different buffers.

 GLuint array; // Generate a name for a new array array. glGenVertexArrays(1, &array); // Make the new array active, creating it if necessary. glBindVertexArray(array); // Enable my attributes glEnableVertexAttribArray(loc_attrib); glEnableVertexAttribArray(normal_attrib); glEnableVertexAttribArray(texcoord_attrib); // Set up the formats for my attributes glVertexAttribFormat(loc_attrib, 3, GL_FLOAT, GL_FALSE, 0); glVertexAttribFormat(normal_attrib, 3, GL_FLOAT, GL_FALSE, 12); glVertexAttribFormat(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24); // Make my attributes all use binding 0 glVertexAttribBinding(loc_attrib, 0); glVertexAttribBinding(normal_attrib, 0); glVertexAttribBinding(texcoord_attrib, 0); // Quickly bind all attributes to use "buffer" // This replaces several calls to glVertexAttribPointer() // Note: you don't need to bind the buffer first! Nice! glBindVertexBuffer(0, buffer, 0, 32); // Quickly bind all attributes to use "buffer2" glBindVertexBuffer(0, buffer2, 0, 32); 

OpenGL 4.5 / ARB_direct_state_access

In OpenGL 4.5, or if you have the ARB_direct_state_access extension, you no longer need to call glBindBuffer() or glBindVertexArray() just to set the settings ... you directly specify arrays and buffers. You only need to bind the array at the end to draw it.

 GLuint array; // Generate a name for the array and create it. // Note that glGenVertexArrays() won't work here. glCreateVertexArrays(1, &array); // Instead of binding it, we pass it to the functions below. // Enable my attributes glEnableVertexArrayAttrib(array, loc_attrib); glEnableVertexArrayAttrib(array, normal_attrib); glEnableVertexArrayAttrib(array, texcoord_attrib); // Set up the formats for my attributes glVertexArrayAttribFormat(array, loc_attrib, 3, GL_FLOAT, GL_FALSE, 0); glVertexArrayAttribFormat(array, normal_attrib, 3, GL_FLOAT, GL_FALSE, 12); glVertexArrayAttribFormat(array, texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24); // Make my attributes all use binding 0 glVertexArrayAttribBinding(array, loc_attrib, 0); glVertexArrayAttribBinding(array, normal_attrib, 0); glVertexArrayAttribBinding(array, texcoord_attrib, 0); // Quickly bind all attributes to use "buffer" glVertexArrayVertexBuffer(array, 0, buffer, 0, 32); // Quickly bind all attributes to use "buffer2" glVertexArrayVertexBuffer(array, 0, buffer2, 0, 32); // You still have to bind the array to draw. glBindVertexArray(array); glDrawArrays(...); 

ARB_direct_state_access is good for many reasons. You can forget about binding arrays and buffers (except when you draw), so you don’t need to think about hidden global variables that OpenGL keeps track of for you. You can forget about the difference between “generating a name for an object” and “creating an object” because glCreateBuffer() and glCreateArray() both perform at the same time.

Vulkan

The volcano goes even further, and you write the code like the pseudocode I wrote above. So you will see something like:

 // This defines part of a "vertex array", sort of VkVertexInputAttributeDescription attrib[3]; attrib[0].location = 0; // Feed data into shader input #0 attrib[0].binding = 0; // Get data from buffer bound to slot #0 attrib[0].format = VK_FORMAT_R32G32B32_SFLOAT; attrib[0].offset = 0; // repeat for attrib[1], attrib[2] 
+94
Feb 08 '14 at 23:12
source share

Your interpretation of the book is not entirely correct. Vertex array objects do not store data. They are a class of objects known as containers, such as Framebuffer Objects. You can attach / associate other objects with them, but they never store the data themselves. Thus, they are not a resource shared by context.

Arte Vertex Array objects encapsulate the state of a vertex array in OpenGL 3.0. Starting with OpenGL 3.1 (instead of GL_ARB_compatibility ) and Core OpenGL 3.2+ profiles, you should always have a non-zero VAO binding to execute commands like glVertexAttribPointer (...) or glDrawArrays (...) . The associated VAO forms the necessary context for these commands and maintains state persistently.

In older versions of GL (and compatibility), the state retained by VAO was part of the global state machine.

It is also worth noting that the “current” binding for GL_ARRAY_BUFFER is not one of the states that VAOs track. Although this binding is used by commands such as glVertexAttribPointer (...) , VAOs do not save the bindings, they only store pointers (the GL_ARB_vertex_attrib_binding extension, introduced with GL 4.3, complicates this bit, so we will ignore it for simplicity).

VAOs do remember that it is bound to GL_ELEMENT_ARRAY_BUFFER , so that indexed drawing commands such as glDrawElements (...) function as you expected (for example, VAO reuses the last buffer of an array of elements).

+12
Feb 08 '14 at 23:08
source share

A link is created when glVertexAttribPointer is called.

Overview of VertexArrays

GL_VERTEX_ARRAY_BINDING and GL_ARRAY_BUFFER_BINDING are constants, but they can indicate a global binding state. I mean the state, not the permanent (orange) image. Use glGet to learn about different global states.

VertexArray groups information (including an array buffer) about a vertex or a set of parallel vertices.

Use GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING with glGetVertexAttrib to determine which attribute array buffer is set.

glBindBuffer (GL_ARRAY_BUFFER sets the global state GL_ARRAY_BUFFER_BINDING

glBindVertexArray sets the global state GL_VERTEX_ARRAY_BINDING

+4
Nov 15 '14 at 16:05
source share

OpenGL is a stateful interface. This is bad, outdated and ugly, but this legacy is for you.

A vertex array object is a set of buffer bindings that a driver can use to obtain data for drawing calls; most textbooks use only one and never explain how to use multiple VAOs.

A buffer binding tells opengl to use this buffer for related methods, in particular for glVertexAttribPointer methods.

+3
Feb 08 '14 at 22:28
source share

There is no connection between VertexArray and VBO.

An array of vertices allocates memory in RAM and sends a pointer to the API. VBO allocates memory on the graphics card - there is no address for it in the system memory. If you need to access vbo data from a system, you need to first copy it from vbo to the system.

In addition, in new versions of OpenGL, vertex arrays are completely deleted (redefined in 3.0, removed in 3.1)

-2
Feb 08 '14 at 22:47
source share



All Articles