elmov
elmov

Reputation: 286

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:

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

img2

Is there something funny going on in my VBO handling?

Upvotes: 0

Views: 1457

Answers (3)

Tim
Tim

Reputation: 35923

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.

Upvotes: 1

cooky451
cooky451

Reputation: 3510

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.

Upvotes: 0

vmpstr
vmpstr

Reputation: 5211

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)

Upvotes: 2

Related Questions