Is there such a thing as 'Normal Arrays'?

I know that vertex arrays allow vertices to be shared between triangles, thereby reducing memory usage, but is it also possible for normals to be shared between vertices?

Although I have a large number of vertices in my meshes the normals are always taken from a relatively small set of say 20-30 ‘predefined’ normals. Because of this it doesn’t really make sense to me to keep a normal with each vertex - I would rather store a ‘normal array’ somewhere and then keep an index into this with the normal.

I’d just assumed this feature existed, but I haven’t been able to find any reference to it. Can anyone tell me if OpenGL has this feature? If not, might there be a way to emulate it with vertex shaders?

Thanks!

It is the way to do from your first sentance.

Each vertex or normal will be affected the same index value. So for each vertex to be rendered will be affected the same normal.
There aren’t any ‘extended arrays’ in GL at this time, and surely won’t have any.
So if you have 100 vertices you must have 100 normals.

Graphics hw prefers interleaved data.

struct MyVertex
{
x, y, z, normalX, normalY, normalZ
}

or

struct MyVertex
{
x, y, z, normalX, normalY, normalZ, s, t
}

Ok, thanks guys. So for maximum performance I’ll just stick to doing it the usual way.

For curiosity sake, has anyone tried using a per-vertex index or weight value to do a VP table lookup for normals, colors, etc… as one would with matrix blending?

I figure it’s not a huge win (or could easily be a loss), as it still requires a full-sized dummy normal array to be bound, loaded, and overridden in the VP…

However, if you really wanted to cram a VP table of shared normals, colors, and/or texcoords at minimal cost, you could pack the indexWeight into your vertex as:

vertex { x , y, z, indexWeight }

and then bind dummy normals, colors, and/or texcoords to the SAME vertex pointers (aliased, in the same VBO so there’s no extra transfer), relying on the VP to stuff the correct output value from your LUT based on the given weight/index.

The biggest limitation, then, is what fits in VP registers – on older cards, on the order of tens to hundreds of unique normals, colors, texcoords AT BEST. However, if your index/weight param(s) are sent as ubyte[4], then you could separately index up to 256 normals, texcoords, colors, etc…, if they all fit.

And if they didn’t fit, then you could perhaps define 4 ubyte indices/weights to find, blend* and normalize 2-4 unique basis vectors in VP registers, to get the complete spectrum – less precision than float[3] normals but much more than sending quantized normals of type byte[3], which generally sucks. Not recommended for colors, which are usually 8 bit anyway.

But unless there’s a transfer bottleneck or you’re animating/cycling normals in some special way, best to stick with “the usual way.” :wink:

[* the idea being some part of the index/weight finds one of N unique basis vectors, while the other part indicates the weight]