# Buffer Objects (BO)

## Buffer Objects (BO)

Most of of OpenGL's data are stored inside of a **B**uffer **O**bject (**BO**) . For example 3D Model data (Vertex data) are stored inside a **V**ertex **B**uffer **O**bject (**VBO**). Or data that is indexing vertices called **I**ndex **B**uffer **O**bject (**IBO**). Data that is exchanged between client and shader can use **U**niform **B**uffer **O**bjects (**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);
```

| glCreateBuffers | Parameter | Type             | Description                                                   |
| --------------- | --------- | ---------------- | ------------------------------------------------------------- |
|                 | 1         | GLsizei n        | Number of buffer objects to create.                           |
|                 | 2         | GLuint \*buffers | An array in which names of the new buffer objects are stored. |

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**.

| glNamedBufferStorage | Parameter | Type              | Description                             |
| -------------------- | --------- | ----------------- | --------------------------------------- |
|                      | 1         | GLuint buffer     | Name of the buffer object.              |
|                      | 2         | GLsizei size      | The size of the buffer in bytes.        |
|                      | 3         | const void \*data | Data to upload into the buffer storage. |
|                      | 4         | GLbitfield flags  | Intented usage bits.                    |

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.

| Bit                       | Description                                                                                                                                                                                                                |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GL\_DYNAMIC\_STORAGE\_BIT | If this is set, we tell OpenGL that we will change the content of the buffer using glBufferSubData. If we don't specify this bit the client (our program) will not be able to change the data of this buffer **directly**. |
| GL\_MAP\_READ\_BIT        | If we want to map the address of the memory into the client space to read from it, we need to set this flag. If not set we can't use **glMapNamedBuffer** to read from it.                                                 |
| GL\_MAP\_WRITE\_BIT       | If we want to map the address of the memory into the client space to write to it, we need to set this flag. If not set we can't use **glMapNamedBuffer**  to write to i&#x74;**.**                                         |
| GL\_MAP\_PERSISTENT\_BIT  |                                                                                                                                                                                                                            |
| GL\_MAP\_COHERENT\_BIT    |                                                                                                                                                                                                                            |
| GL\_CLIENT\_STORAGE\_BIT  | If this bit is set we tell OpenGL that we like the buffer to be managed inside the client memory.                                                                                                                          |

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**.

| glCopyNamedBuferSubData | Parameters | Type                 | Description                                                  |
| ----------------------- | ---------- | -------------------- | ------------------------------------------------------------ |
|                         | 1          | GLuint readBuffer    | The buffer name from where we like to copy from.             |
|                         | 2          | GLuint writeBuffer   | The buffer name where we like to copy to.                    |
|                         | 3          | GLintptr readOffset  | Offset we like to use from the buffer we like to read from.  |
|                         | 4          | GLintptr writeOffset | Offset we like to use inside the buffer we like to write to. |
|                         | 5          | GLsizei size         | Number of bytes to copy.                                     |

### 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**.

| glMapNamedBuffer | Parameters | Type          | Description                  |
| ---------------- | ---------- | ------------- | ---------------------------- |
| GL\_bool         | 1          | GLuint buffer | The VBO name.                |
|                  | 2          | GLenum access | Specifies the access policy. |

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:

| Enum            | Description                                      |
| --------------- | ------------------------------------------------ |
| GL\_READ\_ONLY  | We will only read from the buffer.               |
| GL\_WRITE\_ONLY | We will only write into the buffer.              |
| GL\_READ\_WRITE | We will read and write from and into the buffer. |

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**.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yaakuro.gitbook.io/opengl-4-5/chapter1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
