<p>Back when I did the transition from immediate mode to vertex buffer object (VBO) in my own code base, I have found it easier to proceed with these steps:</p>

<h1>From naive immediate mode code...</h1>

<p>The original code was something like this:</p>

<pre><code>glBegin(GL_TRIANGLES);
glNormal3f(nx, ny, nz);
glVertex3f(px, py, pz);
// [...] arbitrary long sequence of such function calls.
glEnd();
</code></pre>

<h1>1. To array based immediate mode code...</h1>

<p>First, keep using the immediate mode, but make sure that all values passed to the vertex functions come from an array. This seems to be already the state of the code described in the question.</p>

<pre><code>float vertexData[] = { ... }; // Can be all together, or split by attribute type, as you prefer.
glBegin(GL_TRIANGLES);
for (int i = 0; i &lt; numberOfVertices; ++i)
{
    // The indices are going to depend on the data layout.
    glNormal3f(vertexData[0], vertexData[1], vertexData[2]);
    glVertex3f(vertexData[3], vertexData[4], vertexData[5]);
}
glEnd();
</code></pre>

<h1>2. To vertex array version...</h1>

<p>Second, you can replace the loop by a handful of calls with vertex arrays.</p>

<pre><code>glEnableClientstate(GL_Vertex_Array);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), vertexData);
glNormalPointer(GL_FLOAT, 6 * sizeof(float), vertexData + 3);
glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);
glDisableClientState(GL_VERTEX_ARRAY);
</code></pre>

<h1>3. To vertex buffer version</h1>

<p>Finally from the vertex array based version, the transition to VBO is minimal:</p>

<pre><code>// An initialization part will create and populate the vertex buffer:
GLuint vboId = 0;
glGenBuffers(1, &amp;VBOid);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOid);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(float), vertexData, GL_STATIC_DRAW);


// A draw part will bind the vertex buffer and issue the drawcall.
// It's almost the same code as before, except:
// - We bind a VBO
// - We pass (0+offset) as the last parameter for the gl*pointer().
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOId);

glEnableClientstate(GL_Vertex_Array);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (void*)(0));
glNormalPointer(GL_FLOAT, 6 * sizeof(float), (void*)(0 + 3));
glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);
glDisableClientState(GL_VERTEX_ARRAY);
</code></pre>

<p>And that's it. Both vertex array and VBO allow to work directly with vertices or with vertex index, so be careful about possible confusion there.</p>

<p>P.S.: I have written this answer without double checking the code, so it's probably ridden with typos and not meant for copy-pasting. I invite you to read the documentation, understand the API and refer to other examples when you implement it. At first, VBO can be really annoying to get to work properly.</p>

<p>I have used the same distinction when answering this other <a href="https://computergraphics.stackexchange.com/a/36/182">question about performance of VBO</a>.</p>

CC BY-SA 4.0
2018-07-31T13:54:43.867Z
2018-07-31T13:54:43.867Z
Julien Guertault
<p>You first need to put all the data into a VBO in the correct order, it's important that each vertex position corresponds with the normal it uses.</p>

<pre><code>struct Vertex{
    vec3 pos;
    vec3 normal;
}

std::vector&lt;Vertex&gt; vertices;
vertices.reserve(vecf*3);
Vertex v;

for(int j = 0; j &lt; vecf.size(); j++){
    v.normal = vec3(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);
    vertices.push_back(v);
    v.normal = vec3(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);
    vertices.push_back(v);
    v.normal = vec3((vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);
    vertices.push_back(v);
}

int vbo;
glGenBuffer(1, &amp;vbo);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(posAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, pos));
glVertexAttribPointer(normalAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, normal));
</code></pre>

<p>then you can draw it with <code>glDrawArrays(GL_TRIANGLES, 0, vertices.size());</code></p>

CC BY-SA 4.0
2018-07-30T08:36:09.087Z
2018-07-30T08:36:09.087Z
ratchet freak
<p>How to convert from glBegin() and glEnd() to VBOs (Vertex Buffer Objects)?</p>

<p>I found a simple example here:</p>

<pre><code>GLfloat vertices[] = {...}; // 36 of vertex coords
...
// activate and specify pointer to vertex array
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);

// draw a cube
glDrawArrays(GL_TRIANGLES, 0, 36);

// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
</code></pre>

<p><a href="http://www.songho.ca/opengl/gl_vertexarray.html" rel="nofollow noreferrer">http://www.songho.ca/opengl/gl_vertexarray.html</a></p>

<hr>

<p>So if I have code in very "standard" glBegin() and glEnd() fashion like:</p>

<pre><code>glBegin(GL_TRIANGLES);

    for(int j = 0; j &lt; vecf.size(); j++){
        glNormal3f(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);
        glVertex3f(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);
        glNormal3f(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);
        glVertex3f(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);
        glNormal3f(vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);
        glVertex3f(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);
    }

glEnd();
</code></pre>

<p>Then how do I convert this to VBOs?</p>

<hr>

<p>Particularly, I already know that I need to supply vertices array and normals array, but I seem to confuse the orders of some vecs, because what's drawn becomes out as distorted.</p>

CC BY-SA 4.0
2018-07-26T18:33:55.170Z
Check these links.
https://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification

https://stackoverflow.com/questions/23314787/use-of-vertex-array-objects-and-vertex-buffer-objects
gallickgunner
<opengl>
How to convert from glBegin() and glEnd() to VBOs?
mavavilj
# How to convert from glBegin() and glEnd() to VBOs?

(Asked by: username_0 on 2018-07-26)

How to convert from glBegin() and glEnd() to VBOs (Vertex Buffer Objects)?

I found a simple example here:

```
GLfloat vertices[] = {...}; // 36 of vertex coords
...
// activate and specify pointer to vertex array
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);

// draw a cube
glDrawArrays(GL_TRIANGLES, 0, 36);

// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);

```

<http://www.songho.ca/opengl/gl_vertexarray.html>

---

So if I have code in very "standard" glBegin() and glEnd() fashion like:

```
glBegin(GL_TRIANGLES);

    for(int j = 0; j < vecf.size(); j++){
        glNormal3f(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);
        glVertex3f(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);
        glNormal3f(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);
        glVertex3f(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);
        glNormal3f(vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);
        glVertex3f(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);
    }

glEnd();

```

Then how do I convert this to VBOs?

---

Particularly, I already know that I need to supply vertices array and normals array, but I seem to confuse the orders of some vecs, because what's drawn becomes out as distorted.

**Tags:** opengl

> **Comments:**
> **username_1**: Check these links. https://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification  https://stackoverflow.com/questions/23314787/use-of-vertex-array-objects-and-vertex-buffer-objects  

---

## 2 answers

### Answer by username_2 on 2018-07-31. Score: 3

Back when I did the transition from immediate mode to vertex buffer object (VBO) in my own code base, I have found it easier to proceed with these steps:

# From naive immediate mode code...

The original code was something like this:

```
glBegin(GL_TRIANGLES);
glNormal3f(nx, ny, nz);
glVertex3f(px, py, pz);
// [...] arbitrary long sequence of such function calls.
glEnd();

```

# 1. To array based immediate mode code...

First, keep using the immediate mode, but make sure that all values passed to the vertex functions come from an array. This seems to be already the state of the code described in the question.

```
float vertexData[] = { ... }; // Can be all together, or split by attribute type, as you prefer.
glBegin(GL_TRIANGLES);
for (int i = 0; i < numberOfVertices; ++i)
{
    // The indices are going to depend on the data layout.
    glNormal3f(vertexData[0], vertexData[1], vertexData[2]);
    glVertex3f(vertexData[3], vertexData[4], vertexData[5]);
}
glEnd();

```

# 2. To vertex array version...

Second, you can replace the loop by a handful of calls with vertex arrays.

```
glEnableClientstate(GL_Vertex_Array);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), vertexData);
glNormalPointer(GL_FLOAT, 6 * sizeof(float), vertexData + 3);
glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);
glDisableClientState(GL_VERTEX_ARRAY);

```

# 3. To vertex buffer version

Finally from the vertex array based version, the transition to VBO is minimal:

```
// An initialization part will create and populate the vertex buffer:
GLuint vboId = 0;
glGenBuffers(1, &VBOid);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOid);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(float), vertexData, GL_STATIC_DRAW);

// A draw part will bind the vertex buffer and issue the drawcall.
// It's almost the same code as before, except:
// - We bind a VBO
// - We pass (0+offset) as the last parameter for the gl*pointer().
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOId);

glEnableClientstate(GL_Vertex_Array);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (void*)(0));
glNormalPointer(GL_FLOAT, 6 * sizeof(float), (void*)(0 + 3));
glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);
glDisableClientState(GL_VERTEX_ARRAY);

```

And that's it. Both vertex array and VBO allow to work directly with vertices or with vertex index, so be careful about possible confusion there.

P.S.: I have written this answer without double checking the code, so it's probably ridden with typos and not meant for copy-pasting. I invite you to read the documentation, understand the API and refer to other examples when you implement it. At first, VBO can be really annoying to get to work properly.

I have used the same distinction when answering this other [question about performance of VBO](https://computergraphics.stackexchange.com/a/36/182).


---

### Answer by username_3 on 2018-07-30. Score: 0

You first need to put all the data into a VBO in the correct order, it's important that each vertex position corresponds with the normal it uses.

```
struct Vertex{
    vec3 pos;
    vec3 normal;
}

std::vector<Vertex> vertices;
vertices.reserve(vecf*3);
Vertex v;

for(int j = 0; j < vecf.size(); j++){
    v.normal = vec3(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);
    vertices.push_back(v);
    v.normal = vec3(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);
    vertices.push_back(v);
    v.normal = vec3((vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);
    v.pos = vec3(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);
    vertices.push_back(v);
}

int vbo;
glGenBuffer(1, &vbo);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(posAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, pos));
glVertexAttribPointer(normalAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, normal));

```

then you can draw it with `glDrawArrays(GL_TRIANGLES, 0, vertices.size());`


---

