Buffer Objects (BO)

Buffer Objects (BO)

Most of of OpenGL's data are stored inside of a Buffer Object (BO) . For example 3D Model data (Vertex data) are stored inside a Vertex Buffer Object (VBO). Or data that is indexing vertices called Index Buffer Object (IBO). Data that is exchanged between client and shader can use Uniform Buffer Objects (UBO) etc. Those BO are created, initialized and updated by the same functions we will discuss now.

Create identifier

To identify an BO we need an empty name (which is an identificier of that object). We get one using the glCreateBuffers function:

GLuint vbo {};
glCreateBuffers(1, &vbo);

Until here we didn't allocate memory for the BO. We only got an valid name wich we will use to identify our BO. In the next section we will really allocate memory and initialize the BO with data.

Initialize and allocate memory

We want to use our first BO as a VBO. Look at the following code snippet:

struct vertex {
    float x, y, z;
    float r, g, b;
};

const std::vector<vertex> vertices {
    {-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, // Vertex 1
    { 0.0f,  1.0f, 1.0f, 0.0f, 1.0f, 0.0f }, // Vertex 2
    { 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f }  // Vertex 3
};
glNamedBufferStorage(vbo, vertices.size() * sizeof(vertex), vertices.data(), 0);

The first thing we did is to define a structure for our vertex. The structure will hold 3 position and 3 color data. Then we created 3 vertices and put it into an array called: vertices. Now we want to tell OpenGL that we like to upload the vertices and how we like to use the this BO later. To allocate memory and set the properties of the BO we use the function glNamedBufferStorage.

The 1. parameter should be a valid BO name. We got one when we used glCreateBuffers. See above. The 2. parameter as it says it the size of the buffer in bytes. The 3. parameter points to a buffer where the data to upload is hold. If we specify a nullptr nothing will be uploaded but memory allocated of the size we specified in the 2. parameter. The 4. parameter is the important one. It tells OpenGL how to deal with the buffer later when it is used with other OpenGL functions. The following bits can be combined with the OR operator.

If you look at our example above you will notice that we didn't set any flags for the usage. We use = 0. This means we don't want any of those features for this buffer. We just simply use it to draw and never touch it again. Later we will see how to use those flags in different scenarios. For now its sufficient.

Copy data between BO

There will be a time when you want to copy data from one VBO to another. This is done with glCopyNamedBufferSubData.

Mapping BOs address into client memory space

If we want to modify the values of the BO manually we can map the BO's memory into the clients memory space. We use for that glMapNamedBuffer. I hope you didn't forget that we can use this function only if the correct bits where set when we initialized the BO.

The 1. parameter is the name of the BO we have to specify. The 2. parameter is how we like to access the values of the BO. There are the following options:

If everything (mapping) was successful the function will return a valid pointer to the memory.

When we are finished with reading/writing to/from the BO we have to unmap it. This is done by the function glUnmapNamedBuffer.

Last updated