home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / share / k3d / shaders / surface / k3d_skin2.sl < prev    next >
Encoding:
Text File  |  2008-01-23  |  3.5 KB  |  100 lines

  1. /* 
  2.  * skin.sl 
  3.  * 
  4.  * Copyright (C) 2000-2001, Matt Pharr <mmp@SpamSucks_Exluna.com> 
  5.  * 
  6.  * This software is placed in the public domain and is provided as is 
  7.  * without express or implied warranty. 
  8.  * 
  9.  * Surface shader that implements a shading model that should have a visual 
  10.  * appearence generall similar to that of skin.  Based on phenomenological 
  11.  * information about skin reflectance from Hanrahan and Krueger, 
  12.  * "Reflection from layered surfaces due to subsurface scattering", 
  13.  * proceedings of Siggraph 1993. 
  14.  *
  15.  * See SIGGRAPH 2001 course notes, "Advanced RenderMan 3: Render Harder,"
  16.  * for notes and background information.
  17.  */ 
  18.  
  19. /* Evaluate the Henyey-Greenstein phase function for two vectors with
  20.    an asymmetry value g.  v1 and v2 should be normalized and g should 
  21.    be in the range (-1, 1).  Negative values of g correspond to more
  22.    back-scattering and positive values correspond to more forward scattering.
  23. */
  24. float phase(vector v1, v2; float g) {
  25.     float costheta = -v1 . v2;
  26.     return (1. - g*g) / pow(1. + g*g - 2.*g*costheta, 1.5);
  27. }
  28.  
  29. /* Compute a the single-scattering approximation to scattering from
  30.    a one-dimensional volumetric surface.  Given incident and outgoing
  31.    directions wi and wo, surface normal n, asymmetry value g (see above),
  32.    scattering albedo (between 0 and 1 for physically-valid volumes),
  33.    and the thickness of the volume, use the closed-form single-scattering
  34.    equation to approximate overall scattering.
  35. */
  36. float singleScatter(vector wi, wo; normal n; float g, albedo, thickness) {
  37.     float win = abs(wi . n);
  38.     float won = abs(wo . n);
  39.  
  40.     return albedo * phase(wo, wi, g) / (win + won) *
  41.         (1. - exp(-(1/win + 1/won) * thickness));
  42. }
  43.  
  44.  
  45. vector efresnel(vector II; normal NN; float eta; output float Kr, Kt;) {
  46.     vector R, T;
  47.     fresnel(II, NN, eta, Kr, Kt, R, T);
  48.     Kr = smoothstep(0., .5, Kr);
  49.     Kt = 1. - Kr;
  50.     return normalize(T);
  51. }
  52.  
  53.  
  54. /* Implements overall skin subsurface shading model.  Takes viewing and
  55.    surface normal information, the base color of the skin, a
  56.    color for an oily surface sheen, the ratio of the indices of 
  57.    refraction of the incoming ray (typically ~1 for air) to the index
  58.    of refraction for the transmitted ray (say something like 1.4 for
  59.    skin), and the overall thickness of the skin layer.  Then loops
  60.    over light sources with illuminance() and computes the reflected
  61.    skin color.
  62. */
  63. color subsurfaceSkin(vector Vf; normal Nn; color skinColor, sheenColor;
  64.                      float eta, thickness) {
  65.     extern point P;
  66.     float Kr, Kt, Kr2, Kt2;
  67.     color C = 0;
  68.  
  69.     vector T = efresnel(-Vf, Nn, eta, Kr, Kt);
  70.         
  71.     illuminance(P, Nn, PI/2) {
  72.         vector Ln = normalize(L);
  73.  
  74.         vector H = normalize(Ln + Vf);
  75.         if (H . Nn > 0)
  76.         C += Kr * sheenColor * Cl * (Ln . Nn) * pow(H . Nn, 4.);
  77.         C += Kr * sheenColor * Cl * (Ln . Nn) * .2;
  78.  
  79.         vector T2 = efresnel(-Ln, Nn, eta, Kr2, Kt2);
  80.         C += skinColor * Cl * (Ln . Nn) * Kt * Kt2 * 
  81.         (singleScatter(T, T2, Nn, .8, .8, thickness) +
  82.          singleScatter(T, T2, Nn, .3, .5, thickness) +
  83.          singleScatter(T, T2, Nn, 0., .4, thickness));
  84.     }
  85.     return C;
  86. }
  87.  
  88. /* Basic surface shader that uses the skin reflection model implemented
  89.    above.  Uses Cs for the basic color of the skin (.8, .5, .5) works
  90.    reasonably well for Caucasian skin.
  91. */
  92. surface k3d_skin2(color Ka = .5; color sheenColor = 1.;
  93.              float eta = 1./1.4, thickness = .5) {
  94.     normal Nn = faceforward(normalize(N), I);
  95.     vector Vf = -normalize(I);
  96.  
  97.     Oi = Os;
  98.     Ci = Os * subsurfaceSkin(Vf, Nn, Cs, sheenColor, eta, thickness);
  99. }
  100.