0
votes

By modern standards, the preferred way of rendering polygon meshes seems to involve the use of Vertex Buffer Objects in conjunction with index buffers (ultimately drawn by calls to glDrawElements()), which is exactly why I'm trying to wrap my head around these concepts. Also, I insist on using glVertexAttribPointer() instead of the deprecated glVertexPointer(), glNormalPointer() etc.

I'm using a custom, binary 3d file format (a Wavefront .OBJ derivative), the contents of which can be more or less directly memcpy()'d to a vertex array. Here's how I've declared my vertex structure:

   typedef struct vertex_ {

            float vx,vy,vz;
            float nx,ny,nz;
            float padding[2];  // align to 32 bytes 
   
   } vertex; 

The loadBObj() function returns an index buffer (implemented as a simple array of unsigned short ints), and fills up the vertex array with the associated vertex/normal data (the models used all have been exported to have per-vertex-normals for a smoother shading result).

indices = loadBObj("pharaoh.bobj", false, &VBOid);

The loading code itself is verified to work appropriately.

Now, what's also being done in loadBObj()is a new VBO is being created like so:

    glGenBuffers(1, VBOid);
    glBindBuffer(GL_ARRAY_BUFFER, *VBOid);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*vcount, &vertarray[0].vx, GL_STATIC_DRAW);

AfterloadBObj() is called, an index buffer object (probably shouldn't be referred to as such though) is created as follows:

    glGenBuffers(1, &IBOid);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short int)*qfcount*4, indices, GL_STATIC_DRAW);

OK. When it comes to actually rendering the mesh, I've used the following code:

    #define BUFFER_OFFSET(i) ((char *)NULL + (i))
    ...
    glBindBuffer(GL_ARRAY_BUFFER, VBOid);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(0));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(3*sizeof(float)));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
    glDrawElements(GL_QUADS, qfcount*4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

which results in an absolutely correct geometry, but the shading is not quite right:

  • Here's an image of the model, rendered in immediate mode:

img http://i44.tinypic.com/i36zcg.png

  • here's one produced by the program described above:

img2

Is there something funny going on in my VBO handling?

3
Run it under gDEBugger, or something similar, and verify all the data in the VBO is correct. If it is, time to check shaders. Also, GL_QUADS is deprecated and gone from the core profile.Cat Plus Plus
@CatPlusPlus: alright, I've now thoroughly checked the contents of the VBO (gDEBugger = fantabulous utility btw, cheers), and it seems ok. Now, what exactly do you mean by "checking shaders"?elmov

3 Answers

2
votes

It seems that your normals are not passed through correctly

This is probably caused by the fact that you should have

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

Since you are specifying both 0 and 1 pointers. (currently you only have the first line)

1
votes

Are you using shaders? You're only supposed to use glVertexAttribPointer with shaders, and you have to explicitly tell it which attrib array goes with which input variable. (glGetAttribLocation/glBindAttribLocation).

If you're using fixed pipeline you have to stick to glVertexPointer/glNormalPointer.

0
votes

I think what could have happened here is that the triangle* are reversed. You could test that just by swapping each first with each third vertex.

  • Since you're using quads, that's clearly not the error. But you can try swapping each second with each third vertex.