First of all I can confirm, after examining many high quality videos, that vertex normal vector is calculated and normalized only in vertex shader, but the remaining lightning calculation is done per fragment. Doing everything per vertex-only gives visually different results from real Model3.

As Ian already hinted the calculation is based on the angle of incidence. We already have it since it's used for diffuse lighting, so I reuse it and perform other calculation as explained later.

Another "mistery" was the so called exponent, the values given are not meant to be used directly. At first I thought of an index to some built-in formula in Real3D, but I realized that it's just this (pseudo-code):

- Code: Select all
`// "shininess" is the uniform from "(header[6] >> 5) & 3"`

// "NdotL" is the angle of incidence

float expIndex[4] = {8.0, 16.0, 32.0, 64.0};

float exponent = expIndex[int(shininess)];

float specularIntensity = pow(NdotL, exponent);

specularIntensity = clamp(specularIntensity, 0.0, 1.0); // Clamp it just to avoid unpredictable results

Then, I realized that value should be multiplied by a "magic constant" as this (I use again the shininess as an index):

- Code: Select all
`float valueIndex[4] = {1.25, 1.5, 1.75, 2.0};`

specularIntensity *= valueIndex[int(shininess)];

And finally I multiply by the specular value:

- Code: Select all
`// "specularValue" is uniform from "(header[0] >> 26)"`

specularIntensity *= specularValue;

Another thing I noticed, and implemented, is that when translucent polys, like glasses, are hit directly by light they become over-brightened, "whitish". Model 3 seems to treat those special cases by altering the alpha channel by means of that "specularIntensity" value above. Just watch the attract mode of scud race, there are many instances of that case.

Beware that until we make fragment shader "aware" of the machine stepID, and so clamp the ambient+diffuse coefficients only for step 1.0 games, instead of doing it always, the current specular patch still produces slightly different results from real hardware. The screenshots that I'll post later will be from my private build.

Last thing: there're little random shading "misbehavior" for some quad polys whose sub-edges must be inverted, this has nothing to do with specular. I'll talk to Ian about that in another topic.