Advertisement

UV Coordinates by Vertex not Index dilemma (can't pass UV's per index, only by vertex)

Started by February 07, 2025 10:51 AM
4 comments, last by shrink_tubing 22 hours, 19 minutes ago

Hi there!,

I'm sure an expert will know straight away what I'm going to ask. Nevertheless I'll ask it anyway as I would like to have this clear in my mind, as it has been a very confusing topic for me.

So far I've been working with per vertex normals rendering simple meshes and in some cases even having some fun. All seems to have just about worked up to now. However I've recently come across what I think is an old dilemma in graphics programming which is: what do you do when you want to wrap a texture around a model (say like a UV map) and some of the vertices then require multiple UV coordinates. A cube seems to be a good example of this happening.

Even if you just unwrapped the sides (and not the upper and lower surface) you would still have this problem as the first and last points in the UV map would coincide with only one vertex.

I was hoping perhaps the API (I'm using DirectX) would allow me to specify UV coordinates per index, which would solve this problem. I'm discovering that you cannot do that. Maybe even if you could it doesn't seem to be the conventional answer to this problem. It appears one has no choice but to use duplicate vertices to get around this problem.

I'm ok with that up to the point when one has to consider animation. I was always of the understanding that duplicate vertices would mean you get big tears in the mesh when animating at joints in the model.. A shoulder to an arm seems like a spot where this might happen.

However I understand (I think) that if you use mesh skinning, where the whole model is one complete entity that is not separated into groups; then you do not experience tearing. I guess this is because duplicate vertices are right on top of each other and will thus be transformed almost identically by the algorithm.

Perhaps I have answered my own question, but it would be nice have this confirmed by a more experienced person, just so I have it clear in my head, as this been a very confusing problem for me :(

Many Thanks 🙂

shrink_tubing said:
I was always of the understanding that duplicate vertices would mean you get big tears in the mesh when animating at joints in the model.. A shoulder to an arm seems like a spot where this might happen.

No, it does not happen if all your duplicates of a vertex have the same bone indices and weights. So that's never a problem in practice.

shrink_tubing said:
I guess this is because duplicate vertices are right on top of each other and will thus be transformed almost identically by the algorithm.

They don't need to be close in memory, they don't need to be on the same mesh even. They only need the same intial position and the same animated transformation applied to them.
Animation is not affected from duplicated vertices.

shrink_tubing said:
Perhaps I have answered my own question

I think the origin of the ‘problem’ is that we usually start with simple models, e.g. a cube.
When it turns out we have to duplicate each vertex 3 times, it feels inefficient or cumbersome. And it's indeed arguable.

But as we increase detail and complexity of our models, it shows duplication is indeed the best way to do it, because:

Duplication only happens along UV chart or material boundaries, plus eventually at sharp edges.
Thus only a small fraction of vertices will be duplicated, and it's only the duplicated position which we could eventually spare.
But if we try to share, we need more data (multiple indices per vertex for pos, norm, UV, etc.).
So we would end up doing still the same amount of operations, but processing more memory with complex access patterns.
So in practice, for almost any model, duplication is more efficient. (Minecraft voxels is an exception for example)

shrink_tubing said:
I was hoping perhaps the API (I'm using DirectX) would allow me to specify UV coordinates per index, which would solve this problem. I'm discovering that you cannot do that.

It should be possible if you implement yourself: In the VS, use the index on a custom indirection table to get the UV index, then fetch custom UVs.

Now compare the memory access patterns in the general case:

Duplication: Fetch pos, norm and UV using the given index. Simple and ideal.

Custom Sharing: Fetch the indices from indirection tables, then fetch the vertex data. That's more memory we need, and the access pattern is much more random. Complicated and inefficient.

Advertisement

@JoeJ That's an amazing answer Joe, better than I could have even hoped for. So also it seems that the idea of not using duplicates, in the end isn't even more efficient at all.

Thanks very much 🙂

There are tools that can split models out there. I have my own split code if a vertex tangent, uv coord etc require splitting a vertex into two. Like he said above, cache data is small. Most modern CPU's still like 32KB L1 Cache. You want streamlined continuous data going in and out. Indexing vertices is about efficiency in not re-running the same vertex multiple times. If the vertex now has multiple data branches, then it's trying to resolve grabbing data at random spots and be run again. Once Vertex 0 is operated on and cached, you want to be done with it to be fetched later if that vertex belongs to many triangles.

NBA2K, Madden, Maneater, Killing Floor, Sims

Thanks for your reply adam! I made sure I clicked like on it 🙂

Advertisement