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_skin1.sl < prev    next >
Encoding:
Text File  |  2008-01-23  |  8.7 KB  |  298 lines

  1. /**
  2.  * RCskin.sl
  3.  * 
  4.  * Copyright (C) 2002, Rudy Cortes   rcortes@hntb.com
  5.  * created  09/16/2002
  6.  * 
  7.  * This software is placed in the public domain and is provided as is 
  8.  * without express or implied warranty. 
  9.  * 
  10.  * Surface shader that implements a shading model that should have a visual 
  11.  * appearence generall similar to that of skin. 
  12.  *
  13.  * Feel free to use this shader to create skin for any character, anywhere and
  14.  * everywhere, Just list me on the credits under "Shading Team"
  15.  *******************************
  16.  * PARAMETERS
  17.  * Kd = the amount of uniform diffusion applyied to the skin
  18.  * skincolor, skinmap = the color of the skin. Using a map overrides original skincolor
  19.  * color value.
  20.  * sheencolor, shinmap = the color of the skin at grazing angles. Using a map overrides
  21.  * original sheencolor color value.
  22.  * blemishfreq, blemishthresh,blemhishopac = control the freqency, threshold and opacity
  23.  * of blemishes on the skin. Use to give skin a little variation.
  24.  * blemishmap = Use a grayscale map to control where the belmishes will be more visible
  25.  * xdir, angle = control the direction of the specular highlights.
  26.  * Oily,oilmap = controls how oily the skin looks. Use a grayscale map to contol
  27.  * oiliness.---Note--- teh oiliy parameter is multiplied with the map.
  28.  * xroughness,yroughness = how rough is the specular highlight on x and Y?
  29.  * poresfreq, poresthresh poresdepth = control the frequency, threshold and depth of the
  30.  * pores.
  31.  **************************************
  32.  *
  33.  * You can replace the header functions by using
  34.  * #include "locilum.h" and #include "noises.h".
  35.  * NOTE- you must copy the entire subsurface skin function to your
  36.  * "locIllum.h" file
  37.  *
  38.  * Enjoy!!
  39.  *
  40.  * Modification history:
  41.  *   9/22/02 Tal Lancaster
  42.  *     Renamed RudyCSkin for RMR.
  43.  *     Made changes so would compile.
  44.  *
  45.  **/
  46.  
  47. #include "k3d_noises.h"
  48.  
  49.  
  50.  /* NECESARY FUNCTIONS */
  51.  
  52.  
  53.  /*---------FROM BMRT's locillum.h-----
  54.  * Greg Ward Larson's anisotropic specular local illumination model.
  55.  * The derivation and formulae can be found in:  Ward, Gregory J.
  56.  * "Measuring and Modeling Anisotropic Reflection," ACM Computer 
  57.  * Graphics 26(2) (Proceedings of Siggraph '92), pp. 265-272, July, 1992.
  58.  */
  59.  
  60. color
  61. LocIllumWardAnisotropic (normal N;  vector V;
  62.                          vector xdir;  float xroughness, yroughness;)
  63. {
  64.     float sqr (float x) { return x*x; }
  65.  
  66.     float cos_theta_r = clamp (N.V, 0.0001, 1);
  67.     vector X = xdir / xroughness;
  68.     vector Y = (N ^ xdir) / yroughness;
  69.  
  70.     color C = 0;
  71.     extern point P;
  72.     illuminance (P, N, PI/2) {
  73.   /* Must declare extern L & Cl because we're in a function */
  74.   extern vector L;  extern color Cl; 
  75.   float nonspec = 0;
  76.   lightsource ("__nonspecular", nonspec);
  77.   if (nonspec < 1) {
  78.       vector LN = normalize (L);
  79.       float cos_theta_i = LN . N;
  80.       if (cos_theta_i > 0.0) {
  81.     vector H = normalize (V + LN);
  82.     float rho = exp (-2 * (sqr(X.H) + sqr(Y.H)) / (1 + H.N))
  83.         / sqrt (cos_theta_i * cos_theta_r);
  84.     C += Cl * ((1-nonspec) * cos_theta_i * rho);
  85.       }
  86.   }
  87.     }
  88.     return C / (4 * xroughness * yroughness);
  89. }    /*---locillum.h ends---*/
  90.  
  91.  
  92. /* ------ ADAPTED FROM Mat Pahr's Skin.sl------
  93.  * --- subsurfaceSkin------
  94.  * Surface shader that implements a shading model that should have a visual 
  95.  * appearence generall similar to that of skin.  Based on phenomenological 
  96.  * information about skin reflectance from Hanrahan and Krueger, 
  97.  * "Reflection from layered surfaces due to subsurface scattering", 
  98.  * proceedings of Siggraph 1993.
  99.  */
  100. /* Evaluate the Henyey-Greenstein phase function for two vectors with
  101.    an asymmetry value g.  v1 and v2 should be normalized and g should 
  102.    be in the range (-1, 1).  Negative values of g correspond to more
  103.    back-scattering and positive values correspond to more forward scattering.
  104. */
  105. float phase(vector v1, v2; float g) {
  106.   float costheta = -v1 . v2;
  107.   return (1. - g*g) / pow(1. + g*g - 2.*g*costheta, 1.5);
  108. }
  109.  
  110. /* Compute a the single-scattering approximation to scattering from
  111.    a one-dimensional volumetric surface.  Given incident and outgoing
  112.    directions wi and wo, surface normal n, asymmetry value g (see above),
  113.    scattering albedo (between 0 and 1 for physically-valid volumes),
  114.    and the thickness of the volume, use the closed-form single-scattering
  115.    equation to approximate overall scattering.
  116. */
  117. float singleScatter(vector wi, wo; normal n; float g, albedo, thickness) {
  118.     float win = abs(wi . n);
  119.     float won = abs(wo . n);
  120.  
  121.     return albedo * phase(wo, wi, g) / (win + won) *
  122.     (1. - exp(-(1/win + 1/won) * thickness));
  123. }
  124.  
  125. vector efresnel(vector II; normal NN; float eta; output float Kr, Kt;) {
  126.     vector R, T;
  127.     fresnel(II, NN, eta, Kr, Kt, R, T);
  128.     Kr = smoothstep(0., .5, Kr);
  129.     Kt = 1. - Kr;
  130.     return normalize(T);
  131. }
  132.  
  133. /* Implements overall skin subsurface shading model.  Takes viewing and
  134.    surface normal information, the base color of the skin, a
  135.    color for an oily surface sheen.
  136. */
  137. color subsurfaceSkin(vector Vf; normal Nn; color skinColor, sheenColor;
  138.                      float eta, thickness) {
  139.   extern point P;
  140.   float Kr, Kt, Kr2, Kt2;
  141.   color C = 0;
  142.  
  143.   vector T = efresnel(-Vf, Nn, eta, Kr, Kt);
  144.       
  145.   illuminance(P, Nn, PI/2) {
  146.       vector Ln = normalize(L);
  147.  
  148.       vector H = normalize(Ln + Vf);
  149.       if (H . Nn > 0)
  150.     C += Kr * sheenColor * Cl * (Ln . Nn) * pow(H . Nn, 4.);
  151.       C += Kr * sheenColor * Cl * (Ln . Nn) * .2;
  152.  
  153.       vector T2 = efresnel(-Ln, Nn, eta, Kr2, Kt2);
  154.       C += skinColor * Cl * (Ln . Nn) * Kt * Kt2 * 
  155.     (singleScatter(T, T2, Nn, .8, .8, thickness) +
  156.      singleScatter(T, T2, Nn, .3, .5, thickness) +
  157.      singleScatter(T, T2, Nn, 0., .4, thickness));
  158.   }
  159.   return C;
  160. }    /* subsurfaceSkin --ends */
  161.  
  162.  
  163. /*
  164.  *shader beggins here.
  165.  */
  166.  
  167. surface k3d_skin1(
  168.   float Kd = .1;
  169.   color skincolor = color (0.7, 0.56, 0.52);
  170.   string skinmap = "";
  171.   color sheenColor = 1.;
  172.   string sheenmap = "";
  173.   float blemishfreq  = 12,
  174.         belmishthresh = 4,
  175.         blemishopac = 1;
  176.   string blemishmap = "";
  177.   float eta = 1.01,
  178.         thickness = 1;
  179.   varying vector xdir = dPdu;
  180.   float angle = 180;
  181.   float oily = 1.5;
  182.   string oilmap = "";
  183.   float xroughness = .3,
  184.         yroughness = .5;
  185.   float poresfreq = 60,
  186.         poresthresh = 3,
  187.         poresdepth = -0.001;)
  188.  
  189.  
  190. {
  191.   /* initialize local variables*/
  192.  
  193.   normal Nf, NN;
  194.   vector Vf = -normalize(I);
  195.   color sc , lc;
  196.   float lo;
  197.   point PP;
  198.   float turb, f;
  199.   float maxfreq = 8;
  200.  
  201.   color Cskin = skincolor;
  202.   color Csheen = sheenColor;
  203.   float oilVal = oily;
  204.  
  205.  
  206.   /*--- layer 1 - add pores to the skin*/
  207.  
  208.   PP = transform ("shader",P) * poresfreq;
  209.   turb = 0;
  210.   for (f = 1; f< maxfreq; f *= 2)
  211.   turb += abs(snoise(PP * f)) / f;
  212.  
  213.   turb = pow(turb,poresthresh) * poresdepth;
  214.  
  215.  
  216.   /* displace normals*/
  217.   NN = calculatenormal(P + turb * normalize(N));
  218.   Nf = faceforward(normalize(NN),I);
  219.  
  220.   /* layer 1 .- apply a subsurface scattered BRDF to the surface.
  221.    * you can use an image map for the color of the skin and the sheen.
  222.    * If the map is not provided use defined colors*/
  223.  
  224.   if (skinmap != "")
  225.       Cskin = color texture(skinmap);
  226.  
  227.   if ( sheenmap != "")
  228.       Csheen = color texture(sheenmap);
  229.  
  230.   sc = Cskin;
  231.  
  232.   /* layer 2 - create small skin blemishes over the skin. Use a map to control
  233.    * where the blemishes are visible */
  234.  
  235.   PP = transform ("shader",P) * blemishfreq;
  236.   turb = 0;
  237.   for (f = 1; f< maxfreq; f *= 2)
  238.   turb += abs(snoise(PP * f)) / f;
  239.  
  240.   turb = pow(turb, belmishthresh );
  241.  
  242.   color red01 = Cskin + 0.05,
  243.         red02 = red01 - 0.05,
  244.         darkred01 = Cskin - 0.05,
  245.         darkred02 = darkred01 - 0.05;
  246.  
  247.  
  248.   color blemishcol = color spline ( turb,
  249.                                     red01,
  250.                                     red02,
  251.                                     darkred01,
  252.                                     red01,
  253.                                     darkred01,
  254.                                     red02,
  255.                                     darkred01,
  256.                                     darkred02,
  257.                                     darkred01,
  258.                                     darkred02,
  259.                                     red01);
  260.  
  261.   lc =  subsurfaceSkin(Vf, Nf, blemishcol, Csheen, 1/eta, thickness);
  262.   lo = 1 * (blemishopac) ;
  263.  
  264.   if (blemishmap != "")
  265.       lo *= float texture (blemishmap);
  266.  
  267.   sc = mix (sc,lc,lo);
  268.  
  269.   /* --Layer 3-- apply an Anisotropic BRDF to simulate the oil layer that lies
  270.   * outside the skin. Oilyness is controlled by the oily, xrougness and yroughness.
  271.   * */
  272.  
  273.   if (oily > 0.01){
  274.   vector anisoDir = xdir;
  275.   if (angle !=0)
  276.   {
  277.     matrix rot = rotate(matrix 1, radians(angle),Nf);
  278.     anisoDir = vtransform(rot,anisoDir);
  279.     }
  280.   lc = LocIllumWardAnisotropic(Nf,Vf,anisoDir,xroughness,yroughness);
  281.  
  282.   if (oilmap != "")
  283.       oilVal *= float texture(oilmap);
  284.  
  285.   sc += (lc * (oilVal * 0.1) );
  286.   }
  287.  
  288.  
  289.  
  290.   /* output*/
  291.  
  292.   Oi = Os;
  293.   Ci = sc + Kd * diffuse(Nf) ;
  294. }
  295.  
  296.  
  297.  
  298.