1
\$\begingroup\$

I'm trying to draw a simple triangle using the following vertices:

std::vector<VertexFormat> vertices;
vertices.push_back(VertexFormat(glm::vec3(0.25, -0.25, 0.0),
    glm::vec4(1, 0, 0, 1)));
vertices.push_back(VertexFormat(glm::vec3(-0.25, -0.25, 0.0),
    glm::vec4(0, 1, 0, 1)));
vertices.push_back(VertexFormat(glm::vec3(0.25, 0.25, 0.0),
    glm::vec4(0, 0, 1, 1)));

The corresponding Vertex format is given by the following struct:

struct VertexFormat
{
    glm::vec3 position;
    glm::vec4 color;

    VertexFormat(const glm::vec3 &iPos, const glm::vec4 &iColor)
    {
        position = iPos;
        color = iColor;
    }
};

The first call to glVertexAttribPointer() is easy since the position vector appears first in the struct, the call is as follows:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0)

The second call to glVertexAttribPointer() should be made specifying a suitable offset for the color attribute of a vertex. Since the color vector appears after the position, then such offset should be given by sizeof(glm::vec3). The corresponding call is:

glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(sizeof(glm::vec3)))

The output of the program using these parameters is:

enter image description here

This output is wrong. There are only two colors (green and blue) and the colors are in the wrong position, note that the bottom-left vertex is blue, but according to the code the vertex should be green.

If the offset is changed to sizeof(glm::vec4) the call is:

glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(sizeof(glm::vec4)));

And the triangle is rendered correctly

enter image description here

So, Is my understanding of the offset parameter wrong? Why using an offset with the size of a vec4 gives the right output?

Any help would be appreciated.

P.S. Sorry for the bad english.

Edit: After reading the answer of Fibbles, and the comments of Fuzz Logic, I checked the size of the VertexFormat struct. A sizeof() gives a size of 32 bytes for a 32 bit executable. So padding is indeed the problem here. Using the macro suggested by Fibbles solves the problem. Thanks for everything guys!

\$\endgroup\$
3
\$\begingroup\$

Your struct is likely being padded by the compiler. The only guarantee offered by a struct is that its members will be sequential in the order they are declared. Compilers are free to add as much or as little padding as they like.

C and C++ contain a handy macro for determining offsets within structs. I'd recommend using it rather than manually working out the offsets because your code will remain correct even if you later add or remove members of the struct.

glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid*)offsetof(VertexFormat, color));
\$\endgroup\$
  • 1
    \$\begingroup\$ To elaborate a bit on why it would be padding anything, since 3 floats is 12 bytes, it is probably packing on 8byte boundaries (64bit), so the first vec3 is stored as 16bytes instead of just the 12 that is needed. 32bit systems/code normally pack data on 4byte boundaries. They do this for efficiency of accessing memory. \$\endgroup\$ – Fuzzy Logic Aug 24 '15 at 5:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.