3
\$\begingroup\$

Vertices in 3D models CAN get cut in the process of optimizing 3D geometry, (degenerate vertices) by 3D graphics software (Blender, ...) when exporting because they aren't needed when reusing a vertex for multiple triangles. (In the current case 3D data is exported from Blender as .ply and read by a simple application that displays the 3D model)

Every vertex has a few attributes like position, color, normal, tangent,... But the data for each vertex that is cut through the vertex sharing is lost and is missing in the vertex shader.

Modern shader techniques like Bump or Normal mapping require normals/tangents per vertex which are also cut.

To use complex shader techniques IBOs must not be used? Or is there a way to use IBOs and retain the data per vertex that was origionally lost?

\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

Index buffers are useful because they reduce the amount of vertex data that the GPU must process. First of all, where vertices are reused across multiple triangles, only one copy of the vertex data is needed; since vertex data is typically much larger than index data, that means less memory consumed, and less memory bandwidth required to load the vertex data into the GPU's shader cores.

Second, GPUs have a vertex cache, where recently-transformed vertices are stored and the results can be re-used if that vertex is seen again soon. The index buffer is the tag for this cache - that is, the index is how the GPU tells whether a vertex is the same as one already in the cache.

Now, as you point out, sometimes vertices are not reused due to a UV seam, a hard edge (i.e. a seam in the normals), etc. So vertices must sometimes be duplicated, producing two vertices with the same position but different UVs, normals, etc. However, (a) this often only affects a fraction of the vertices in the mesh, and (b) the vertices still get reused a little.

For example, in a cube model with no UVs or normals, you'd have 8 vertices and 12 triangles, so each vertex would be reused on average 4.5 times (that's 12 * 3 / 8). Adding UVs and normals, so that every face of the cube requires its own vertices, you now have 24 vertices and 12 triangles, so each vertex is reused on average 1.5 times. You have lower vertex reuse, but you still have some reuse, so it's still worthwhile to use an index buffer.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @0xFAIL Vertices can only be reused where all the attributes are the same, yes. \$\endgroup\$ Jun 26, 2013 at 20:13
  • \$\begingroup\$ @0xFAIL Degenerate vertices are used with triangle strips, as basically a hack to let you merge several strips together, by connecting the end of one strip to the beginning of the next with degenerate triangles (which are invisible when rendered). It's a separate issue from vertex reuse in general. \$\endgroup\$ Jun 26, 2013 at 23:15
4
\$\begingroup\$

You need to process exported models to be used in a game. Model editors like Blender or Max are not strictly intended for making real-time simulations. You can use tools like AssImp to read in models in various formats, do a number of post-processing steps (many are built in), and then save it in a format better fitted to your engine. One of these stages will be to properly map vertex position back to its attribute data for all vertices. This is required for a large number of formats which try to optimize for very different needs than high-speed rendering, such as optimizing storage space or something.

So far as degenerate model data goes (more in the context of degenerate triangles) these are to make a single triangle strip in place of multiple triangle strips. Triangle strips are more efficient than triangle list and having a single draw call is significantly more efficient than several. A degenerate triangle allows a triangle strip to "jump" from one strip to another without breaking the stream of vertices. These degenerate triangles are never rendered, don't need vertex attribute data (of course something still needs to be filled in due to how the pipline works), and there's no need to worry about normal mapping or texture lookups for such triangles. Usually you don't actually use a degenerate vertex here, but it's possible (maybe necessary in some cases; I've never written an algorithm to optimize meshes like this myself).

If the data is truly being lost for some reason, try exporting in a differnt format.

\$\endgroup\$
3
  • \$\begingroup\$ Less "fitting the programming language" and more "fitting your renderer and GPU hardware," but yes. And no, IBOs are not useless; the other answer is to me a bit questionable. \$\endgroup\$ Jun 26, 2013 at 17:51
  • \$\begingroup\$ IBOs? You use them to make the vertex submission faster. Why send a shared vertex 4 times instead of once? Since it's faster to use a single draw call, in a model with some shared and some unshared vertices you use an IBO for everything; usually you have way more shared than unshared verts. Shaders have absolutely nothing to do with the value of IBOs at all; IBOs are for optimizing the data upload and input assembly stages before any shader is run. Missing attributes are either fixed by asset conditioning tools or fixed by the artist in the modeler. \$\endgroup\$ Jun 26, 2013 at 18:14
  • 2
    \$\begingroup\$ @0xFAIL You don't have multiple normals per vertex, you just duplicate the vertices. So you have two vertices with the same position but different normals. The triangles on either side of the hard edge would reference the vertex with the correct normal for that triangle. Now the vertex shader can only see one of the two normals, but that's all it needs - there's usually no reason it needs to know about other possible normals at that point. \$\endgroup\$ Jun 26, 2013 at 19:57
0
\$\begingroup\$

If I'm understanding your question correctly you are asking, then yes it is possible by recombining the data into a per vertex data and then eliminating reused vertices.

You can definitely use Index Buffers with modern shader techniques - in fact I'd argue they are more useful as in modern shader techniques you probably won't have per vertex Normals/Tangents/Binormals/BiTangents anyway. Most of those in high end engines are probably written into a texture to be used in per-pixel lighting.

\$\endgroup\$
4
  • \$\begingroup\$ Even if you write things into textures, you need tangents and binormals to access those textures appropriately. Normals are themselves one of those things in a texture, the normal map as it is usually called. \$\endgroup\$ Jun 26, 2013 at 17:52
  • \$\begingroup\$ @SeanMiddleditch ah maybe I'm confused, I was under the impression that you do not need a normals with your vertex points if you provided a normal map - you only needed the point and UV along with an additional UV into the normal map. \$\endgroup\$
    – NtscCobalt
    Jun 26, 2013 at 19:41
  • \$\begingroup\$ @NtscCobalt Normal maps are normally stored in tangent space, so you need per-vertex tangent/bitangent/normal vectors to transform the normal map into whatever space you use for lighting. (Actually, you can get rid of the tangent/bitangent and compute them from per-pixel derivatives, but you still need the normal vector for smooth shading - if you got it from derivatives, you'd have flat shading on every triangle.) \$\endgroup\$ Jun 26, 2013 at 20:04
  • 1
    \$\begingroup\$ @NathanReed ah thank you, well my answer is almost completely wrong then. Well at least I feel like I learned something. \$\endgroup\$
    – NtscCobalt
    Jun 26, 2013 at 20:15

You must log in to answer this question.

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