0
\$\begingroup\$

Please consider the following vertex structure

struct vertex {
    vec3 posL, normalL;
};

Using this vertex layout, we can provide the vertex data in an interleaved way, i.e. (posL,normalL),(posL',normalL'),... This works pretty fine in combination with indexed drawing via glDrawElements().

However, if we add texture coordinates to our vertex structure, i.e. consider

struct vertex
{
    vec3 posL, normalL;
    vec2 tex;
};

things get more complicated. Since one and the same vertex (meaning it's position) may participate in a variety of different faces with varying texture coordinates, I wondered how one would provide such vertex data to the vertex buffer.

One solution would be to quit storing the data interleaved and provide it a linear way, i.e. (posL,posL',...),(normalL,normalL',...),(tex,tex',...) where each tuple has the same length. Doing so, we would hold related things together (i.e. the k-th element of each tuple forms exactly one input the vertex shader sees).

But we would push much more data to the pipeline than necessary. So, what's the "ideal" solution to this problem? If one suggests to use different buffers, how does the vertex shader know, that texture coordinate tex at position i in Buffer 2 corresponds to the tuple (posL,normalL) at position j in Buffer 1?

\$\endgroup\$
  • \$\begingroup\$ Interleaved vertexes tend to perform better on modern GPUs due to better cache efficiency. For each vertex processed, the GPU will need to fetch all of its attributes. So it makes sense to keep them packed together. \$\endgroup\$ – glampert Apr 23 '14 at 19:01
2
\$\begingroup\$

There is not ideal way of doing it, this is a common problem with meshes. To solve this there, are two different approaches: Considering that you have a vertex that has to be used with two different textures coordinates here is how you can approach the problem:

1:Duplicate the vertex and assign to each one the different texture coordinates. As a result you will have two vertices with exactly the same position but two different texture coordinates. How you store the vertex data is not really relevant at this point (interleaved or not). There is no way i know right now (someone correct me if i'm wrong) to be able to represent an indexed vertex buffer in order to share vertex position and different texture coordinates.

2:Separate the geometry in multiple parts and draw it with two (or multiple) draw calls but this has a couple of drawbacks. First need to create extra code to be able to share the vertex position, second you need to make multiple draw calls and this hurts performance especially on mobile devices.

I think the first approach is the industry standard because in the end the extra memory used is not much of a problem. One way to overcome the memory usage is to use streaming and it's much easier to use that (not to mention that you can significantly increase the amount of geometry) instead of the second approach in which adds a lot of code complexity.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.