|
|
https://www.cs.cornell.edu/~srm/publications/SG05-wood-lr.pdf
https://www.cs.cornell.edu/~srm/publications/SG05-wood.html
has a link to a tar/gz archive with code. :)
/*
* woodreflectance.sl -- wood (anisotropic)
*
* DESCRIPTION:
* Simple wood shader, driven by four textures:
* RGB diffuse color
* RGB fiber (anisotropic highlight) color
* x,y,z of unit vector giving local fiber orientation in local
* coordinates
* beta, a "roughness" parameter to control width of highlight.
* If any of these files is not specified, we fall back on a
* uniform parameter. So far, every map has had uniform beta.
*
* PARAMETERS:
*
* diffuse_texture: name of file containing 3-channel texture
* modulating color across the patch.
*
* fiber_texture: name of file containing 3-channel texture
* modulating fiberColor across the patch. This map is divided by
* 20 because it generally contains values greater than 1, which
* would be clamped in an integer pixel format.
*
* axis_texture: name of file containing 3-channel texture
* modulating fiberAxis across the patch. Values are mapped
* [0:max] -> [-1:1] for each component, since most image file
* formats are unsigned.
*
* beta_texture: name of file containing 1-channel texture
* modulating beta across the patch.
*
* eta: Index of refraction of surface finish. Used to modulate
* highlight and subsurface with varying angle. eta=0 used to
* signal absence of overcoat.
*
* color, fiberColor: fallback diffuse and directional colors if
* texture is missing
*
* fiberAxis: fallback fiber direction if texture is missing
*
* beta: width of subsurface highlight if texture is missing
*
* roughness: width of surface (white) highlight
*
* Ka, Kd, Ks: normal Renderman coefficients. Ka and Kd modulate the
* diffuse component (parameter "color"), and Ks is a fudge factor
* on the surface (white) highlight.
*
* ANTIALIASING: provided by texture lookup
*
* REFERENCE: Stephen R. Marschner, Stephen H. Westin,
* Adam Arbree, and Jonathan T. Moon,
* "Measuring and Modeling the Appearance of
* Finished Wood", SIGGRAPH 2005
*
* AUTHOR: written by Stephen H. Westin,
* Cornell University Program of
* Computer Graphics
* last modified by $Author: westin $
*
* VERSION: $Revision: 1.2 $
*
* HISTORY:
* $Log: woodreflectance.sl,v $
* Revision 1.2 2005/05/10 20:02:15 westin
* Modified to use 4 TIFF texture maps rather than a single
* 10-channel map.
*
* Revision 1.1 2005/05/09 21:10:18 westin
* Working version of shader; used for animation on Proceedings DVD-ROM.
*
*/
surface
woodreflectance ( float Ka = 1.0,
Kd = 1.0,
Ks = 1.0;
float eta = 1.5;
vector fiberAxis = ( 1, 0, 0 );
float beta = .1745; /* 10 degrees -> radians */
color fiberColor = color ( 1, .6, .4 );
string diffuse_texture = "",
fiber_texture = "",
axis_texture = "",
beta_texture = "";
float minU = 0, maxU = 1,
minV = 0, maxV = 1,
roughness = 0.2; )
{
uniform float sqrt2pi = 2.5066283;
vector local_z; /* Surface normal in "world" space */
vector local_x, local_y; /* Unit vector in "u" and "v" directions */
normal Nf = faceforward (normalize(N), I); /* Forward-facing normal */
vector V = normalize(I); /* Normalized eye vector */
color diffuseColor, highlight;
vector axis;
float tx_beta;
vector ssInDir, ssOutDir; /* Light and eye vector, possibly refracted */
float thInPrime, thOutPrime;
float halfAngle, diffAngle;
float fiberFactor, geometryFactor;
float Kr, Kt; /* for output of fresnel() */
float ssAtten; /* Attenuation from going through the smooth interface twice */
/* Get local coordinate system in terms of native
parameters (u,v). We should really use (s,t). */
local_z = Nf;
/* Get unit vector in "u" parameter direction */
local_x = normalize ( dPdu );
/* Get final local basis vector y perpendicular to x and z. */
local_y = local_z^local_x;
/* If there is a clear overcoat, calculate refraction direction and
attenuation. */
if ( eta != 1.0 ) {
vector Rdir; /* Dummy */
fresnel ( V, Nf, 1.0/eta, Kr, Kt, Rdir, ssOutDir );
ssOutDir = -ssOutDir;
// Use (1-Kr) rather than Kt, because we are dealing with power,
// not radiance.
ssAtten = 1 - Kr;
} else {
ssOutDir = -V;
ssAtten = 1.0;
}
normalize(ssOutDir);
color axisTemp;
float ourS = minU + u * (maxU - minU),
ourT = minV + v * (maxV - minV);
// Get parameters locally from texture maps, if available
if ( diffuse_texture != "" )
diffuseColor = color texture ( diffuse_texture, ourS, ourT );
else
diffuseColor = Cs;
if ( fiber_texture != "" )
highlight = color texture ( fiber_texture, ourS, ourT ) * 20;
else
highlight = fiberColor;
if ( axis_texture != "" ) {
axisTemp = color texture ( axis_texture, ourS, ourT )
*2 - 1.0;
/* Transform to local coordinate system */
axis = comp ( axisTemp, 0 ) * local_x
- comp ( axisTemp, 1 ) * local_y
+ comp ( axisTemp, 2 ) * local_z;
}
else
axis = comp ( fiberAxis, 0 ) * local_x
+ comp ( fiberAxis, 1 ) * local_y
+ comp ( fiberAxis, 2 ) * local_z;
normalize(axis);
if ( beta_texture != "" )
tx_beta = float texture ( beta_texture, ourS, ourT );
else
tx_beta = beta;
thOutPrime = asin ( ssOutDir.axis );
/* Calculate anisotropic highlight for each light */
Ci = 0;
illuminance ( P, Nf, PI/2 /* Hemisphere */ ) {
float dummy, ssAttenOut;
vector Ln = normalize ( L );
/* Refract at smooth surface */
if ( eta != 1.0 ) {
vector Rdir; /* dummy */
fresnel ( -Ln, local_z, 1.0/eta, Kr, Kt, Rdir, ssInDir );
// Use (1-Kr) rather than Kt, because we are dealing with power,
// not radiance.
ssAttenOut = 1 - Kr;
} else {
ssInDir = -Ln;
ssAttenOut = 1.0;
}
float ssFactor = max ( 0, -ssInDir.local_z ) * ssAtten*ssAttenOut;
thInPrime = asin ( -ssInDir.axis );
halfAngle = thOutPrime + thInPrime;
diffAngle = thOutPrime - thInPrime;
// Compute value of Gaussian at this angle
fiberFactor = tx_beta * exp ( -pow(halfAngle/tx_beta,2)/2 )
/ sqrt2pi;
float cosIncline = cos(diffAngle / 2);
geometryFactor = 1 / pow ( cosIncline, 2 );
fiberFactor *= geometryFactor;
// Add in diffuse term, attenuated by surface term.
Ci += Cl * Kd * diffuseColor * ssFactor;
// Add in fiber highlight, also attenuated.
Ci += Cl * fiberFactor * highlight * ssFactor;
/* Second Fresnel call is for strength of surface highlight */
vector H = normalize ( -V + Ln );
fresnel ( V, H, 1.0/eta, Kr, Kt );
// Blinn/Phong highlight with Fresnel attenuation
Ci += Cl * Ks * Kr
* pow ( max ( 0, H.local_z ), 1/roughness );
}
Ci += Ka * diffuseColor * ambient();
}
Post a reply to this message
|
|