4

I have trouble rendering some geometry by using a vertex buffer object. I intend to draw a plane of points, so basically one vertex at every discrete position in my space. However, I cannot render that plane, as every time I call glDrawElements(...), application crashes returning an access violation exception. There must be some mistake while initialization, I guess.

This is what I have so far:


#define SPACE_X 512
#define SPACE_Z 512

typedef struct{
    GLfloat x, y, z; // position
    GLfloat nx, ny, nz; // normals
    GLfloat r, g, b, a; // colors
} Vertex;

typedef struct{
    GLuint i; // index
} Index;

// create vertex buffer
GLuint vertexBufferObject;
glGenBuffers(1, &vertexBufferObject);

// create index buffer
GLuint indexBufferObject;
glGenBuffers(1, &indexBufferObject);

// determine number of vertices / primitives
const int numberOfVertices = SPACE_X * SPACE_Z;
const int numberOfPrimitives = numberOfVertices; // As I'm going to render GL_POINTS, number of primitives is the same as number of vertices

// create vertex array
Vertex* vertexArray = new Vertex[numberOfVertices];

// create index array
Index* indexArray = new Index[numberOfPrimitives];

// create planes (vertex array)
// color of the vertices is red for now
int index = -1;
for(GLfloat x = -SPACE_X / 2; x < SPACE_X / 2; x++) {
    for(GLfloat z = -SPACE_Z / 2; z < SPACE_Z / 2; z++) {
        index++;
        vertexArray[index].x = x;
        vertexArray[index].y = 0.0f;
        vertexArray[index].z = z;
        vertexArray[index].nx = 0.0f;
        vertexArray[index].ny = 0.0f;
        vertexArray[index].nz = 1.0f;
        vertexArray[index].r = 1.0;
        vertexArray[index].g = 0.0;
        vertexArray[index].b = 0.0;
        vertexArray[index].a = 1.0;
    }
}

// bind vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);

// buffer vertex array
glBufferData(GL_ARRAY_BUFFER, numberOfVertices * sizeof(Vertex), vertexArray, GL_DTREAM_DRAW);

// bind vertex buffer again
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);

// enable attrib index 0 (positions)
glEnableVertexAttribArray(0);

// pass positions in
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), vertexArray);

// enable attribute index 1 (normals)
glEnableVertexAttribArray(1);

// pass normals in
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertexArray[0].nx);

// enable attribute index 2 (colors)
glEnableVertexAttribArray(2);

// pass colors in
glVertexAttribPointer((GLuint)2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertexArray[0].r);

// create index array
for(GLunit i = 0; i < numberOfPrimitives; i++) {
    indexArray[i].i = i;
}

// bind buffer
glBindBuffer(GL_ELEMENET_ARRAY_BUFFER, indexBufferObject);

// buffer indices
glBufferData(GL_ELEMENET_ARRAY_BUFFER, numberOfPrimitives * sizeof(Index), indexArray, GL_STREAM_DRAW);

// bind buffer again
glBindBuffer(GL_ELEMENET_ARRAY_BUFFER, indexBufferObject);

// AND HERE IT CRASHES!
// draw plane of GL_POINTS
glDrawElements(GL_POINTS, numberOfPrimitives, GL_UNSIGNED_INT, indexArray);

// bind default buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// delete vertex / index buffers
glDeleteBuffers(1, &vertexBufferObject);
glDeleteBuffers(1, &indexBufferObject);

delete[] vertexArray;
vertexArray = NULL;

delete[] indexArray;
indexArray = NULL;
genpfault
  • 51,148
  • 11
  • 85
  • 139
Walter
  • 396
  • 1
  • 5
  • 16
  • Please always mention which version of OpenGL you're targetting - 3.x is a bit vague. BTW- it's good practice to create and bind a vertex array object before any `glVertexAttribPointer` or `glEnableVertexAttribArray`. You're probably using OpenGL compatibility profile, so you didn't receive an error because of that. – Kos Dec 03 '10 at 20:49
  • Fair enough. I guess 3.x is a bit vague. I figured that there are major differences between even minor versions of GL. So, currently I am using OpenGL 3.3. – Walter Dec 06 '10 at 00:28

3 Answers3

6

When you are using buffer objects, the last parameters in the gl*Pointer and 4th parameter in glDrawElements are no longer addresses in main memory (yours still are!), but offsets into the buffer objects. Make sure to compute these offsets in bytes! The "offsetof" macro is very helpful there.

ltjax
  • 15,837
  • 3
  • 39
  • 62
  • That's right - if any VBO is bound to `GL_ELEMENT_ARRAY_BUFFER`, then the last argument uses the buffer's relative position as addressing base. Value `0` means "the beginning of currently bound VBO". Operator `offsetof` will indeed help you. – Kos Dec 03 '10 at 20:52
  • That's an interesting point. So if I understand that right, for the colors it should look like this: glVertexAttribPoint(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)(offsetof(Vertex, r))); Is that correct? – Walter Dec 06 '10 at 09:50
  • You are right! That's the solution to my problem! It was not only the fact that I wrongly used glEnableClientState(...), but I also misunderstood the parameters you mentioned. Thanks for that hint. My application works fine now... – Walter Dec 06 '10 at 10:13
  • Its the forth parameter to glDrawElements. Not the third. – user492238 May 29 '13 at 17:29
0

Look at the second example on this page and compare it to what you did: http://www.opengl.org/wiki/VBO_-_just_examples

And you have one typo: GL_DTREAM_DRAW.

Bojan
  • 736
  • 8
  • 18
  • It seems as I didn't see the wood for the trees. I knew that page, but for some reason I had overseen the fact that "glEnableClientState(...)" is deprecated! That's kinda embarrassing. Sorry for bothering you. – Walter Dec 03 '10 at 09:17
  • Was that the only problem? Is your code working properly now? – Bojan Dec 03 '10 at 09:23
  • Well, it works somewhat. I have some other problems now. After having got rid of the glEnableClientState(...), I was actually able to run the application for the first time. However, it doesn't work as expected since it crashes after some time. So, I try to figure what exactly causes the crash. If I omit the creating of the vertex buffer object and the drawing of its vertices, the application works fine on a good speed. But as soon as I add the above code, it takes maybe 15 seconds and the application crashes. – Walter Dec 05 '10 at 23:59
0

The method glEnableClientState(...) is deprecated! Sorry, for some reason I had overseen that fact.

Walter
  • 396
  • 1
  • 5
  • 16
  • 1
    glEnableClientState is not only deprecated, but incorrect here- remember that you want to point to vertices in a VBO (so on the GPU's memory, not the client's memory). That's no longer client state if it's in a VBO. :) – Kos Dec 03 '10 at 20:48