1
\$\begingroup\$

The concept of Index buffers is that certain vertices are shared across faces, hence can be reused to save space of duplicated verticies. A vertex is usually more than 12 bytes (depending on the number of attributes, ie. 3* 32-bit floats), while an index could be stored in as little as 1 to 4 bytes (depending on max number of vertices).

Example: A cube consisting of 6 quad-faces without using an index buffer would require 6 * 4 * 12 = 288 bytes But as it only has 8 unique vertices, it could be stored using an index buffer with 4 * 6 indices = 8 * 12 + 4 * 6 = 120 bytes

However for non-shared vertices the space used by the Index Buffer is effectively wasted - because these vertices could've been drawn without an index buffer (if correct ordering in the vertex buffer is given). Considering only the vertex position as attribute, this trade-off would make sense for most meshes - but meshes in the real-world tend to have also other attributes like normals, texture-coordinates etc. Even if a vertex position is shared across faces, it is rare that all other attributes are also shared - hence the vertex needs to be duplicated in the vertex buffer.

Example: A cube with normals has 8 unique vertices, but each of its 6 faces having a different normal vector. So 48 unique vertices are required, if one vertex is 24 bytes this results in = 8 * 6 * 24 = 1152 bytes Using an index buffer the same size is needed plus at least 48 bytes to store the indices = 1200 bytes

Not only would a vertex buffer without index buffer need less memory, it would probably be more cache-friendly as well (as the memory accessed is continous memory).

I try to find out in which scenarios I should use an index buffer instead of a plain vertex buffer, but I failed to find any real-world examples where it would make sense to use an index buffer at all.

My question is: Are there any cases in modern graphics-programming where using an index buffer will actually bring a benefit (ie. is there any advantage which I overlooked)?

\$\endgroup\$
4
  • \$\begingroup\$ What's wrong with the example you gave in the first sentence? \$\endgroup\$
    – Jay
    Commented Mar 15, 2019 at 6:00
  • \$\begingroup\$ @Jay Nothing wrong by itself, but I don't see the field of application for solid colored surfaces without normal. If this rather obscure combination is really the only practical usuage of index buffers, I wonder if this justifies that all modern graphics APIs support this feature. \$\endgroup\$
    – Constantin
    Commented Mar 15, 2019 at 8:03
  • 1
    \$\begingroup\$ The normal can absolutely be a part of the vertex definition, and it's not obscure but relatively common. There are cases that need separated vertices as you've described. But imagine a skinned an animated character, each vertex (position and normal) should be calculated once, instead of each time per triangle. \$\endgroup\$
    – Jay
    Commented Mar 15, 2019 at 8:44
  • \$\begingroup\$ "I don't see the field of application for solid colored surfaces without normal" - cubemaps, skyboxes, shadow maps, particle systems, etc - just because you don't see it, doesn't mean it doesn't exist. As my answer demonstrates, there are actually many practical applications for indexing. \$\endgroup\$ Commented Mar 15, 2019 at 9:29

1 Answer 1

6
\$\begingroup\$

The example you use of a cube is a very specific, and somewhat contrived, one where indexing does not provide it's full benefit. For most real-world examples the constraints you mention do not exist, and indexing has been demonstrated - for approx 20 years - to be effective. This is something that goes back to at least Quake 3 in 1999:

Quake3’s rendering architecture has been defined with the primary goal of minimizing API calls and focusing as much work as possible in a single place to make optimization more productive.

During gameplay, 99.9% of all primitives go through a single API point:

glDrawElements( GL_TRIANGLES, numIndexes, GL_UNSIGNED_INT, indexes );

I'd encourage you to look at examples such as the Stanford Bunny, which is more representative of the kind of data real applications use. That has 35947 vertices and 69451 triangles, or in other words 35947 vertices and 208353 indices. So therefore each vertex is reused on average 5.7 times.

Saving memory is the naive advantage of indexing. The other two advantages, which are far more important, are:

  • Allowing your GPUs vertex cache to work. What this means is that if a recently transformed vertex is reused, it does not need to be transformed again.
  • Concatenating primitives. A mesh composed of multiple strips and fans can be handled in a single draw call instead of multiple, and we all like reducing our draw call count.

The important thing to realise is that even if none of the other advantages apply, being able to concatenate primitives and reduce CPU overhead for a very small trade-off of slightly increased memory usage is a good thing.

So the answer to your question - when does it make sense to use index buffers - is actually almost always.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .