Introduction

Data from a character such as vertices, normals and UV coordinates are loaded into OpenGL objects called Buffer Objects. There are many ways to load these data. In this section, You will learn all the possible ways that these data can be loaded.

Simple data loading

First, let's load a simple array of data representing the vertex position of a character. We are going to create a single OpenGL buffer, bind it to GL_ARRAY_BUFFER and place the vertex data in it. Once the data has been loaded, we will link it to the shaderattributeposition.

The first thing we do before loading data is to create a buffer myBuffer as shown in line 1 listing 1. The buffer is bound to the binding point GL_ARRAY_BUFFER (line 2). Once binding is complete, we are able to load the data into myBuffer. This is accomplished by using the OpenGL function glBufferData as shown in line 3.

The OpenGL function glBufferData requires the binding point of myBuffer, the size of the data to be loaded and the pointer to the data vertexData. The parameter GL_STATIC_DRAW states that the data will not change.

For the data to properly be used in the shader, we need to get the location of the attribute position which is referenced in the shader (line 4). This location is then enabled as shown in line 6. Once enabled, we can link the attribute position with the data in the vertexData array. The link is establish by using the function glVertexAttribPointer as shown in line 7. This function requires the location of the attribute, the number of components per vertex (in our case it is 3. x, y and z components), type of data, normalization, stride and a pointer to the first component of the data.

Loading Interleaved data

The above example shows how to load a simple array of data representing the position of a 3D model. However, most likely you will also need to load data representing normals and uv-coordinates. These data may be interleaved as shown below in the characterData array. The first two components of the array represent the uv coordinates. The next three represent normal coordinates and the last three represent vertex position.

The process is essentially the same as shown in listing 1. Lines 1-3 simply create an OpenGL buffer and loads data into the buffer. Lines 4, 5 and 6 query for the attribute locations position, normal and textCoord, respectively. Line 8 enables each of these attribute location.

Line 9 links the data in the characterData array with the attribute locations. The last parameter of the function glVertexAttribPointer asks for a pointer offset to the components in the array.

For example, The uv-coordinates have an offset of 0, since it is the first component in the array. The offset for the components representing the normal coordinates is sizeof(float)*(elementPosition)=sizeof(float)*2=8. The vertex position pointer is set to 20. sizeof(float)*(elementPosition)=sizeof(float)*5=20.

The stride is set to 32, because that is when the attributes repeat in the array.

Source Code

Loading using glBufferSubData

You may also have vertex, normal and uv data in different arrays. These data can still be loaded into the same OpenGL buffer by using the function glBufferSubData.

The process is the same. We create a OpenGL buffer and bind it as shown in listing 3, lines 1&2. However, the parameters in glBufferData differ as shown in line 3. The size of the buffer is the sum of the size of all three arrays and the parameter pointer for the data is set to NULL (line 3).

Each data is then loaded separately using glBufferSubData as shown in line 3a. Notice the second parameter of the function glBufferSubData representing the offset to the data. It increases as you load more data (lines 3b-3c).

After that, everything is pretty much the same until you get to the function glVertexAttribPointer (line 7). As you link buffer data to the attributes locations, the last parameter of glVertexAttribPointer increases by the array size of the previous linked location (lines 7a-7c).

I like to load data using glBufferSubData, however, you can load the data using either method without any performance penalty.