Indexed arrays.. pointless?

Started by
12 comments, last by Alex Baker 18 years ago
Maybe im missing something here, but i recently went ahead and put my geometry into indexed arrays, thinking cutting my total verts from 14k to 2k would be a huge performance increase. Then i find out or, am led to believe that OpenGL dosn't support mutliple indexed arrays for the different arrays of information. For example, i have an array of unique verts, uv's, normals and tangents. I also have unique index arrays to access each of these, all the index arrays are the same size. I go ahead and try to implement this into opengl only to find out that i can't do this, and im forced to have ONE index array that indexes all of my arrays. I've looked through all of the functions i can trying to figure out a way around this, and while some seem like they may solve my problem (IE: Interleaved arrays) the way they work leads me to believe they don't really do what i think they do, or i just don't understand how they work. So, if i need one index, to index the vert,normal,uv and tangent arrays, i basically have the same amount of verts, normals, uvs, and tangents as before. Maybe im missing something, but it seems pointless to even use an indexed array in this sense. This puts me back at one vertex, per point on the triangle, which wouldn't be to bad, but then when i reuse that point, i cant make a index represent to spots in two different arrays. I don't see what's so hard about just specifiing multiple index arrays for each type of data, especially if the arrays at least are the same size.
Advertisement
I feel the same way, actually... multiple indicies per vertex attribute do help in lowering memory requirements. But it's not OpenGL's fault -- video hardware simply doesn't support that functionality. This includes DirectX as well.

Supposedly, you can do it with Shader Model 3.0. I haven't looked into the details on how it is done, however.
it's the age odl problem. Use a single index per vertex/normal/uv combination. There are good reasons for doing this though (so all is not lost). Compared to unindexed arrays, this is a fairly big memory saving. The other advantage is that using shared indices reduces the amount of vertex processing required by the GPU (unlike glBegin/glEnd and display lists), so it will be considerably faster in say a static VBO.

You are right, there is no way to use multiple index arrays to access different streams at the same time. The hardware simply doesn't work that way.

It is not pointless though. If you have two vertices that share the same attributes (position, normal, tex coords, etc.. ), you can only store one vertex and use an index to access it from different triangles, rather than repeating that vertex for each triangle that references it. Depending on your type of models, this can be a massive gain. The worst case being something like a cube (you can hardly reuse any vertex since they all have different normals), and best case being something like a heightmap.

Video cards have a vertex transform cache, and that cache uses the index to know if previous vertices have already been transformed or not. Using multiple indices would likely disable that cache, killing all the performance. And obviously using a single index is better than using none. It's a matter of balance..

Y.
alright, first thanks for the quick replys guys.

Now, i went ahead and tried implementing another method of getting the one index array idea. Im still having a hard time comprehending how its supposed to work, but this is what im understanding right now.

I need one number that indexs into an array of verts, normals, uvs, tangents and returns the correct value for the current vertex.

To do this, i wrote a function that takes in the current vert,normal,uv and tangent of the vertex as well as a vector for each property that starts empty for each one. If i can find within each vector the vert,normal,uv and tangent, all at the same index and equal to the ones i passed in, then i return that index, otherwise i push them all on to their individual vectors and return the last index.

I ended up saving 8 verts out of 14,228. Now, im thinking what you guys are saying is only remove dupe vertex positions, and go ahead an just render the duped normals, tangents and uvs?

It just dosnt seem possible for me to be able to have one index that correctly indexes into all four at the right time. I think im missing something important, but like i said, i'm having a hard time understand how this is really supposed to work. thx again.
if you have hard edges like a cube has, don't bother using an indexed array. Simpy use an unidexed. Smooth objects work way better
Just a thought. How do you compare positions, uv, normals and tangents? I'd suggest using a threshold when comparing.

E.g.
(pos1 - pos2).MagnitudeSqr() < 1e-4 and
dot(normal1, normal2) > cos(5.0 degrees).

Of course you can play with the thresholds, in case to not reject too many vertices. But by using a direct comparison of floats (pos1.x == pos2.x) may not give correct results.

Hope that helps a little.

HellRaiZer
HellRaiZer

Well I'd say that you have too many different factors, of course, if you need hard edged lighting between polygons then there is no other way.

If you would for example just take only the position and uv, and then do average for normal and tangents you would end up with much less vertices.

Of course some normals and tangents shouldn't be blended together, but that's just one more parameter.
Quote:Original post by nefthy
if you have hard edges like a cube has, don't bother using an indexed array. Simpy use an unidexed. Smooth objects work way better


Well, the problem is looping through 14k verts for vertex animation sucks, and would be a lot better if i was only looping through the non-duped (2k). My problem is speed here, and im sure i would get a speed increase looping through 2k and not 14k ;)
Quote:Original post by HellRaiZer
Just a thought. How do you compare positions, uv, normals and tangents? I'd suggest using a threshold when comparing.

E.g.
(pos1 - pos2).MagnitudeSqr() < 1e-4 and
dot(normal1, normal2) > cos(5.0 degrees).

Of course you can play with the thresholds, in case to not reject too many vertices. But by using a direct comparison of floats (pos1.x == pos2.x) may not give correct results.

Hope that helps a little.

HellRaiZer


The way i compare, i don't think this would be a problem. I have all the dupes, and to remove dupes, i start with an empty stl vector of positions. I check the vector to see if the position exists, if it does return the index, if not push it on and return the last index.

This works great, i can remove over 10k verts. I can even index the verts, normals, tangents and uvs all correctly.

Now i have the problem of making the indices match up, which is where i get lost. I may try taking tangents out of the equation and see what i end up with.

This topic is closed to new replies.

Advertisement