Flat Shading And Normal Maps

> Quick question about normal maps - what happens to 'traditional' > smooth/flat shading attributes when a normal map is present? For > example, the kind of vertex normal instructions set by the 'edge split > angle' control in AC3D? Are they ignored, or do they have some kind of > effect still?

Well, there are 3 things going on here:

1. What happens with flat/smooth shading in ac3d. 2. What ATTR_flat does in a file. 3. What normal maps do.

And they are (fortunately for my sanity) all independent.

First: ac3d. Ac3d doesn't generate flat shading attributes any more. :-) If ac3d says the surface is flat (because it is flat shaded OR below the crease angle) ac3d actually gives me (the exporter) per-vertex normals that happen to be aligned for flat shading.

In very old versions of the plugin I did generate ATTR_flat when I detected that we really were in flat shading but...it turns out it's worth eating the vertex count (see below) to avoid attribute changes.

Second: what is flat shading? Basically flat shading can be thought of as sort of a "sustain pedal" for normals...in flat shading, the normal that "provokes" the triangle (that is, normals # 3, 6, 9, etc. the ones that are emitted last before the triangle) are the ones used to shade the entire triangle. You can think of it as "smearing" the 3rd, 6th, and 9th normal back over the previous two.

So when we export a flat shaded object, basically ac3d has done this in advance. Anything you can do with flat shading, you can do with smooth shading by pre-changing the normals.

(Note that both modes still interpolate lighting over the entire triangle! If you had per vertex spot lighting, each corner would be lit differently.  The "smoothness" of a curved surface comes from having different normals in each corner of the triangle, even though in truth the triangle is, by definition, planar.)

Just from this we can see a side-effect of not having flat shading: more normals. If we had a cube where the XYZ and ST coordinates of each vertex were the same for the shared vertices of each face (in other words, no texture discontinuity) we can share the vertices with flat normals (because the normal that provokes might not be the one we have) by carefully picking which normals provoke.

With smooth shading, we have to copy the vertices just so we can have different normals for different faces (to get that "crisp" edge).

Back in v6 when we cared about every vertex, this copying was a problem. In v9, where we can have 50,000 vertices, we really don't care anymore...we care more about the ATTR. (Also, most high vertex count meshes I've seen come from round things where we need smooth shading anyway. Optimizing a cube down from 24 to 8 vertices isn't worth it.

Now there's one more issue: in the old days, with flat shading, we could simply specify one normal per each 3 or 4 vertices. This is now a very bad idea...modern hardware sucks up vertices at high speed _only_ when every vertex has the same layout. So we can't get a win there. (That s to say, flat shading is an API feature that might not exist if OpenGL were built today for today's hardware from scratch.)

Third: okay. So we have normals coming in per vertex, and OpenGL is looking at all of them, or only the provoking one, and then interpolating them across the triangle to get a roughly interpolated normal per pixel. That's what you get when you use per-pixel lighting with no normal map.

The normal map takes that interpolated normal and the texture coordinate system and builds a coordinate system (called "tangent space", because it is a coordinate system tangent to the surface). The normal vector from the normal map is translated into that coordinate system.

So...the "basis" for the normal map will be very simple, constant and boring if you have flat shading, whether from ATTR_flat or from ac3d. If you have smooth shading and a "curved" surface, a pure blue normal map (no bumps) will still curve.