glVertexAttribPointer

Hello forum,

I am confused about the specification of one of the parameter in the above mentioned function - stride. According to the documentation it says that -

“Specifies the byte offset between consecutive generic vertex attributes. If stride is 0, the generic vertex attributes are understood to be tightly packed in the array. The initial value is 0.”

Is there any graphical explanation so that I can get some insights from the above statement. I have vertex attributes arranged in a struct as follows:


    struct Vertex
    {
        glm::vec3 position;
        glm::vec3 color;
    };

    Vertex mVertices[3];

    GLushort mIndices[3];


What should be the value of the parameter - “stride”. I have the vertex attributes defined as follows for a simple triangle , but the color output is strange.


    //setup the triangle geometry
    mVertices[0].color = glm::vec3(1.0,0.0,0.0);
    mVertices[1].color = glm::vec3(0.0,1.0,0.0);
    mVertices[2].color = glm::vec3(0.0,0.0,1.0);

    mVertices[0].position = glm::vec3(-1,-1,0);
    mVertices[1].position = glm::vec3(0,1,0);
    mVertices[2].position = glm::vec3(1,-1,0);

    //setup the triangle indices
    mIndices[0] = 0;
    mIndices[1] = 1;
    mIndices[2] = 2;



Check the following screen-shot

http://imgur.com/WMgR9PB

I wonder how the black color is appearing from. I defined the color at one end of the triangle to be blue.

Any idea ?

You didn’t show how you actually filled the buffer so all i can do is guess.
It seems that your position data is also used for colors.

mVertices[0].position = glm::vec3(-1,-1,0); //-> clamped to (0,0,0) black
mVertices[1].position = glm::vec3(0,1,0); //-> green
mVertices[2].position = glm::vec3(1,-1,0); //-> clamped to (1,0,0) red

You probably forgot to set the offset parameter in glVertexAttribArray, so that GL actually knows where color values start.

Stride is just the byte difference between two vertex-attributes of the same type.
So how many bytes are between mVertices[n].position and mVertices[n+1].position?
Similar question, how many bytes are between mVertices[n].color and mVertices[n+1].color?
That is exactly the stride parameter for each attribute.

I assume (but don’t know, i don’t use C++ and glm) that your struct Vertex is 24 bytes in size, there are no padding bytes and you filled the buffer with interleaved vertexdata:


byte
0	Position[0]
12	Color[0]
24	Position[1]
36	Color[1]
48	Position[2]
60	Color[2]

That means the first call to glVertexAttribArray for positions attribute has parmeters offset = 0 and stride = 24
and the second call for colors attribute has parameters offset = 12 and stride = 24.

Here goes the snippet that initializes the buffer and assign the data:


void TriangleScene::initialise()
{
    //return if already initialized
    if(mInitialized)
        return;

    if(!initializeOpenGLFunctions())
    {
        std::cerr << "Modern OpenGL Functions could not be initialized." << std::endl;
        std::exit(EXIT_FAILURE);
    }

    GL_CHECK_ERRORS;

    //make the projection and model-view matrix
    //identity matrices
    mProjectionMatrix = glm::mat4(1.0f);
    mModelViewMatrix = glm::mat4(1.0f);

    //load and compile the shaders
    loadShaders();

    //setup the triangle geometry
    mVertices[0].color = glm::vec3(1.0,0.0,0.0);
    mVertices[1].color = glm::vec3(0.0,1.0,0.0);
    mVertices[2].color = glm::vec3(0.0,0.0,1.0);

    mVertices[0].position = glm::vec3(-1,-1,0);
    mVertices[1].position = glm::vec3(0,1,0);
    mVertices[2].position = glm::vec3(1,-1,0);

    //setup the triangle indices
    mIndices[0] = 0;
    mIndices[1] = 1;
    mIndices[2] = 2;

    //check for opengl errors
    GL_CHECK_ERRORS;

    //setup the triangle vao and vbo stuff
    glGenVertexArrays(1,&mVaoID);

    glGenBuffers(1,&mVerticesID);
    glGenBuffers(1,&mIndicesID);

    //get the size of the Vertex struct
    GLsizei stride = sizeof(Vertex);

    glBindVertexArray(mVaoID);

    glBindBuffer(GL_ARRAY_BUFFER,mVerticesID);
    //pass triangle vertices to the buffer object
    glBufferData(GL_ARRAY_BUFFER,  //specifies the target buffer object
                 sizeof(mVertices),//specifies the size in bytes
                 &mVertices[0], // pointer to the data
                 GL_STATIC_DRAW); //usage pattern of the data

    GL_CHECK_ERRORS;

    glEnableVertexAttribArray(GLuint(0));
    glVertexAttribPointer(GLuint(0), //index of the generic vertex attribute to be modified
                          3,//the number of components per generic vertex attribute
                          GL_FLOAT, //the data type of each component in the array
                          GL_FALSE,//if the fixed point data to be normalized or not
                          stride,
                          0);

    GL_CHECK_ERRORS;

    //enable vertex attribute array for the color
    glEnableVertexAttribArray(GLuint(1));
    glVertexAttribPointer(GLuint(1),
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          stride,
                          (const GLvoid*)offsetof(Vertex,color));

    GL_CHECK_ERRORS;

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mIndicesID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(mIndices),&mIndices[0],GL_STATIC_DRAW);

    glDisableVertexAttribArray(GLuint(0));
    glDisableVertexAttribArray(GLuint(1));
    glBindVertexArray(0);

    GL_CHECK_ERRORS;

    mInitialized = true;

}

Vertex = v
Color = c
Normal = [COLOR="#008000"]n[/COLOR]

vvvvvvccccccnnnnnn
Stride is 0 (zero) when it comes to vertices. With color you have stride at 0 and just pointer value which points at the start of the color part. Same thing with the normal.
[STRIKE]vcnvcnvcnvcnvcn
Vertex stride is 0 and pointer is 0. Color stride is sizeof(Vertex) and pointer points to the first color value so the attribute reader knows where to start. Normal stride is sizeof(Vertex) + sizeof(Color) and pointer points to first normal value.[/STRIKE]

Please correct me if I’m wrong.

Color stride is sizeof(Vertex) and pointer points to the first color value so the attribute reader knows where to start. Normal stride is sizeof(Vertex) + sizeof(Color) and pointer points to first normal value.

No. The stride is the same stride for all of the components. The offset is the only thing that is different.

Also, don’t call the position the “vertex”; it’s confusing, since vertices are composed of multiple attributes.

I got lectured and I hope I learned it.
vcn size forms the stride. Pointer offset still stands right?

Vertex Attribute Stride

I’d give him a break on this one. From geometry, “vertex” is really the correct terminology for the position (representing the position of a corner of a geometric shape). Not to mention the original GL APIs to set these vertices are glVertex[1-4][sifd] and glVertexPointer.

All the rest of the data that comes along for the ride with each vertex are “vertex attributes”.

That said, it’s true that newer GL versions (GL3+?) have “promoted” the term vertex to refer to mean all vertex attributes for a vertex “including” position (thus the common API for setting both the position and other attributes: glVertexAttrib*Pointer).

That said, it’s true that newer GL versions (GL3+?) have “promoted” the term vertex to refer to mean all vertex attributes for a vertex “including” position

I wouldn’t call it “promotion” exactly; simply a change in terminology needed to recognize how things work in a shader-based world. Nor would I consider OpenGL 2.0 to be “newer”, and that’s when Vertex Shaders, glVertexAttribPointer, and so forth became core OpenGL functionality. We’re talking 10 years ago, and they were part of ARB_vertex_program before that.

Also, I feel that it’s important to recognize that vertices in OpenGL do not have to have anything even remotely resembling a position. You could generate a position in various shader stages from whole cloth, or you could be doing transform feedback, where you’re not rasterizing data at all.