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_superplank.sl < prev    next >
Encoding:
Text File  |  2008-01-23  |  11.2 KB  |  334 lines

  1. /****************************************************************************
  2.  * superplank.sl -- another surface shader for wood planks.
  3.  *
  4.  * Description:
  5.  *   Makes texture of wooden planks in s-t space.  This wood looks rather
  6.  *   like varnished oak planks, with staggered planks, rings and grain,
  7.  *   reflections (either traced or via reflection map), and bumps.
  8.  *   It can make the plank pattern as either straight staggered planks
  9.  *   or in a parquet pattern.
  10.  *
  11.  * Parameters:
  12.  *   Ka, Kd, Ks, specularcolor, roughness - work just like the plastic shader
  13.  *   Kr, eta - reflection amount and index of refraction (for fresnel)
  14.  *   Ktrace, Krefl, reflmap - const for trace, for refl map, filename
  15.  *   txtscale - overall scaling factor for the texture
  16.  *   Km - overall scaling factor for bumpiness.
  17.  *   lightwood - wood-like color from which the various shades are derived.
  18.  *   plankwidth - width of each plank (in terms of s/t)
  19.  *   planklength - length of each plank (in terms of s/t)
  20.  *   groovewidth - width of the grooves between the planks (in terms of s/t)
  21.  *   groovedepth - depth of the groove indentations (in shader space units)
  22.  *   groovecolor - the color of the "grooves" between the planks
  23.  *   plankpattern - plank orientation pattern  1=straight, 2=parquet
  24.  *   plankspertile - for parquet, number of sub-planks
  25.  *   plankstagger - for staggered, how much are the rows of planks staggered
  26.  *   plankvary - controls how much wood color varies from plank to plank
  27.  *   ringscale - scaling for the ring spacing
  28.  *   ringwidth - relative width of the dark ring parts
  29.  *   wavy - relative wavyness of the ring pattern
  30.  *   grainy - relative graininess (0 = no fine grain)
  31.  *   grainscale - scaling for the fine grain
  32.  *   graindepth - depth of grain and ring grooves
  33.  *   varnishbumpfreq - frequency of bumps in the varnish coating
  34.  *   varnishbumpamp - height of bumps in the varnish coating
  35.  *
  36.  * Antialiasing: this shader does a pretty good job of antialiasing itself,
  37.  *   even with low sampling densities.
  38.  *
  39.  * Author: written by Larry Gritz
  40.  *          current contact address: gritzl@acm.org
  41.  *
  42.  * $Revision: 1.1 $     $Date: 2006/02/25 20:11:54 $
  43.  *
  44.  ****************************************************************************/
  45.  
  46. #include "k3d_noises.h"
  47. #include "k3d_patterns.h"
  48.  
  49.  
  50.  
  51.  
  52. surface k3d_superplank(        /* Parameters: */
  53.             /* BRDF */
  54.             float Ka = 1, Kd = 1;    /* Overall ambient & diffuse response */
  55.             float Ks = .75, roughness = .02;    /* Spec highlight control */
  56.             color specularcolor = 1;    /* Spec reflection color */
  57.             float Kr = 1, eta = 1.5;    /* Mirror refl & index of refr */
  58.             float Ktrace = 1, Krefl = 0;    /* trace and reflection map */
  59.             string reflmap = "";
  60.             /* Overall texturing control */
  61.             float txtscale = 1;    /* Overall scaling factor */
  62.             float Km = 1;    /* Overall bumpiness factor */
  63.             color lightwood = color(.5, .2, .067);    /* light wood color */
  64.             /* Plank layout */
  65.             float plankpattern = 1;    /* 1=straight, 2=parquet */
  66.             float plankspertile = 4;    /* For parquet */
  67.             float plankwidth = .05;    /* Width of a plank */
  68.             float planklength = .75;    /* Length of a plank */
  69.             float groovewidth = 0.001;    /* Width of the grooves between planks */
  70.             float groovedepth = .0004;    /* Depth of the groove */
  71.             color groovecolor = color(.01, .003, .001);
  72.             float plankstagger = 1;    /* How much should rows be staggered */
  73.             float plankvary = 0.8;    /* Wood color variation plank-to-plank */
  74.             /* Wood appearance */
  75.             float ringscale = 25;    /* Larger makes more, thinner rings */
  76.             float ringwidth = 1;    /* Relative ring width */
  77.             float wavy = 0.08;    /* Larger makes rings more wavy */
  78.             float grainy = 1;    /* Relative graininess */
  79.             float grainscale = 60;    /* Larger makes smaller "grains" */
  80.             float graindepth = 0.0001;    /* Depth of divots where grains are */
  81.             float varnishbumpfreq = 30;    /* Bump freq of the varnish */
  82.             float varnishbumpamp = 0.0003;    /* How big are the varnish bumps? */
  83.   )
  84. {
  85.   /* mapping coordinates */
  86.   float ss, tt;
  87.   float grain_s, grain_t, ring_s, ring_t, plank_s, plank_t;
  88.   /* antialiasing */
  89.   float swidth, twidth, fwidth;
  90.   float sw, tw, overallscale;
  91.   /* Planks & grooves */
  92.   uniform float PGWIDTH, PGHEIGHT, GWF, GHF;
  93.   float whichrow, whichplank;    /* Index for each row & plank within row */
  94.   float w, h;            /* temporaries */
  95.   float groovy;            /* 0 in groove, 1 in woody part */
  96.   /* Wood appearance */
  97.   color Ct, woodcolor;
  98.   float r2;
  99.   float fade, ttt;
  100.   float ring;            /* 1 in a ring darkening, 0 where not */
  101.   float grain;            /* 1 inside a grain bit, 0 elsewhere */
  102.   /* Illumination model */
  103.   float adjustedKs;
  104.   vector IN;            /* normalized I vector */
  105.   normal NN;            /* normalized N for displacing */
  106.   normal Nf;            /* forward facing, normalized normal */
  107.   vector R, T_dummy;        /* Refl (and tummy transmit) from fresnel */
  108.   float fresnelKr, fresnelKt;    /* Fresnel reflection coefficients */
  109.   float shadlen;        /* length of a unit of shader space */
  110.   float disp;            /* accumulate displacement here */
  111.   point Pndc;            /* NDC coordinate of P */
  112.   vector V;
  113.   color Cspec;
  114.   float nonspec;
  115.   float tmp;
  116.  
  117.   /*
  118.    * 1. Setup.
  119.    *
  120.    * Determine the basic mapping, filter sizes for antialiasing, other
  121.    * values used throughout the shader.
  122.    */
  123.  
  124.   /* First, determine the basic mapping */
  125.   ss = s * txtscale;
  126.   tt = t * txtscale;
  127.   /* Compute the basic filter size for antialiasing */
  128.   swidth = filterwidth(ss);
  129.   twidth = filterwidth(tt);
  130.   fwidth = max(swidth, twidth);
  131.  
  132.   /* How much current space corresponds to a unit of s or t?
  133.    * We will use this later to help scale the displacement, this making
  134.    * the bumps scale relative to the overall pattern, rather than being
  135.    * strictly tied to the scale of the object.
  136.    */
  137.   overallscale = (length(Deriv(P, ss)));
  138.  
  139.  
  140.   /*
  141.    * 2. Plank pattern.
  142.    *
  143.    * Determine which row and plank we're on, and come up with an
  144.    * antialiased term for whether we're in or out of a groove.
  145.    */
  146.   if(plankpattern == 1)
  147.     {
  148.       /* Straight, staggered planks */
  149.       PGWIDTH = plankwidth + groovewidth;
  150.       PGHEIGHT = planklength + groovewidth;
  151.       plank_s = ss / PGWIDTH;
  152.       whichrow = floor(plank_s);
  153.       /* Jiggle each row */
  154.       plank_t = tt / PGHEIGHT + 20 * plankstagger * cellnoise(whichrow);
  155.       whichplank = floor(plank_t);
  156.     }
  157.   else
  158.     {
  159.       /* Parquet pattern */
  160.       PGWIDTH = plankwidth + groovewidth;
  161.       PGHEIGHT = PGWIDTH * plankspertile;
  162.       plank_s = ss / PGWIDTH;
  163.       whichrow = floor(plank_s);
  164.       plank_t = tt / PGHEIGHT;
  165.       whichplank = floor(plank_t);
  166.       if(mod((whichrow / plankspertile) + whichplank, 2) >= 1)
  167.     {
  168.       plank_s = tt / PGWIDTH;
  169.       plank_t = ss / PGHEIGHT;
  170.       whichrow = floor(plank_s);
  171.       whichplank = floor(plank_t);
  172.       tmp = ss;
  173.       ss = tt;
  174.       tt = tmp;
  175.       tmp = swidth;
  176.       swidth = twidth;
  177.       twidth = tmp;
  178.     }
  179.     }
  180.   /* Now whichplank is a unique integer index for each plank */
  181.  
  182.   /* Figure out where the grooves are.  The value groovy is 0 where there
  183.    * are grooves, 1 where the wood grain is visible.  Do some simple
  184.    * antialiasing by trying to box filter the edges of the grooves.
  185.    */
  186.  
  187.   /* compute half width & length of groove as fraction of plank size */
  188.   GWF = groovewidth * 0.5 / PGWIDTH;
  189.   GHF = groovewidth * 0.5 / PGHEIGHT;
  190.   sw = swidth / PGWIDTH;
  191.   tw = twidth / PGHEIGHT;
  192.   if(sw >= 1)
  193.     w = 1 - 2 * GWF;        /* Filter width is wider than the plank itself */
  194.   else
  195.     w = filteredpulse(whichrow + GWF, whichrow + 1 - GWF, plank_s, sw);
  196.   if(tw >= 1)
  197.     h = 1 - 2 * GHF;        /* Filter width is longer than the plank itself */
  198.   else
  199.     h = filteredpulse(whichplank + GHF, whichplank + 1 - GHF, plank_t, tw);
  200.   groovy = w * h;
  201.  
  202.   /*
  203.    * 3. Ring and grain patterns, color and specularity adjustment.
  204.    *
  205.    * The wood has rings at one scale, grain at a finer scale.  They
  206.    * interact subtly.
  207.    */
  208.  
  209.   /* Compute the filter width first, so we don't bother with more if
  210.    * the rings are too small to see.
  211.    */
  212.   fwidth = max(swidth * ringscale, twidth * ringscale);
  213.   fade = smoothstep(.75, 4, fwidth);
  214.   if(fade < 0.999)
  215.     {
  216.       ring_s = ss * ringscale;
  217.       ring_t = tt * ringscale;
  218.       ttt = ring_t + whichplank * 28.38 + wavy * noise(8 * ring_s, ring_t);
  219.       ring = ringscale * noise(ring_s - whichplank * 4.18, ttt / 20);
  220.       ring -= floor(ring);
  221.       ring =
  222.     0.3 + 0.7 * smoothstep(.55 - .35 * ringwidth, 0.55,
  223.                    ring) * (1 - smoothstep(0.75, 0.8, ring));
  224.       ring = (1 - fade) * ring + 0.65 * fade;
  225.  
  226.       /* Grain pattern */
  227.       fwidth = max(swidth * grainscale, twidth * grainscale);
  228.       fade = smoothstep(.75, 4, fwidth);
  229.       if(fade < 0.999)
  230.     {
  231.       grain_s = ss * grainscale;
  232.       grain_t = tt * grainscale;
  233.       r2 = 1.3 - noise(12 * grain_s, grain_t);
  234.       r2 = grainy * r2 * r2 + (1 - grainy);
  235.       grain = (1 - fade) * r2 + (0.75 * fade);
  236.     }
  237.       else
  238.     grain = 0.75;
  239.     }
  240.   else
  241.     {
  242.       ring = 0.4875;
  243.       grain = 0.75;
  244.     }
  245.   grain *= (.85 + .15 * ring);
  246.  
  247.   /* Start with the light wood color */
  248.   woodcolor = lightwood;
  249.   /* Add some plank-to-plank variation in overall color */
  250.   woodcolor *=
  251.     1 - plankvary / 2 + plankvary * float cellnoise(whichplank, whichrow);
  252.   /* Darken the wood according to the ring and grain patterns */
  253.   woodcolor *= (1 - 0.25 * ring) * (1 - .5 * grain);
  254.   /* Combine the rings, grain, plank variation into one surface color */
  255.   Ct = mix(groovecolor, woodcolor, groovy);
  256.   /* Less specular in the grooves, more specular in the dark wood. */
  257.   adjustedKs = Ks * (1 + .2 * ring) * (1 + .3 * grain) * groovy;
  258.  
  259.  
  260.   /*
  261.    * 4. Bumps
  262.    *
  263.    * We do some bump mapping to make the grooves and grain depressed,
  264.    * and add some general lumpiness to the varnish layer.
  265.    */
  266.   if(Km > 0)
  267.     {
  268.       /* Grooves */
  269.       disp = -groovedepth * (1 - groovy);
  270.       /* Random bumps on the varnish */
  271.       if(varnishbumpamp > 0)
  272.     disp +=
  273.       varnishbumpamp * (2 *
  274.                 noise(varnishbumpfreq * ss,
  275.                   varnishbumpfreq * tt) - 1);
  276.       /* Depressions due to grain & rings */
  277.       disp -= graindepth * (.75 * grain + ring);
  278.       /* Find out how long a unit of shader space is, in current units */
  279.       NN = normalize(N);
  280.       shadlen = overallscale / length(ntransform("shader", NN));
  281.  
  282.       /* Recalculate N */
  283.       N = calculatenormal(P + (Km * shadlen * disp) * NN);
  284.     }
  285.  
  286.   /*
  287.    * 5. BRDF
  288.    *
  289.    * The wood itself behaves like plastic, the varnish overtop reflects
  290.    * using the fresnel formula (grazing angles reflect like mirrors).
  291.    * Have some subtle interaction between grain and specularity.
  292.    */
  293.  
  294.   IN = normalize(I);
  295.   V = -IN;
  296.   Nf = faceforward(normalize(N), I);
  297.   fresnel(IN, Nf, 1 / eta, fresnelKr, fresnelKt, R, T_dummy);
  298.   fresnelKr *= Kr;
  299.   Cspec = 0;
  300.   illuminance(P, Nf, PI / 2)
  301.   {
  302.     nonspec = 0;
  303.     lightsource("__nonspecular", nonspec);
  304.     if(nonspec < 1)
  305.       {
  306.     vector H = normalize(normalize(L) + V);
  307.     Cspec +=
  308.       Cl * ((1 - nonspec) *
  309.         smoothstep(.6, .85, pow(max(0, Nf.H), 8 / roughness)));
  310.       }
  311.   }
  312.   Ci =
  313.     (1 - fresnelKr) * (Ct * (Ka * ambient() + Kd * diffuse(Nf))) +
  314.     adjustedKs * (specularcolor * Cspec);
  315.  
  316.   /* Only compute reflections if Kr > 0 */
  317.   if(fresnelKr > 0.001)
  318.     {
  319.       if(Krefl > 0 && reflmap != "")
  320.     {
  321.       Pndc = transform("NDC", P);
  322.       Ci +=
  323.         fresnelKr * specularcolor * texture(reflmap, xcomp(Pndc),
  324.                         1 - ycomp(Pndc));
  325.     }
  326.       if(Ktrace > 0)
  327.     Ci += Ktrace * fresnelKr * specularcolor * trace(P, R);
  328.     }
  329.  
  330.   /* Scale by opacity */
  331.   Oi = Os;
  332.   Ci *= Oi;
  333. }
  334.