🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How does OpenGL calculates the Layout buffer position for each vertex?

Started by
0 comments, last by babaliaris 3 years, 9 months ago

I'm trying to figure out how OpenGL actually calculates the beginning of each attribute using the layout info I'm providing. I concluded to an equation that seems to work when providing a layout of :

{pos, normal, coord} → {pos, normal, coord} → {pos, normal, coord} → {pos, normal, coord} …

But when I provide the data in a batch way:

{positions} → {normals} → {coordinates}

The formula seems to break. This is the formula

attribute_pos = buffer_begin + i * stride[location] + offset[location]

where i = current vertex shader run , location = the layout location you specify inside the vertex shader.

If for example, you have these data:

            // positions          // normals           // texture coords
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
            0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,
            0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
            0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
            .
            .
            .

First vertex shader run, i = 0:

position_begin[0]   = buffer_begin + 0 * stride[0] + offset[0]
normal_begin[1]     = buffer_begin + 0 * stride[1] + offset[1]
coordinate_begin[2] = buffer_begin + 0 * stride[2] + offset[2]

This will actually give the start address of each attribute correctly for the first shader run and if you try to calculate the next shader run it will still work.

But when providing batch data like this:

unsigned int vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (m_positions.size() + m_normals.size() + m_coordinates.size()), NULL, GL_STATIC_DRAW);



         //Positions.
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * m_positions.size(), &m_positions[0]);
        
        //Normals.
        glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * m_positions.size(), sizeof(float) * m_normals.size(), &m_normals[0]);
        
        
//Texture coordinates.
        glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * (m_positions.size() + m_normals.size()), sizeof(float) * m_coordinates.size(), &m_coordinates[0]);


        
//Positions.
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
        glEnableVertexAttribArray(0);


        //Normals.
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (const void*)(sizeof(float) * m_positions.size()));
        glEnableVertexAttribArray(1);


        //Texture coordinates.
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (const void*)(sizeof(float) * (m_positions.size() + m_normals.size())));
        glEnableVertexAttribArray(2);

The equation seems to work, but if I replace the stride of the positions with 0


         //Positions.
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(0);

The cube still renders correctly!!!

But according to my equation, the above attribute should always give the first position ONLY.

//Total 36 vertices (a cube), stride[0] = 0, offset[0] = 0
position_begin[0]   = buffer_begin + 0 * stride[0] + offset[0] = buffer_begin //First vertex run => first pos.
position_begin[0]   = buffer_begin + 1 * stride[0] + offset[0] = buffer_begin //second vertex run => first pos.
position_begin[0]   = buffer_begin + 2 * stride[0] + offset[0] = buffer_begin //third vertex run => first pos.
.
.
.
position_begin[0]   = buffer_begin + 36 * stride[0] + offset[0] = buffer_begin //36th vertex run => first pos.

As you can see, I always end up getting the beginning of the buffer so this should not work. But the cube is being rendered correctly. So my equation breaks. This seems to work only for the first attribute. If I also replace the stride of the texture coordinates with zero too, then things start to break. So, I can't understand why it works with a stride of zero…

I tried to replace my equations with this:

attribute_pos = buffer_begin + i * size[location] * type[location] + stride[location] + offset[location]

but this makes the stride meaningless. The above equation should work with the batch data for stride = 0 for all the attributes!!!


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

This topic is closed to new replies.

Advertisement