/*
* lafortune.sl -- Implement the BRDF representation of Lafortune et al.
*
* DESCRIPTION:
* Implement the BRDF representation described in "Non-Linear
* Approximation of Reflectance Functions", by Eric P. F. Lafortune,
* Sing-Choong Foo, Kenneth E. Torrance, and Donald P. Greenberg, in
* SIGGRAPH 97 Proceedings.
*
* PARAMETERS:
* coeff: Coefficients for each lobe. There will be
* 3 coefficients per lobe per wavelength.
* for each lobe of Nlobes:
* for each channel of N_WAVES:
* cxy, cz, n
* where cxy, cz are the directional and scale components
* n is the exponent for the cosine
*
* Cs: Diffuse color of surface. This provides the diffuse
* term that is an integral part of the model. This
* will be the diffuse component from the Lafortune
* model multiplied by pi, as the RenderMan definition
* of reflectance is different.
* colormatrix: 3x3 color transformation matrix, if needed.
* This is here because measured data may be in the
* RGB space of some sensor (e.g. a digital camera)
* and may need correction for display. Since the three
* channels are represented independently (i.e. each
* channel will have different directionality), this
* correction must be done on a per-pixel basis.
* Since the correction may be different for each
* shader, we must do it here. Default is the identity
* matrix.
*
* ANTIALIASING: should antialias itself fairly well
*
* AUTHOR: written by Stephen H. Westin, Cornell University Program of
* Computer Graphics
*
* HISTORY:
*
* initial version 22 March 1999 S. H. Westin
*
* 22 March 1999 S. H. Westin
* Flipped sign on Cx to agree with description in SIGGRAPH paper
* 25 October 2000 S. H. Westin
* Multiply lobes by incident cosine.
* 27 October 2000 S. H. Westin
* Multiply lobes by incident cosine. Before, I was trying to
* use diffuse(), which doesn't work.
*
*/
/* Number of coefficients per lobe: 3 for an isotropic surface */
#define LOBESIZE 3
/* Number of wavelengths (wired in) */
#define N_WAVES 3
/* Number of lobes (wired in) */
#define Nlobes 3
#define COEFFLEN (LOBESIZE*N_WAVES*Nlobes)
/* Default BRDF: flat blue paint */
/* Use "Color [ .3094 .39667 .70837 ]" for consistency with default */
surface
lafortune ( uniform float coeff[27] = /* Change 27 to equal COEFFLEN */
{ -0.870567, 0.803624, 21.820103,
-0.857255, 0.774290, 18.597755,
-0.670982, 0.586674, 7.472717,
0.451218, 0.023123, 2.774499,
0.406681, 0.017625, 2.581499,
0.477976, 0.227295, 3.677653,
1.031545, 0.706734, 66.899060,
1.029426, 0.696530, 63.767912,
1.026588, 0.687715, 57.489181 };
uniform float colormatrix[9] =
{ 1, 0, 0, 0, 1, 0, 0, 0, 1 };
uniform string texturename = ""; )
{
varying vector local_z;
varying vector local_x, local_y; /* Unit vector in "u" and "v" directions */
varying vector V; /* Normalized eye vector */
varying vector Ln; /* Normalized vector to light */
varying float x, z, f; /* subterms */
varying float fr, fg, fb; /* RGB components of the non-Lambertian term */
uniform float basepointer, j; /* loop counters */
/* Get unit vector in "u" parameter direction */
local_x = normalize ( dPdu );
local_z = faceforward (normalize(N), I);
V = normalize (I);
/* Get a local coordinate system. */
local_y = local_z^local_x;
/* The first term is the diffuse component. This should be the
diffuse component in the Lafortune model multiplied by pi. */
if ( texturename == "" )
Ci = (diffuse(local_z) + ambient()) * Cs;
else
Ci = (diffuse(local_z) + ambient()) * color texture (texturename);
illuminance ( P, local_z, 1.57079632679489661923 /* Hemisphere */ ) {
Ln = normalize ( L );
/* Compute the terms
x = x_in * x_view + y_in * y_view
z = z_in * z_view
*/
x = local_x.V * local_x.Ln + local_y.V * local_y.Ln;
z = - ( local_z.V * local_z.Ln );
/* Coefficient structure:
for each lobe of Nlobes:
for each channel of N_WAVES:
cxy, cz, n
where cxy, cz are the directional and scale components
n is the exponent for the cosine
*/
for ( basepointer=0;
basepointer 0.001*rexponent )
fr = pow ( f, rexponent ) ;
f = -x * coeff[basepointer+LOBESIZE]
+ z * coeff[basepointer+LOBESIZE+1];
if ( f > 0.001*gexponent )
fg = pow ( f, gexponent ) ;
f = -x * coeff[basepointer+2*LOBESIZE]
+ z * coeff[basepointer+2*LOBESIZE+1];
if ( f > 0.001*bexponent )
fb = pow ( f, bexponent ) ;
Ci += ( Cl * color "rgb" ( fr, fg, fb ) ) * (local_z.Ln);
}
}
/* Color correction from camera space */
/* use dot product with rows of matrix */
fr = colormatrix[0]*comp(Ci,0)
+ colormatrix[1]*comp(Ci,1) + colormatrix[2]*comp(Ci,2);
fg = colormatrix[3]*comp(Ci,0)
+ colormatrix[4]*comp(Ci,1) + colormatrix[5]*comp(Ci,2);
fb = colormatrix[6]*comp(Ci,0)
+ colormatrix[7]*comp(Ci,1) + colormatrix[8]*comp(Ci,2);
Ci = color "rgb" ( fr, fg, fb );
Ci *= Os;
}