glShadeModel for Colors and Normals

Would it be possible to make the shading model for the colors and normals distinct?

I am involved in visualisation of simulation data on unstructured meshes and I often have to render mesh data where each triangle has a single normal but a different color at each vertex. I want a single normal because the surface can often be very rough and using smoothed per-vertex normals makes it look silly.

Up to now I have been doing this using glDrawArrays but the vast increase in size of the data-sets has forced me to look into alternatives. One such alternative is glDrawElements but this doesn’t give the required flexibility without duplicating vertices and then I am effectively back to glDrawArrays.

The only way I have found is to set glShadeModel to GL_FLAT and then use 1D texture objects to do the colour shading but not every computer I will come across will have texture mapping in hardware.

Cheers,

Jason

For 95% of the people who ask for this extension (basically, multiply-indexed vertex arrays), they don’t really need it. Typically, these people are writing an export program from a modeler and would like to simply dump out a bunch of arrays and indices to a file and let OpenGL sort it out. Though transforming these lists into unique vertex arrays is a not trivial, it isn’t particularly hard either. And, it doesn’t add a tremendous amount of overhead to their models either.

You, sir, reside in the 5% of the people who want this extension. For the others, it makes life a bit easier. For you, it makes life possible.

I have never really thought about a problem like yours before. Originally, I was going to suggest glDrawElements, but I quickly realized that, if all the faces have different normals, none of the vertices would be the same, so you would basically get a performance drop over glDrawArrays.

The only reason I can think of that this extension has not been implemented is that it is a non-trivial task for hardware to multiply index an array.

And the current vertex array specification sounds like it should allow for multiple indices. After all, in non-interleved formats, vertex arrays are all separate anyway. How hard could it be to write a glDrawMultiElementsEXT?

Since you mentioned that this program might be running on computers that don’t have hardware texturing, I’m assuming that performance (while always important) is not a primary concern. Instead, you are concerned about memory. So, I would suggest, outside of any driver writers responding to your pleas, that you download Mesa3D (and OpenGL-look-a-like) and add a glDrawMultiElementsEXT yourself. You could base it off of glDrawElements, since it probably won’t be that different.

An alternative to that would be to set up your arrays however you want and then use immediate mode commands (which support a per-face normal) to draw it. It may not render as fast as vertex arrays, but it will take up less room, since you are in charge of the data structures.

Good luck. Cool name, btw.

Although a glDrawMultiElementsEXT would be nice I would be happy if there were just two different glShadeModel functions, one for colors and one for normals, which I can’t see why that would be difficult to implement.

When I use glDrawElements with GL_FLAT shading and the texture mapping I still have to play with the arrays a bit to make sure that the last index for each face doesn’t point to the same vertex (or normal) position otherwise the normal for one of the faces will be wrong.

If they do happen to collide then I either reorder the vertices for that triangle so they don’t clash or duplicate that vertex.

An example would be:

Triangle 1 (45,56,78)
Triangle 2 (56,90,78)

Now with this example the normal used is the one at position 78 but this is used for both triangles. To solve this I either reorder one of the triangles, e.g.

Triangle 1 (45,56,78)
Triangle 2 (78,56,90)

Now the normals are from different vertex positions so no clash or I just duplicate a vertex and make the second triangle point to the new vertex.

The former can be quite complex on a large mesh since changing one face can impact on neighbouring faces. The latter involves extra vertices but when used in combination with the former I have found very few to be duplicate.

So essentially, I have GL_FLAT for normals and GL_SMOOTH for the texture coordinates.

All I need is GL_FLAT for the normals and GL_SMOOTH for the colours and replace my texture coordinates with colour information.

As for the point about not needing performance - it couldn’t be farther from the truth. I agree with your conclusions where PCs are concerned because people can change their graphics cards every 6 months.

However, we work with people on Sun and SGI workstations which, due to their cost, can’t be changed so regularly. If we take, for example, an SGI Power Indigo2 with Impact graphics. The rendering rate for this graphics card is very high but the low-end version doesn’t have texture-mapping in hardware so I can go from rendering speeds of millions of triangles per second to watching each triangle be drawn slowly just by enabling texture mapping.

I have a different request on per face attribute, similar to per vertex attribute array, vertexColor, vertexNormal, vertexTexture…, introduce per face (triangle) attribute array, so we can also have faceNormal, faceColor…, then it is possible to have a new mode of

::glEnable (GL_TRIANGLE_NORMAL_ARRAY);
::glEnable (GL_VERTEX_COLOR_ARRAY);
::glDrawArray(…);

this will direct the rendering to use per triangle normal and per vertex color. In the rendering stage, it should simple to change normal only at the specification of the third vertex of the triangle but a lot efficient.

– Youda