[Bf-committers] Re: Minnaert shader

Jonathan Merritt j.merritt at pgrad.unimelb.edu.au
Sat Apr 9 11:04:06 CEST 2005

Hi Everyone,

I've been extremely busy, so have only just been able to get around to
responding to the discussion on the Minneart shader.  I've got to say
that I think most of the discussion about the "correctness" of the
shader has been a bit silly... I'll try to explain below:

First of all, some theory.  The standard Lambertian shading model
calculates intensity as the value of the dot product between the surface
normal vector (n) and the normalized vector from the surface point to
the light point (l):
    Lambertian = n . l

Minneart's original BRDF, as given in his 1941 paper (1), is:
    Minneart_original = ((n . l) ^ k) * ((n . v) ^ (k-1))
Where (v) is the normalized vector from the observer to the point being
Note that the Lambertian term (n . l) is actually raised to the power of
k.  This is also equivalent to:
    Minneart_original = Lambertian * ((n . l) * (n . v)) ^ (k-1)
as given by (2).  In this form, the Minneart model can be understood as
a "limb darkening" or "limb brightening" of the original Lambertian
model.  This explains where the power of (k-1) originally came from, and
why (for example) just k was not used originally.

Just for completeness, in the MinneartB model (eg (3)), we have:
    MinneartB = Lambertian * (n . l)^k * (1 - n . v)^(1-k)
For the record, the MinnaertB model is currently *not* in Tuhopuu.

The model currently in Tuhopuu3 CVS is Minneart (not MinneartB). 
Instead of assigning the "proper" range of k to be [0,1] with k=1 being
Lambertian,  I assigned the "proper" range of k to be [-1,0], with k=0
being Lambertian:
    Minneart_Tuhopuu = Lambertian * ((n . l) * (n . v)) ^ k
The *range* of k (not what happens when you increase or decrease k) is
the main difference anyone will notice.  Changing the range of k was a
choice I made because k is described as a "darkening term".  Hence, you
would think that zero darkening of the Lambertian model (ie: k=0) would
correspond to Lambertian.  It is somewhat counter-intuitive to have 0
darkening being the maximum darkening, while 1 is the minimum, wouldn't
you say?

Now, before anyone gets upset about me tampering with the "purity" of
the original Minnaert formulation, it is important to note that the
original Minnaert formula is fundamentally flawed (shock horror!!!). 
Take a look at what happens as the darkening parameter approaches its
minimum value (either k -> -1 in my range, or k -> 0 in the original
range).  You'll find that at the glancing edges of the object, where (n
. v) goes to zero, the Minneart shader goes to infinity!!!  This causes
some nasty artifacts.  If you don't believe me, go right ahead and
change the code and see for yourself!

To avoid the shader going "to infinity and beyond", I clamped the ((n .
l) * (n . v)) term to be no less than 0.1, and then scaled the
brightness of the rest of the range of values appropriately, so that the
overall brighness of the object would look approximately correct.

The important take-home message here is that we *CANNOT* use the
original form of the Minnaert shader without having horrible rendering
artifacts when the intensity approaches infinity!  It's just a fact of
life.  Take a look at the animation for Minnaert in (3) to get some
idea.  If we're going to clamp the intensity somehow (as I've done),
then we lose the "purity" of the original model anyway, so why not
change the range of k to be more intuitive at the same time?  As for
anyone who wants to look up k in a table... c'mon, you *really* think
that's likely?!!!  Anyone that technical is surely smart enough to be
able to add one to their value of k.

If there's a "standard" Minneart shader in other 3D packages (and by
"standard", I mean appearing fairly identical in 2 or more other
packages), then if someone can provide the details, I can change the
Tuhopuu shader so that it matches.  I really don't think that Minneart
is quite so "standard" though.  Plus, other packages will need to have
overcome the problem with the glancing edges of objects somehow, which
will mean that they are definitely *not* Minneart's original formulation.

If Minneart is committed to the main tree then I can (of course) provide
documentation about exactly the shading model that is being used
(although it's simple enough to just look at the code!).

(1) - Minneart, M. (1941) The Reciprocity Principle in Lunar Photometry,
Astrophysical Journal, 93:403-410.

(2) - http://www.cs.princeton.edu/~smr/cs348c-97/surveypaper.html

(3) - http://accad.osu.edu/~bwatkins/ADC/Hw6/hw.html

Jonathan Merritt BE(Mech)/BSc
PhD Student - Equine Biomechanics
The University of Melbourne
Veterinary Clinical Centre, Werribee

More information about the Bf-committers mailing list