NoviceCai
NoviceCai

Reputation: 612

OpenGL: how to use buffer_objects to draw

In page 103 of OpenGL redbook, they give an example (example 2-17) about how to use buffer_object to draw something.

#define BUFFER_OFFSET(bytes) ((GLubyte*) NULL + (bytes))


GLuint buffers[NUM_BUFFERS];

GLfloat vertices[][3] = {
{ -1.0, -1.0, -1.0 },
{ 1.0, -1.0, -1.0 },
{ 1.0, 1.0, -1.0 },
{ -1.0, 1.0, -1.0 },
{ -1.0, -1.0, 1.0 },
{ 1.0, -1.0, 1.0 },
{ 1.0, 1.0, 1.0 },
{ -1.0, 1.0, 1.0 }
};

GLubyte indices[][4] = {
{ 0, 1, 2, 3 },
{ 4, 7, 6, 5 },
{ 0, 4, 5, 1 },
{ 3, 2, 6, 7 },
{ 0, 3, 7, 4 },
{ 1, 5, 6, 2 }
};

glGenBuffers(NUM_BUFFERS, buffers);
//Generate NUM_BUFFERS of buffers and put them in buffers array.

glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]);
//bind buffers


glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//allocate space for buffers


glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

Here, we suppose to have a point to a array to specify in which array we will find the data. Then is that should be a pointer to some memory address in server?

I just do not understand that BUFFER_OFFSET(0).

Does that mean that there is always only one Vertex_Array in server and the program will choose that address automatically? The BUFFER_OFFSET(0) just tell you where to start in this array?????????

glEnableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDICES]);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));

Same thing here. We suppose to give a address at the last parameter. But I do not see that BUFFER_OFFSET(0) is a useful address.

Upvotes: 2

Views: 4322

Answers (3)

Bahbar
Bahbar

Reputation: 18015

glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), BUFFER_OFFSET(0))

The last parameter does not point to some memory address. Not directly anyways.

It says "use the offset 0 of the currently bound buffer".

You have called

glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]);

So the coupling of these 2 calls (bind first, VertexPointer second) essentially means "use the address of the buffer whose handle is buffer[VERTICES], offset by 0".

Upvotes: 2

Giawa
Giawa

Reputation: 1381

The offset becomes useful when you have interleaved data, or data in the buffer that is not tightly packed. A stride of zero assumes tightly packed data. An offset of zero tells OpenGL that your data starts right away. An example could be as follows. Using your current method, you would need a separate buffer for vertices and normals. However, you could interleave that data:

vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z

And then you could bind that data to a buffer. Then when you tell OpenGL to bind the buffer you need to let it know the stride and offsets. Assuming you have an array of floats that contains the interleaved vertex and normal data, your example could become

glGenBuffers(NUM_BUFFERS, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(interleaved_data), interleaved_data, GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), BUFFER_OFFSET(0));
glNormalPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), BUFFER_OFFSET(3 * sizeof(GLfloat)); 

Notice the value of stride is 6 * sizeof(GLfloat), which indicates that there are 24 bytes between successive entries in the buffer. And the offset of the normal pointer is 3 * sizeof(GLfloat), which indicates that the normal data is offset by 12 bytes from the start of the buffer.

Hopefully this helps - let me know if I've made a mistake.

Upvotes: 1

Tonttu
Tonttu

Reputation: 1821

If there is a buffer binded, that pointer given to glDrawElements is treated as an offset to that buffer and not as a regular pointer.

BUFFER_OFFSET is needed because the original ARB_vertex_buffer_object extension wanted to use the same function prototype, so it's necessary to convert integer offset to a pointer.

See some more information in OpenGL.org wiki.

Upvotes: 1

Related Questions