Search code examples
c++openglopengl-3

glVertexAttribPointer trouble (OpenGL 3.x forward-compatible context)


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?


Solution

  • 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.