home *** CD-ROM | disk | FTP | other *** search
- {
- He-Torrance Reflectance Model
-
- This is the simplified version that doesn't account for
- changes in reflection due to changes in wavelength. Also,
- specular and directional-diffuse hightlights are left uncolored
- because coloring them requires multiple evaluations of some
- very expensive functions.
-
- * Arguments for the BRDTfunc type are:
- * 10+ rrefl grefl brefl
- * rtrns gtrns btrns
- * rbrtd gbrtd bbrtd
- * funcfile transform
- * 0
- * 6+ red grn blu rspec trans tspec A7 ..
- *
- * In addition to the normal variables available to functions,
- * we can use the following:
- * NxP, NyP, NzP - perturbed surface normal
- * RdotP - perturbed ray dot product
- * CrP, CgP, CbP - perturbed material color
- }
-
- { Constants }
- lambda : .5; { wavelength (microns) }
- z0err : .0001; { accepted error in value of z0 }
- Dsumlim : .000001; { last term of D summation }
- Dsummax : 200; { maximum terms in D summation }
-
- { Parameters }
- sigma0 = arg(7); { surface height deviation (microns) }
- tau = arg(8); { correlation distance (microns) }
- n_real = arg(9); { real part of index of refraction }
- n_imag = arg(10); { imaginary part of index of refraction }
- { Derived parameters }
- n_k = n_imag/n_real;
-
- { Repeated formulas }
- cotexp(t) = tau/sigma0/2/tan(t);
- shadowf2(et,erfcet) = (1-.5*erfcet) /
- ((Exp(-sq(et))/sqrt(PI)/et - erfcet)/2 + 1);
- shadowf1(t) = or(FTINY-sigma0, .01-abs(t));
- shadowf0(t) = abs(t) - (PI/2-.0001);
- shadowf(t) = if(shadowf0(t), 0, if(shadowf1(t), 1,
- shadowf2(cotexp(t), erfc(cotexp(t)))));
- K(t) = if(abs(t)-FTINY, tan(t) * erfc(cotexp(t)), 0);
- fuvA(ct) = sq(n_real)*(1-sq(n_k)) - (1-sq(ct));
- fuvB(ct) = sqrt(sq(fuvA(ct)) + 4*sq(sq(n_real)*n_k));
- fu2(ct) = (fuvA(ct) + fuvB(ct))/2;
- fv2(ct) = (-fuvA(ct) + fuvB(ct))/2;
- fperp2(ct) = (sq(ct-sqrt(fu2(ct))) + fv2(ct)) /
- (sq(ct+sqrt(fu2(ct))) + fv2(ct));
- fpara2(ct) = (sq(sq(n_real)*(1-sq(n_k))*ct - sqrt(fu2(ct))) +
- sq(2*sq(n_real)*n_k*ct - sqrt(fv2(ct)))) /
- (sq(sq(n_real)*(1-sq(n_k))*ct + sqrt(fu2(ct))) +
- sq(2*sq(n_real)*n_k*ct + sqrt(fv2(ct))));
- fresnel2(ct) = (fperp2(ct) + fpara2(ct))/2;
-
- { Formulas dependent only on reflected direction }
- theta_r = Acos(RdotP);
- shadowf_r = shadowf(theta_r);
- K_r = K(theta_r);
- srx = Dy*NzP - Dz*NyP; sry = Dz*NxP - Dx*NzP; srz = Dx*NyP - Dy*NxP;
- srn2 = sq(srx) + sq(sry) + sq(srz);
- prx = sry*Dz - srz*Dy;
- pry = srz*Dx - srx*Dz;
- prz = srx*Dy - sry*Dx;
- s = fresnel2(RdotP)*Exp(-g(RdotP))*sq(shadowf_r);
-
- { Formulas dependent on incident direction }
- { z0 }
- z0d(Ki,z) = -(Ki+K_r)/(4*sigma0)*z*Exp(-sq(z/sigma0)/2) - sqrt(PI/2);
- z0lim(x) = if(x, max(x,z0err), min(x,-z0err));
- z0off(Ki,z) = (sigma0/4*(Ki+K_r)*Exp(-sq(z/sigma0)/2)-sqrt(PI/2)*z)/
- z0lim(z0d(Ki,z));
- z0root(Ki, x0, x1, i) = if(i,
- if(z0err-abs(x1-x0),
- x1,
- z0root(Ki,x1,x1-z0off(Ki,x1),i-1)),
- 0);
- z0(ti) = z0root(K(ti), .1, -z0off(K(ti),.1), 100);
- { sigma }
- sigma(ti) = if( FTINY-sigma0, sigma0,
- sigma0/sqrt(1+sq(z0(ti)/sigma0)) );
- { g }
- g(cti) = sq(2*PI/lambda*sigma(Acos(cti))*(cti+RdotP));
- { |F|^2 }
- fresnel2dd(kix,kiy,kiz) = fresnel2(sqrt(sq(kix-Dx) + sq(kiy-Dy) +
- sq(kiz-Dz))/2);
- { G }
- G2( kix,kiy,kiz, six,siy,siz ) =
- sq((sq(Dx-kix)+sq(Dy-kiy)+sq(Dz-kiz))/(Dz-kiz)) /
- sq(sq(Dy*kiz-Dz*kiy)+sq(Dz*kix-Dx*kiz)+sq(Dx*kiy-Dy*kix)) *
- (sq(srx*kix+sry*kiy+srz*kiz) +
- sq(prx*kix+pry*kiy+prz*kiz)) *
- (sq(six*Dx+siy*Dy+siz*Dz) +
- sq((siy*kiz-siz*kiy)*Dx+(siz*kix-six*kiz)*Dy+(six*kiy-siy*kix)*Dz)) /
- srn2 / (sq(six)+sq(siy)+sq(siz));
- G(kix,kiy,kiz) = G2(kix,kiy,kiz,
- kiy*NzP-kiz*NyP, kiz*NxP-kix*NzP, kix*NyP-kiy*NxP);
- { D }
- Dsum2(m,lt,c,t,e,g) = if(or(m-Dsummax,and(lt-t,Dsumlim-t)),0,
- t+Dsum2(m+1,t,c*g/(m+1),c*g/(m+1)*Exp(-g-e/(m+1))/(m+1),e,g));
- Dsum(e,g) = Dsum2(1,0,g,g*Exp(-g-e),e,g);
- D(kix,kiy,kiz) = sq(PI)/4/sq(lambda)*sq(tau) *
- Dsum(sq(2*PI/lambda)/4*sq(tau)*(sq(kix-Dx)+sq(kiy-Dy)),
- g(kix*NxP+kiy*NyP+kiz*NzP));
- { rho_dd }
- dd2(cti) = shadowf_r*shadowf(Acos(cti))/cti/RdotP;
- dd(kix,kiy,kiz) = dd2(kix*NxP+kiy*NyP+kiz*NzP)*G(kix,kiy,kiz)*
- fresnel2dd(kix,kiy,kiz)/PI*D(kix,kiy,kiz);
-