TATN
TATN

Reputation: 1269

C++ OpenGL - Vertex Color

I'm playing around with OpenGL vertex color. Basically, I drew a square consisted of 2 triangles. I were able to color up the 1st triangle the way I wanted, but the 2nd triangle didn't color up the way I expected. I have been researching the problem for the past 2 days but I couldn't figure it out so I'm asking for some guidance in here.

Here is my code:

void Construct_Cube()
{
    //---------------------
    //Init cube's vertices

    float Vertices_Temp[] = 
    {
        0, 0, 0, //bottom-left corner
        0, 1, 0, //top-left
        1, 1, 0, //top-right
        1, 0, 0  //bottom-right
    };

    for(int i = 0; i < (sizeof(Vertices_Temp) / sizeof(GLfloat)); i++)
    {
        Vertices_Cube.push_back(Vertices_Temp[i]);
    }

    //---------------------------
    //Init cube's draw order list
    int tempOrder[] = { 0, 1, 2, 0, 3, 2};

    for(int i = 0; i < (sizeof(tempOrder) / sizeof(int)); i++)
    {
        drawOrder_Cube.push_back(tempOrder[i]);
    }

    //------------------
    //Init cube's color
    Color_Cube.resize(18);

    //Color of each triangle (Red-Green-Yellow)
    for(int i = 0; i < 18;)
    {
        Color_Cube[i++] = 1.0f;
        Color_Cube[i++] = 0.0f;
        Color_Cube[i++] = 0.0f;

        Color_Cube[i++] = 0.0f;
        Color_Cube[i++] = 1.0f;
        Color_Cube[i++] = 0.0f;

        Color_Cube[i++] = 1.0f;
        Color_Cube[i++] = 1.0f;
        Color_Cube[i++] = 0.0f;
    }

    glGenVertexArrays(1, &VAO_Cube);
    glBindVertexArray(VAO_Cube);

    //-------------------
    //Buffer for vertices
    glGenBuffers(1, &VBO_Cube_Vertices);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_Cube_Vertices);
    glEnableVertexAttribArray(0);

    //Passing CartesianSys coord data into the ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, (Vertices_Cube.size())*sizeof(float), &Vertices_Cube[0], GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); //size = 3 (X,Y,Z)

    //----------------
    //Buffer for color
    glGenBuffers(1, &VBO_Cube_Color);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_Cube_Color);
    glEnableVertexAttribArray(1);

    glBufferData(GL_ARRAY_BUFFER, (Color_Cube.size())*sizeof(float), &Color_Cube[0], GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, (void *)36); //size = 3 (R,G,B)

    glBindVertexArray(0); //Unbind VAO
}

void draw()
{
    glBindVertexArray(VAO_Cube); //Bind VAO
    glDrawElements(GL_TRIANGLES, drawOrder_Cube.size(), GL_UNSIGNED_INT, &drawOrder_Cube[0]);
    glBindVertexArray(0); //Unbind VAO
}

This was what it looked like:

enter image description here

The 1st triangle had the correct colors: "Red, Green, Yellow" respectively at "Bottom left, Top left, Top right".

However, the 2nd triangle didn't have the correct color: "Red, Black, Yellow(?)" instead of "Red, Green, Yellow" at "Bottom left, Bottom right, Top right".

Initially, I thought maybe I missed some color values in the color array (hence, it appeared "Black" since "0" is the default value). However, my color array (Color_Cube[]) was properly initialized: 18 color elements for the 6 vertices of my square.

However, after playing with the color array a bit, I noticed something weird:

If I only initialize the first 9 elements of the array, my square turned all black!

for(int i = 0; i < 9;)
{
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;
    Color_Cube[i++] = 0.0f;

    Color_Cube[i++] = 0.0f;
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;

    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;
}

Why did it turn all black? Was it supposed to color up the 1st triangle?

Then, if I initialize the last 9 elements of the array, the square colored up exactly like it was before (1st triangle has the correct color, but not the 2nd triangle)

for(int i = 9; i < 18;)
{
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;
    Color_Cube[i++] = 0.0f;

    Color_Cube[i++] = 0.0f;
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;

    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 1.0f;
    Color_Cube[i++] = 0.0f;
}

Why did it color up both triangles when I only passed in color for the last 3 vertices? Was it supposed to make the 1st triangle black and the 2nd triangle "Red, Green, Yellow"?

It seemed like the first 9 elements of the color array were totally ignored. Why???

So, I was stumped there. I thought maybe I made a mistake in the offset values of glVertexAttribPointer(). However, after double checking those functions, I didn't see any thing wrong, or maybe I'm missing something:

//Buffer for vertices
glEnableVertexAttribArray(0);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);

//Buffer for color
glEnableVertexAttribArray(1);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, (void *)36);

I'm not using the alpha value, so I have 18 floats total in the vertex array (first 9 floats are the triangle coordinates and last 9 floats are the triangle color. The vertex array starts at location 0, while the color array starts at location 36).

What am I missing here? For the past 2 days, I couldn't figure out what went wrong, so I came here asking for some pointer and guidance.

Thank you in advance.

Upvotes: 2

Views: 7933

Answers (1)

bwroga
bwroga

Reputation: 5459

When you call glVertexAttribPointer for the colors, the last parameter (pointer) should be 0 in your case. Pointer will be the offset in bytes from the beginning of the color buffer (not the vertex array) to the start of the significant data. The colors in Color_Cube start at byte 0.

When you specify a pointer of 36 bytes, you are saying that the color data starts at the 36th byte of Color_Cube, which is actually the 4th color. There are only 3 colors from this point on. That is why one corner is black: there is no color for that vertex. When you initialized Color_Cube with only the first three colors, there were no more colors from the 36th byte onward, and the whole square turned black.

Also:

Vertices_Cube has 12 elements, but Color_Cube has 18. Since you only have four vertices in Vertices_Cube, you should have only four colors in Color_Cube, since you are using the same index buffer to refer to the vertex and color buffers.

Upvotes: 3

Related Questions