All pastes #771156 Raw Edit

Anonym

public text v1 · immutable
·published 2007-11-12 20:55 UTC
rendered paste body

#define HALF_PI 1.57079632679

surface test (

color SurfaceColor=color(0.8,0.74,0.68); 
float diffuseCoeff=.8; 
float Ka2=0.5; 
color sheenColor2=color(1,1,1); 
float eta2=0.714; 
float thickness2=0.5; 
color SurfaceColor2=color(.8,.5,.5); 
color incandescence=color(0,0,0); 
float translucence=0; 
color specularColor=color(0.5,0.5,0.5); 
float eccentricity=.3; 
float specularRollOff=.7; ) 
{
/** Surface main-code start **/

/* Evaluate the Henyey-Greenstein phase function for two vectors with
an asymmetry value g. v1 and v2 should be normalized and g should 
be in the range (-1, 1). Negative values of g correspond to more
back-scattering and positive values correspond to more forward scattering.
*/
float phase(vector v1, v2; float g) {
float costheta = -v1 . v2;
return (1. - g*g) / pow(1. + g*g - 2.*g*costheta, 1.5);
}

/* Compute a the single-scattering approximation to scattering from
a one-dimensional volumetric surface. Given incident and outgoing
directions wi and wo, surface normal n, asymmetry value g (see above),
scattering albedo (between 0 and 1 for physically-valid volumes),
and the thickness of the volume, use the closed-form single-scattering
equation to approximate overall scattering.
*/
float singleScatter(vector wi, wo; normal n; float g, albedo, thickness) {
float win = abs(wi . n);
float won = abs(wo . n);

return albedo * phase(wo, wi, g) / (win + won) *
(1. - exp(-(1/win + 1/won) * thickness));
}

vector efresnel(vector II; normal NN; float eta; output float Kr, Kt;) {
vector R, T;
fresnel(II, NN, eta, Kr, Kt, R, T);
Kr = smoothstep(0., .5, Kr);
Kt = 1. - Kr;
return normalize(T);
}


/* Implements overall skin subsurface shading model. Takes viewing and
surface normal information, the base color of the skin, a
color for an oily surface sheen, the ratio of the indices of 
refraction of the incoming ray (typically 
1 for air) to the index
of refraction for the transmitted ray (say something like 1.4 for
skin), and the overall thickness of the skin layer. Then loops
over light sources with illuminance() and computes the reflected
skin color.
*/
color subsurfaceSkin(vector Vf; normal Nn; color skinColor, sheenColor;
float eta, thickness) {
extern point P;
float Kr, Kt, Kr2, Kt2;
color C = 0;

vector T = efresnel(-Vf, Nn, eta, Kr, Kt);

illuminance(P, Nn, PI/2) {
vector Ln = normalize(L);

vector H = normalize(Ln + Vf);
if (H . Nn > 0)
C += Kr * sheenColor * Cl * (Ln . Nn) * pow(H . Nn, 4.);
C += Kr * sheenColor * Cl * (Ln . Nn) * .2;

vector T2 = efresnel(-Ln, Nn, eta, Kr2, Kt2);
C += skinColor * Cl * (Ln . Nn) * Kt * Kt2 * 
(singleScatter(T, T2, Nn, .8, .8, thickness) +
singleScatter(T, T2, Nn, .3, .5, thickness) +
singleScatter(T, T2, Nn, 0., .4, thickness));
}
return C;
}

normal Nn2 = faceforward(normalize(N), I);
vector Vf2 = -normalize(I);
/* #define HALF_PI 1.57079632679 */

normal Nf3;
vector H3, Ln3, V3;
color Ia3, Id3, Itr3, Is3;
float NH3, NH23, NHSQ3, Dd3, Gg3, VN3, VH3, LN3, Ff3, tmp3;
/* uniform float E3 = 1 / (eccentricity * eccentricity - 1); */
float E3 = 1 / (eccentricity * eccentricity - 1);

Nf3 = faceforward(normalize(N), I);
Ia3 = ambient() + subsurfaceSkin(Vf2, Nn2, SurfaceColor2, sheenColor2, eta2, thickness2);
Id3 = diffuseCoeff * diffuse(Nf3);

Itr3 = 0;
if (translucence != 0) {
illuminance(P, Nf3, PI)
Itr3 += Cl;
Itr3 *= translucence;
}

Is3 = 0;
V3 = normalize(-I);
VN3 = V3.Nf3;
illuminance(P, Nf3, HALF_PI) {
Ln3 = normalize(L);
H3 = normalize(Ln3+V3);
NH3 = Nf3.H3;
NHSQ3 = NH3*NH3;
NH23 = NH3 * 2;
Dd3 = (E3+1) / (NHSQ3 + E3);
Dd3 *= Dd3;
VH3 = V3.H3;
LN3 = Ln3.Nf3;
if (VN3 < LN3) {
if (VN3 * NH23 < VH3)
Gg3 = NH23 / VH3;
else
Gg3 = 1 / VN3;
}
else {
if (LN3 * NH23 < VH3)
Gg3 = (LN3 * NH23) / (VH3 * VN3);
else
Gg3 = 1 / VN3;
}
tmp3 = pow((1 - VH3), 3);
Ff3 = tmp3 + (1 - tmp3) * specularRollOff;
Is3 += Cl * Dd3 * Gg3 * Ff3;
}
Is3 *= specularColor;

/** Surface main-code end **/

Ci = SurfaceColor * (Ia3 + Id3 + Itr3 + incandescence + Is3);

}