Vertices and Indices can sound like something really complex and difficult when you are first starting out in 3D. Further complicating things is the enormous number of options surrounding vertices and indices. So, I thought it might be useful to spend some time on the topic. The singular form of the words vertices and indices is vertex and index.
Let’s start by taking a look as vertices. When you first get into 3D, a vector, a point, and a vertex all seem like the same thing. All 3 have points, or positions, in 3D space. They are not the same thing at all, although you may see them treated similarly from time to time. This is because they all have a point, or position.
Everything in your 3D world will be drawn using either lines or triangles. XNA calls lines and triangles “primitives”. A lot of times you will hear triangles referred to as polygons or simply “polys”. But everything you see on the screen is made from triangles. In DX11, even sprites are drawn using triangles and I suspect that XNA does this behind the scenes with sprites. The way these triangles are defined is by 3 points called “vertices”. Now, I just said that a vertex is not a point. That’s true. But, all vertices have a position. They have much more than that though and that is the distinction.
So, 3 vertices define a triangle. You can start by thinking of them as the positions of the corners of the triangle, although this is a bit of an oversimplification.
Vertices can also be used to define the two points that a line draws between when drawing lines.
But, it is important to know that vertices almost always contain additional data. For example, each vertex can have a color. For a line, this will mean that the line will start with one color and change to the other color as it gets closer to the second vertex and its color.
For a triangle, if all 3 vertices have separate colors, you will get a mix of all 3 colors where the color becomes more pure nearer its vertex.
There is another way to “paint” the triangles of your object that is almost always used instead of just paintings vertices with color. This method of painting triangles is known as “texturing,” Texturing basically paints a “texture”, or photograph, across the surface of the triangle and is the primary way that things are “painted” in 3D games these days. The texture is mapped, or attached, to the triangles at the vertices with what is called “UV” coordinates. These UV coordinates are also part of the vertex. Basically, they “pin” the part of the image at the UV coordinate (XY position in the picture) to the vertex. And the picture then stretches between vertices according to the UV coordinates.
A vertex may also contain additional information a normal, a tangent, or other data. In fact, you can even define your own custom vertex format. Normals are used for lighting calculations and basically specify what direction the vertex is “facing”.
And now may be a good time to mention vertex “winding”. Often, it is very important to know which direction a triangle is facing. The way this is determined is by the order that the vertices are defined in (or indexed in). If they are defined in clockwise order, the triangle will point one way and if they are in counter clockwise order the triangle will face the other way. This order the vertices are defined in is called their “winding”.
But, starting out, you can think of vertices mostly as the corner positions of the triangles that compose all of your objects, as long as you understand that they contain a lot more data than that.
You “could” define all your objects just using vertices alone. But you quickly find that a lot of triangles in your objects share vertices. For example, think about a cube. Each square face of the cube will be made up of two triangles. There are 6 faces and each face is 2 triangles. So, that’s 12 triangles in a cube. And if each is defined by 3 vertices, then that’s 36 vertices.
But notice that every corner is one position but if every triangle is made up of 3 vertices, then a single corner will have several vertices that are all redundant. There are only 8 corners. So why does it take 36 vertices to define those corners? That’s 28 vertices more than what you “should” need. And this is still one of the most simple game objects you can have. Can you imagine an object with 10 million vertices and 9 million of them are basically the same vertex? When you consider all the data in these vertices, you can see that they could easily be 20 bytes in size each. So, 9 million wasted vertices would be 180MB just wasted in one object.
And this is where indices come in. Indices allow you to specify what order your vertices get drawn in. This allows you to draw them out of order, but more importantly it means that we only need 8 vertices for our cube and then we can use indices to draw all the triangles of the cube. And an index is just an integer. Each index is considerably smaller than a vertex. And that means substantially less memory used up by your object because it only needs 1 million vertices instead of 10 million and the indices that replaced each vertex are a fraction of the memory used.
With indices, you’re basically just specifying the order of the vertices.
With a Triangle List draw (drawing triangles as a list of triangles) you just specify the vertices in order, as if you were drawing the lines, or edges, of the triangles. So a square might be something like 0,1,2, 2,3,0 for the indices. 0,1,2 defines a triangle in clockwise order (presumably) and 2,3,0 defines another triangle in clockwise order. So, that would be "Draw from vertex 0 to 1 to 2 (triangle) and draw from vertex 2 to 3 to 0 (triangle). But notice the second triangle doubles back and uses two of the vertices from the first triangle. And that makes sense since the two triangles share two vertices when they form a square.
And if you were wondering, the vertex "number" is just whatever
order the vertices were defined in your vertex array or buffer. Vertex 0
is the first one defined followed by vertex 1 and so forth in numeric
And if you were wondering, the vertex "number" is just whatever order the vertices were defined in your vertex array or buffer. Vertex 0 is the first one defined followed by vertex 1 and so forth in numeric order.
A Triangle Strip will also use indices, but instead of using the indices to specify triangles, it assumes that you will always use the previous two indices. So, once you draw your first triangle every vertex results in a triangle after that. So, triangle strips make indices even more efficient.
And that’s basically all there is to vertices and indices.
You generally define them in arrays of vertices and integers (for indices). You could call DrawUserPrimitives() to draw just using vertices. Or you could call DrawUserIndexedPrimitives() to draw using indices. However, you can also store this data on the graphics card and call it from there to make it more efficient. To do that, you would use DrawIndexedPrimitives() or DrawPrimitives(). If you are going to do this, however, you have to transfer the vertices and indices to a buffer and send that data to the graphics card, which is another step or two.
One last thing that people may be confused by starting out: XNA has a model class that you can use to draw models. Internally, this is also using vertices and indices. However, the model class manages all that data for you. In fact, in order to draw a model, you just tell every mesh within the model to draw itself. So, there’s no vertices, indices, or mess. They just simply know how to draw themselves. They are using vertices and indices (and are made up of triangles) too, you just don’t have to deal with them.
Vertices and Indices may sound like something really complicated, but in fact they are fairly straight forward. Think of vertices as the corners of the triangles that make up every object drawn on the screen. And think of indices as the order the vertices are drawn in.
Here we examine them in more detail.