indices per attribute impossible?

Started by
12 comments, last by Falken42 18 years, 4 months ago
I've been using VBOs to store (for the time being) just indices and vertex data, and have decided to add vertex colors into the mix. I went back and took a look at how to setup glColorPointer and then realized that the indicies that I would be passing to glDrawElements only represent the index into both arrays, not an individual index for vertex and color separately! This means that a large number of vertices (and colors) will have to be duplicated, because I cannot index through both arrays with different indicies per vertex. For example, a simple cube with only 8 vertices where each face had a different color would end up requiring 8*6=48 vertices (even though the actual vertex positions are the same) because the color table requires different values for each vertex. [ Edit: Actually not 48, but 24. See my reply below. ] Sorry, I come from a GameCube background where we were able to do this. :) Is there something I'm overlooking, or perhaps an extension which provides this functionality? Or is this just impossible under OpenGL? (I'd also like to know if it's possible or not under DirectX if anyone else out there knows the answer.) [Edited by - bpoint on November 30, 2005 3:48:07 AM]
Advertisement
no, u have to duplicate the vertices
(its how the hardware works so it aint possible in d3d either)

Urggh... I was hoping you wouldn't say that.

I know the GameCube used a specialized ATI chipset, but I'd presume that after 3+ years something as useful as having multiple indices per attribute would have at least made it into consumer-level hardware by now.

*grumble*
Future version of D3D for PC will most probably allow for manual vertex fetching from within vertex shader. You could use vertex texture fetch (within vertex shader) nowadays, but it won't probably be an optimal solution.

Edit: Oops, somehow I thought I was on another forum ;)
Maciej Sawitus
my blog | my games
Quote:Original post by bpoint
Urggh... I was hoping you wouldn't say that.

I know the GameCube used a specialized ATI chipset, but I'd presume that after 3+ years something as useful as having multiple indices per attribute would have at least made it into consumer-level hardware by now.

*grumble*


Sorry to be pedantic, but no it doesn't.
NGC uses an ArtX chip, which firm was later bought by ATI (some months before the NGC release), so it has nothing to do with ATI PC products. (But is related to XBox & Revolution GPUs)
-* So many things to do, so little time to spend. *-
Is there anyone other than me who thinks that having separate indicies for each attribute would be incredibly useful? I guess you'd have to actually use it first to realize the amount of data it can save. :)

MickeyMouse's comment on pulling vertices from a vertex shader sounds interesting though... I wonder how long until something like that gets implemented.

I don't exactly know how OpenGL extensions are decided upon, but I'd be more than willing to put together an extension specification _just_ to have future drivers and hardware vendors support this functionality.

Comments, anyone?
Quote:Original post by bpoint
I've been using VBOs to store (for the time being) just indices and vertex data, and have decided to add vertex colors into the mix.

I went back and took a look at how to setup glColorPointer and then realized that the indicies that I would be passing to glDrawElements only represent the index into both arrays, not an individual index for vertex and color separately! This means that a large number of vertices (and colors) will have to be duplicated, because I cannot index through both arrays with different indicies per vertex.

For example, a simple cube with only 8 vertices where each face had a different color would end up requiring 8*6=48 vertices (even though the actual vertex positions are the same) because the color table requires different values for each vertex.

Sorry, I come from a GameCube background where we were able to do this. :)

Is there something I'm overlooking, or perhaps an extension which provides this functionality? Or is this just impossible under OpenGL? (I'd also like to know if it's possible or not under DirectX if anyone else out there knows the answer.)


I am not understanding how you are getting 48? You don't create new vertices after you specify them unless you are tesselating or doing a displacement mapping of some kind? If you have 8 vertices then you have 8 sets of vertex data which includes position, color, texture coords, secondary color, normals. For color OpenGL needs the color per vertex if I am right (Please correct me if I am wrong) to do shading from vertex to vertex if you declare a new color at each vertex...

I apologize -- I was wrong about the original calculation of 48. A single vertex would be shared by only three polygons, not 6, so the actual number of required vertices is 8*3=24. Regardless, vertex data still needs to be unnecessarily duplicated.

Anyway, I'll explain. Given a simple cube, with 8 vertices, and the indices to render it (ignore the vertex winding order for example's sake):

Vector3 verts[8] = {    { -1.0f, -1.0f, -1.0f },    { -1.0f, -1.0f,  1.0f },    { -1.0f,  1.0f, -1.0f },    { -1.0f,  1.0f,  1.0f },    {  1.0f, -1.0f, -1.0f },    {  1.0f, -1.0f,  1.0f },    {  1.0f,  1.0f, -1.0f },    {  1.0f,  1.0f,  1.0f }};u16 indices[4][6] = {    0, 1, 2, 3,    4, 5, 6, 7,    0, 1, 4, 5,    2, 3, 6, 7,    0, 2, 4, 6,    1, 3, 5, 7};


This can now be rendered with:

glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, verts);for (int t = 0; t < 6; t++)    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, &indicies[t]);


Now I want to add color per vertex, with a specific color per face. This means that each vertex requires its own color. Since indicies only represent a vertex and not an individual attribute, the vertices will need to be duplicated for each color that is different. This is best shown by using interleaved data:

typedef struct{    Vector3 pos;    u32 rgba;} Vertex;Vertex verts[24] = {    { { -1.0f, -1.0f, -1.0f }, RED },    { { -1.0f, -1.0f,  1.0f }, RED },    { { -1.0f,  1.0f, -1.0f }, RED },    { { -1.0f,  1.0f,  1.0f }, RED },    { {  1.0f, -1.0f, -1.0f }, GREEN },    { {  1.0f, -1.0f,  1.0f }, GREEN },    { {  1.0f,  1.0f, -1.0f }, GREEN },    { {  1.0f,  1.0f,  1.0f }, GREEN },    { { -1.0f, -1.0f, -1.0f }, BLUE },    { { -1.0f, -1.0f,  1.0f }, BLUE },    { {  1.0f, -1.0f, -1.0f }, BLUE },    { {  1.0f, -1.0f,  1.0f }, BLUE },    { { -1.0f,  1.0f, -1.0f }, YELLOW },    { { -1.0f,  1.0f,  1.0f }, YELLOW },    { {  1.0f,  1.0f, -1.0f }, YELLOW },    { {  1.0f,  1.0f,  1.0f }, YELLOW },    { { -1.0f, -1.0f, -1.0f }, CYAN },    { { -1.0f,  1.0f, -1.0f }, CYAN },    { {  1.0f, -1.0f, -1.0f }, CYAN },    { {  1.0f,  1.0f, -1.0f }, CYAN },    { { -1.0f, -1.0f,  1.0f }, MAGENTA },    { { -1.0f,  1.0f,  1.0f }, MAGENTA },    { {  1.0f, -1.0f,  1.0f }, MAGENTA },    { {  1.0f,  1.0f,  1.0f }, MAGENTA }};


As you can see, there are three times the number of vertices required than would be necessary if the position and color data were split into different buffers and likewise indexed separately. On the GameCube, we were able to do this:

Vector3 verts[8] = {    { -1.0f, -1.0f, -1.0f },    { -1.0f, -1.0f,  1.0f },    { -1.0f,  1.0f, -1.0f },    { -1.0f,  1.0f,  1.0f },    {  1.0f, -1.0f, -1.0f },    {  1.0f, -1.0f,  1.0f },    {  1.0f,  1.0f, -1.0f },    {  1.0f,  1.0f,  1.0f }};u32 colors[6] = {    RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA};


And then send two indicies per vertex. While this is a fairly simple test case, larger models might be able to have a decent amount of unnecessary data trimmed down. Skinned models might not benefit that _much_ from having separate index buffers because most polygons are joined together with the same normal, same vertex color, and same texture coordinate. Basically any vertex that does not share the _exact_ same attributes for all polygons attached to it needs to be duplicated.

Technically, this could be accomplished under OpenGL as well by maintaining multiple index buffers and calling glColorPointer after each call to glDrawElements. This would allow the same vertex buffer to be used while referencing different colors, but this is a fairly specialized case and not very efficient.

I also don't think that it would be that hard to implement from a hardware perspective. There are already pointers to different attribute buffers, so why aren't there multiple indicies for each of those attributes?
I definitely agree that there should be a way to do this, I have commonly wished it were possible, because most modeling formats and models have more texture coords then vertices because they are specialized for each face. If we could specify which color/texcoord/vertex indices separately it would be much easier to render these. To bad there isn't a way presently.
"I seek knowledge and to help those who also seek it"
Exactly -- changes in texture coordinates also requires vertex duplication. An extension like this would definitely cut down on some excess memory while improving performance (less vertex data to process / cross the memory bus, or if you're using VBOs, more texture space).

If there are enough people that think something like this might be useful, I'll write up an OpenGL extension specification and send e-mail to some of the contacts at nVidia and ATI to see what the best way to progress would be. It may never actually be implemented, but it certainly can't hurt to try. ;)

This topic is closed to new replies.

Advertisement