# Vertices and Index Buffers

This topic is 4175 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Currently my models and maps for the game I'm making have a vertex list, and then a polygon list where each polygon contains 3 indices (for 3 vertices) into the vertex list. So polygon 1 contains vertices 1 2 3...Polygon 2 contains vertices 2 3 4, and so on. This means that polygons are sharing vertices. Do you get faster performance by having polygons share vertices? What if every vertice in my model had a different normal (For whatever reason), or a better example, what if every vertice had a different tangent vector and binormal for bump mapping. I'd have to specify a unique vertex for every polygon. Is that bad? Is the main issue just memory? If I have a unique vertex for every polygon do I need even need an index buffer? I'm confused! Lol, thanks for your help.

##### Share on other sites
I'm not quite sure that I understand what you are asking. But Index buffers are used to optimise memory usages. If you have a vertex that is shared by many polygons it uses less memory if you only specify it once and then just have an id for it (thats the index).

I.e. if the vertex is specified as
float x, y, z; // 12 bytes
float nx, ny, nz; // 12 bytes
float tu, tv // 8 bytes

// total -> 32 bytes

an index is often only a short -> 2 bytes

So if this vertex is shared by 4 polygons the memory usage will be:
Not using index buffers: 32*4 = 128 bytes

If the vertex representation differs you must have two verticies.

Not the best explanation but hope you got something out of it.

Lizard

##### Share on other sites
Ha! I know exactly what you're thinking here 'cos I went through the same phase myself!

The problem is that the api doesn't like shared vertices having different normals, tangents, wotever. So, if you want your vertex to have different normals in different subsets, you'll just have to duplicate the vertex. That's not necessarily a bad thing since most graphics card can push in ridiculously large number of vertices with little overhead.

Index buffers are still a good thing even with large number of duplicate vertices since to manipulate the render buffer you only need to manipulate the indices rather than tinkering with the vertices themsleves.

##### Share on other sites
You'll get better performance if you use VBO's with indexed geometry. This way you leverage the vertex cache of the GPU, so drawing the same vertex twice (the indexed one) doesn't cost that much anymore. You have to draw them with glDrawElements() or glDrawRangeElements(). Many say that the latter gives slightly better performance, but I've always used glDrawElements() because it's easier to setup. For static geometry, I would just use display lists and put regular vertex arrays with indexed geometry in those, cause they're just as fast (even faster sometimes) than VBO's. Just be careful not to flood your GPU's pipeline ofcourse.
Now, if every vertex has a different normal/tangent/binormal, you have to duplicate some vertices in the array or you average the normals together.
Here's some code to duplicate vertices: (I get this question every two weeks or so and I used to have a site but I can't find it anymore)

struct pos {	float x, y, z;    bool operator==( pos const & other ) const     {		return x == other.x && y == other.y && z == other.z;    }};struct uv {	float u, v;    bool operator==( uv const & other ) const     {		return u == other.u && v == other.v;    }};struct color{	float r, g, b;	bool operator==( color const & other ) const	{		return r == other.r && g == other.g && b == other.b;	}};struct vert {	pos p;     uv t;	color c;    bool operator==( vert const & other ) const 	{		return p == other.p && t == other.t && c == other.c;    }};struct two_indices {	unsigned short p;    unsigned short t;	unsigned short c;};int normalize_arraysExt(pos const *posIn, uv const *uvIn,color const *colorIn, two_indices const *ixIn,int ixInCount, vert *vertOut, unsigned short *ixOut){  int oCount = 0;  int oUsed = 0;  for(int ix = 0; ix < ixInCount; ix++)   {	  vert v;	  v.p = posIn[ ixIn[ix].p ];	  v.t = uvIn[ ixIn[ix].t ];	  v.c = colorIn[ ixIn[ix].c ];      for(int f = 0; f < ix; f++) 	  {		  if( v == vertOut[f] ) 		  {			  ixOut[oCount] = f;			  goto next_vert;		  }	  }    	  vertOut[oUsed] = v;	  ixOut[oCount] = oUsed;      oUsed++;   next_vert:      oCount++;  }  assert(oCount == ixInCount);  return oUsed;}

This will work for a vertex array with vertices, texture coords and vertex colors, but can be easily extended to do other things.

Hope I've been able to help,
Jeroen

##### Share on other sites
There are two caches that speed up things when you use vertices: one for the vertex data, and one for the result of the vertex calculation. The second one produces more of a saving, since the vertex shader doesn't need to run again.

So if two triangles use just 4 vertices, the cache will help make this 4 calculations, instead of 6. In theory the cache can help reduce the number of calculations by about 3 times (though you'd have to optimise for this), but even the 4/6 ratio is pretty good.

If you have to have different data for each triangle, i.e. 6 different vertices, then the cache can't work, obviously. On most smooth surfaces, however, you'd actually want normals, etc., to be the same for all triangles using the vertex, since using the same value for nearby triangles is what eliminates discontinuities.