problem with glVertexAttribPointer for normal attr

well, since glVertexPointer(), glNormalPointer() and so on are deprecated a long time now I was doing some tests to redraw my elements with the generic glVertexAttribPointer(). It turns out that it works nice for vertex geometry (positions) but not for normal attributes. Here’s a sample code (i copy from here with minor changes):


struct MyVertex
{
  float x, y, z;        //Vertex
  float nx, ny, nz;     //Normal
};

MyVertex pvertex[3];
//VERTEX 0
pvertex[0].x = -1.0f;
pvertex[0].y = 0.0f;
pvertex[0].z = 0.0f;
pvertex[0].nx = 0.0f;
pvertex[0].ny = 0.0f;
pvertex[0].nz = 1.0f;
//VERTEX 1
pvertex[1].x = 1.0f;
pvertex[1].y = 0.0f;
pvertex[1].z = 0.0f;
pvertex[1].nx = 1.0f;
pvertex[1].ny = 0.0f;
pvertex[1].nz = 0.0f;
//VERTEX 2
pvertex[2].x = 0.0f;
pvertex[2].y = 1.0f;
pvertex[2].z = 0.0f;
pvertex[2].nx = 0.0f;
pvertex[2].ny = 1.0f;
pvertex[2].nz = 0.0f;

int vbo
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(MyVertex)*3, &pvertex[0].x, GL_STATIC_DRAW);

ushort pindices[3];
pindices[0] = 0;
pindices[1] = 1;
pindices[2] = 2;

int ibo
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*3, pindices, Gl.GL_STATIC_DRAW);

define BUFFER_OFFSET(i) ((char *)NULL + (i))

//OPTION 1: deprecated way
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(12));

//OPTION 2: new generic way
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MyVertex), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MyVertex), BUFFER_OFFSET(12));


//draw
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);

glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

well, using option 1 I obtain the triangle with the fading light as expected (given the normals I set). However, using option 2 I do have the triangle but with flat/constant light over the entire triangle’s surface, as if no normal was set. If I mix the normal part of option 1 with the vertex part of option 2 it works again. So, there’s something I’m not doing well for the normals, but I don’t know what. I’ve tried several different numbers for the index of normals, but nothing works. Any ideas?

Btw, since these are generic functions, how does they know that, for example, the index number 0 is for geometry and index number 1 for normals? Are these default numbers? I tried numbers 1 and 2 respectively and nothing was draw; then I tried 1 for geometry and 0 for normal and a triangle shows up, but with flat light face and with coordinates corresponding to those of the normal vectors. Then, this might mean that somehow the number 0 is dedicated to geometry (position).

leo

Btw, since these are generic functions, how does they know that, for example, the index number 0 is for geometry and index number 1 for normals?

It doesn’t; that’s your problem.

When you link a program, each vertex attribute is assigned an attribute index. You can query this index with glGetAttribLocation. You can either assign vertex attributes to an index (either by using glBindAttribLocation or directly in the shader with the newer GL_ARB_explicit_attrib_location extension), or you can allow GLSL to automatically assign an index. If you do the latter, you will need to query it.