Why does the order of vertices and indices matter?

Started by
6 comments, last by TheStudent111 8 years, 2 months ago

Why does the order, in which vertices are arranged matter. The following compiles fine


    const GLfloat vertices[] =

    {

        0.5f,  0.5f, 0.0f,   // Top Right    

        0.5f, -0.5f, 0.0f,   // Bottom Right

       -0.5f, -0.5f, 0.0f,   // Bottom Left

       -0.5f,  0.5f, 0.0f    // Top Left

    

    };
 
...
 
    const GLint indices[] =

    {

        0, 1, 3,  // 1st Triangle

        1, 2, 3   // 2nd Triangle

    

    };

while something like this does not,



    const GLfloat vertices[] =
    {        
        0.5f, -0.5f, 0.0f,   // Bottom Right
        -0.5f,  0.5f, 0.0f,   // Top Left
        0.5f,  0.5f, 0.0f,   // Top Right    
       -0.5f, -0.5f, 0.0f   // Bottom Left

    
    };
 
...
 
    const GLint indices[] =
    {
        0, 1, 2,  // 1st Triangle
        3, 1, 2   // 2nd Triangle
    
    };
 
 

What am I missing in terms of a pattern, that I can get out of this.

Advertisement


The following compiles fine

<snip>

while something like this does not,

<snip>

What is the error message you get when compiling?

Hello to all my stalkers.

Not really an error message, its more of a deformed shape. The normal output should be a square that is composed of two triangles. Used Element Buffer Objects to reduce the number of vertices that are stored in the array. Its a more efficient way of drawing something like a square, that uses the same vertices multiple times.


Not really an error message, its more of a deformed shape.

Then it is not a compilation error. Terminology matters :)

That said, it looks like your indices are incorrect.

You seem to have:

Bottom Right - Top Left - Top Right

Bottom Left - Top Left - Top Right

You probably want to swap Top Right with Bottom Right (so 3, 1, 0 for the second triangle).

Hello to all my stalkers.

Sorry, for the confusion.

I am aware the second code snippet is incorrect, but I just want to understand why it is incorrect. How does OpenGL read the vertices and indices? Why does it do it this way?

Each set of three indices correspond to a triangle.

Look more closely at your second case. Your two triangles are overlapping, instead of being adjacent.

Vertex order allows for one implementation of https://en.wikipedia.org/wiki/Back-face_culling .

We arbitrarily define the "front" and "back" of a triangle by using the fact that a triangle's vertices, in order, are either clockwise or counterclockwise when viewed from a camera. Then, our convention is to put all of the "front" faces facing outwards from the object (therefore, backfaces are facing towards the inside of the object). When the GPU decides whether to draw a triangle, we can tell it to only draw it if the "front" is facing towards the camera (by telling it "cull (counter)clockwise triangles").

Graphics APIs that let you change the triangle culling mode usually allow for clockwise, counterclockwise, and don't-cull-either modes.

In games, you can sometimes maneuver your player character "inside" an object, and if that game uses culling (most do), you will be able to see out from the inside, since you're looking at backfaces which are not being drawn.



If you are using indices, then your vertices can be in any order, and the indices control how triangles are formed.

You can put your vertices in any order, and then decide where your triangles go from there:


0 1
2 3
Your indices could be {0, 1, 2} and {1, 3, 2} if you're drawing clockwise.

But you can just as freely put your vertices like this:


0 1
3 2
And define your indices as {0, 1, 3} and {1, 2, 3} for the exact same shape as the first case.



The index array can be read in multiple ways as well. The way you've got here is a "triangle list": The list is read 3 numbers at a time, and each three form a single triangle.

There are other kinds as well, such as:

https://en.wikipedia.org/wiki/Triangle_strip
https://en.wikipedia.org/wiki/Triangle_fan

(the other common ones are as Point list, Line list, Line strip).


For a triangle strip like what you have here, you can think of the internal workings like this:


While index buffer is not empty
{
   if there are less than three indices left, report an error.
   
   let index[0..2] = the next three indices in the index buffer.
   let vertex[0..2] = vertex_buffer[index[0..2]]
   DrawTriangle(vertex[0], vertex[1], vertex[2]);
}

Great response, Nypyren, now everything makes sense.

This topic is closed to new replies.

Advertisement