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

  1. /****************************************************************************
  2.  * uberlight.sl - a light with many fun controls.
  3.  *
  4.  * Description:
  5.  *   Based on Ronen Barzel's paper "Lighting Controls for Computer
  6.  *   Cinematography" (in Journal of Graphics Tools, vol. 2, no. 1: 1-20).
  7.  *
  8.  * Rather than explicitly pass "from" and "to" points to indicate the
  9.  * position and direction of the light (as spotlight does), this light
  10.  * emits from the origin of the local light shader space and points
  11.  * toward the +z axis (also in shader space).  Thus, to position and
  12.  * orient the light source, you must translate and rotate the
  13.  * coordinate system in effect when the light source is declared.
  14.  * Perhaps this is a new idea for some users, but it isn't really
  15.  * hard, and it vastly simplifies the math in the shader.
  16.  *
  17.  * Basic color/brightness controls:
  18.  *   intensity - overall intensity scaling of the light
  19.  *   lightcolor - overall color filtering for the light
  20.  *
  21.  * Light type:
  22.  *   lighttype - one of "spot", "omni", or "arealight".  Spot lights are
  23.  *       those that point in a particular direction (+z in local light
  24.  *       space, for this light).  Omni lights throw light in all directions.
  25.  *       Area lights are emitted from actual geometry (this only works on
  26.  *       BMRT area lights for the time being).
  27.  *
  28.  * Distance shaping and falloff controls:
  29.  *   cuton, cutoff - define the depth range (z range from the origin, in
  30.  *       light coordinates) over which the light is active.  Outside
  31.  *       this range, no energy is transmitted.
  32.  *   nearedge, faredge - define the width of the transition regions
  33.  *       for the cuton and cutoff.  The transitions will be smooth.
  34.  *   falloff - defines the exponent for falloff.  A falloff of 0 (the
  35.  *       default) indicates that the light is the same brightness
  36.  *       regardless of distance from the source.  Falloff==1 indicates
  37.  *       linear (1/r) falloff, falloff==2 indicates 1/r^2 falloff
  38.  *       (which is physically correct for point-like sources, but
  39.  *       sometimes hard to use).
  40.  *   falloffdist - the distance at which the incident energy is actually
  41.  *       equal to intensity*lightcolor.  In other words, the intensity
  42.  *       is actually given by:   I = (falloffdist / distance) ^ falloff
  43.  *   maxintensity - to prevent the light from becoming unboundedly
  44.  *       large when the distance < falloffdist, the intensity is
  45.  *       smoothly clamped to this maximum value.
  46.  *   parallelrays - when 0 (the default), the light appears to emanate
  47.  *       from a single point (i.e., the rays diverge).  When nonzero, 
  48.  *       the light rays are parallel, as if from an infinitely distant
  49.  *       source (like the sun).
  50.  *
  51.  * Shaping of the cross-section.  The cross-section of the light cone
  52.  * is actually described by a superellipse with the following
  53.  * controls:
  54.  *   shearx, sheary - define the amount of shear applied to the light
  55.  *       cone direction.  Default is 0, meaning that the center of the
  56.  *       light cone is aligned with the z-axis in local light space.
  57.  *   width, height - define the dimensions of the "barn door" opening.
  58.  *       They are the cross-sectional dimensions at a distance of 1
  59.  *       from the light.  In other words, width==height==1 indicates a
  60.  *       90 degree cone angle for the light.
  61.  *   wedge, hedge - the amount of width and height edge fuzz,
  62.  *       respectively.  Values of 0 will make a sharp cutoff, larger
  63.  *       values (up to 1) will make the edge softer.
  64.  *   roundness - controls how rounded the corners of the superellipse
  65.  *       are.  If this value is 0, the cross-section will be a perfect
  66.  *       rectangle.  If the value is 1, the cross-section will be a
  67.  *       perfect ellipse.  In-between values control the roundness of
  68.  *       the corners in a fairly obvious way.
  69.  *   beamdistribution - controls intensity falloff due to angle.
  70.  *       A value of 0 (the default) means no angle falloff.  A value
  71.  *       of 1 is roughly physically correct for a spotlight and 
  72.  *       corresponds to a cosine falloff.  For a BMRT area light, the
  73.  *       cosine falloff happens automatically, so 0 is the right physical
  74.  *       value to use.  In either case, you may use larger values to
  75.  *       make the spot more bright in the center than the outskirts.
  76.  *       This parameter has no effect for omni lights.
  77.  *
  78.  * Cookie or slide filter:
  79.  *   slidename - if a filename is supplied, a texture lookup will be
  80.  *       done and the light emitted from the source will be filtered
  81.  *       by that color, much like a slide projector.  If you want to
  82.  *       make a texture map that simply blocks light, just make it
  83.  *       black-and-white, but store it as an RGB texture.  For
  84.  *       simplicity, the shader assumes that the texture file will
  85.  *       have at least three channels.
  86.  *
  87.  * Projected noise on the light:
  88.  *   noiseamp - amplitude of the noise.  A value of 0 (the default) 
  89.  *       means not to use noise.  Larger values increase the blotchiness
  90.  *       of the projected noise.
  91.  *   noisefreq - frequency of the noise.
  92.  *   noiseoffset - spatial offset of the noise.  This can be animated,
  93.  *       for example, you can use the noise to simulate the
  94.  *       attenuation of light as it passes through a window with 
  95.  *       water drops dripping down it.
  96.  * 
  97.  * Shadow mapped shadows.  For PRMan (and perhaps other renderers),
  98.  * shadows are mainly computed by shadow maps.  Please consult the
  99.  * PRMan documentation for more information on the meanings of these
  100.  * parameters.
  101.  *   shadowmap - the name of the texture containing the shadow map.  If
  102.  *       this value is "" (the default), no shadow map will be used.
  103.  *   shadowblur - how soft to make the shadow edge, expressed as a
  104.  *       percentage of the width of the entire shadow map.
  105.  *   shadowbias - the amount of shadow bias to add to the lookup.
  106.  *   shadownsamps - the number of samples to use.
  107.  *
  108.  * Ray-traced shadows.  These options work only for BMRT:
  109.  *   raytraceshadow - if nonzero, cast rays to see if we are in shadow.
  110.  *       The default is zero, i.e., not to try raytracing.
  111.  *   nshadowrays - The number of rays to trace to determine shadowing.
  112.  *   shadowcheat - add this offset to the light source position.  This
  113.  *       allows you to cause the shadows to emanate as if the light
  114.  *       were someplace else, but without changing the area
  115.  *       illuminated or the appearance of highlights, etc.
  116.  *
  117.  * "Fake" shadows from a blocker object.  A blocker is a superellipse
  118.  * in 3-space which effectively blocks light.  But it's not really
  119.  * geometry, the shader just does the intersection with the
  120.  * superellipse.  The blocker is defined to lie on the x-y plane of
  121.  * its own coordinate system (which obviously needs to be defined in
  122.  * the RIB file using the CoordinateSystem command).
  123.  *   blockercoords - the name of the coordinate system that defines the
  124.  *       local coordinates of the blocker.  If this is "", it indicates 
  125.  *       that the shader should not use a blocker at all.
  126.  *   blockerwidth, blockerheight - define the dimensions of the blocker's
  127.  *       superellipse shape.
  128.  *   blockerwedge, blockerhedge - define the fuzzyness of the edges.
  129.  *   blockerround - how round the corners of the blocker are (same
  130.  *       control as the "roundness" parameter that affects the light
  131.  *       cone shape.
  132.  *
  133.  * Joint shadow controls:
  134.  *   shadowcolor - Shadows (i.e., those regions with "occlusion" as
  135.  *       defined by any or all of the shadow map, ray cast, or
  136.  *       blocker) don't actually have to block light.  In fact, in
  137.  *       this shader, shadowed regions actually just change the color
  138.  *       of the light to "shadowcolor".  If this color is set to
  139.  *       (0,0,0), it effectively blocks all light.  But if you set it
  140.  *       to, say (.25,.25,.25), it will make the shadowed regions lose
  141.  *       their full brightness but not go completely dark.  Another
  142.  *       use is if you are simulating sunlight: set the lightcolor to
  143.  *       something yellowish and make the shadowcolor dark but
  144.  *       somewhat bluish.  Another effect of shadows is to set the
  145.  *       __nonspecular flag so that the shadowed regions are lit only
  146.  *       diffusely, without highlights.
  147.  * 
  148.  * Other controls:
  149.  *   nonspecular - when set to 1, this light does not create
  150.  *       specular highlights!  The default is 0, which means it makes
  151.  *       highlights just fine (except for regions in shadows, as
  152.  *       explained above).  This is very handy for lights that are
  153.  *       meant to be fill lights, rather than key lights.
  154.  *       NOTE: This depends on the surface shader looking for, and
  155.  *       correctly acting upon, this parameter.  The built-in functions
  156.  *       diffuse(), specular() and phong() all do this, for PRMan 3.5
  157.  *       and later, as well as BMRT 2.3.5 and later.  But if you write
  158.  *       your own illuminance loops in your surface shader, you've got
  159.  *       to account for it yourself.  The PRMan user manual explains how
  160.  *       to do this.
  161.  *   __nondiffuse - the analog to nonspecular; if this flag is set to
  162.  *       1, this light will only cast specular highlights but not
  163.  *       diffuse light.  This is useful for making a light that only
  164.  *       makes specular highlights, without affecting the rest of the
  165.  *       illumination in the scene.  All the same caveats apply with
  166.  *       respect to the surface shader, as described above for
  167.  *       __nonspecular.
  168.  *   __foglight - the "noisysmoke" shader distributed with BMRT will add
  169.  *       atmospheric scattering only for those lights that have this
  170.  *       parameter set to 1 (the default).  In other words, if you use
  171.  *       this light with noisysmoke, you can set this flag to 0 to
  172.  *       make a particular light *not* cause illumination in the fog.
  173.  *       Note that the noisysmoke shader is distributed with BMRT but
  174.  *       will also work just fine with PRMan (3.7 or later).
  175.  *
  176.  * NOTE: this shader has one each of: blocker, shadow map, slide, and
  177.  * noise texture.  Some advanced users may want more than one of some or
  178.  * all of these.  It is left as an exercise for the reader to make such
  179.  * extensions to the shader.
  180.  *
  181.  ***************************************************************************
  182.  *
  183.  * This shader was written as part of the course notes for ACM
  184.  * SIGGRAPH '98, course 11, "Advanced RenderMan: Beyond the Companion"
  185.  * (co-chaired by Tony Apodaca and Larry Gritz).  Feel free to use and
  186.  * distribute the source code of this shader, but please leave the
  187.  * original attribution and all comments.
  188.  *
  189.  * This shader was tested using Pixar's PhotoRealistic RenderMan 3.7
  190.  * and the Blue Moon Rendering Tools (BMRT) release 2.3.6.  I have
  191.  * tried to avoid Shading Language constructs which wouldn't work on
  192.  * older versions of these renderers, but I do make liberal use of the
  193.  * "vector" type and I often declare variables where they are used,
  194.  * rather than only at the beginning of blocks.  If you are using a
  195.  * renderer which does not support these new language features, just
  196.  * substitute "point" for all occurrances of "vector", and move the
  197.  * variable declarations to the top of the shader.
  198.  *
  199.  * Author: coded by Larry Gritz, 1998
  200.  *         based on paper by Ronen Barzel, 1997
  201.  *
  202.  * Contacts:  {lg|ronen}@pixar.com
  203.  *
  204.  *
  205.  * $Revision: 1.2 $    $Date: 2006/03/08 16:01:22 $
  206.  *
  207.  ****************************************************************************/
  208.  
  209.  
  210.  
  211.  
  212. /* Superellipse soft clipping
  213.  * Input:
  214.  *   - point Q on the x-y plane
  215.  *   - the equations of two superellipses (with major/minor axes given by
  216.  *        a,b and A,B for the inner and outer ellipses, respectively)
  217.  * Return value:
  218.  *   - 0 if Q was inside the inner ellipse
  219.  *   - 1 if Q was outside the outer ellipse
  220.  *   - smoothly varying from 0 to 1 in between
  221.  */
  222. float clipSuperellipse(point Q;    /* Test point on the x-y plane */
  223.                float a, b;    /* Inner superellipse */
  224.                float A, B;    /* Outer superellipse */
  225.                float roundness;    /* Same roundness for both ellipses */
  226.   )
  227. {
  228.   float result = 0;
  229.   float x = abs(xcomp(Q)), y = abs(ycomp(Q));
  230.   if(x != 0 || y != 0)
  231.     {                /* avoid degenerate case */
  232.       if(roundness < 1.0e-6)
  233.     {
  234.       /* Simpler case of a square */
  235.       result = 1 - (1 - smoothstep(a, A, x)) * (1 - smoothstep(b, B, y));
  236.     }
  237.       else if(roundness > 0.9999)
  238.     {
  239.       /* Simple case of a circle */
  240.       float sqr(float x)
  241.       {
  242.         return x * x;
  243.       }
  244.       float q = a * b / sqrt(sqr(b * x) + sqr(a * y));
  245.       float r = A * B / sqrt(sqr(B * x) + sqr(A * y));
  246.       result = smoothstep(q, r, 1);
  247.     }
  248.       else
  249.     {
  250.       /* Harder, rounded corner case */
  251.       float re = 2 / roundness;    /* roundness exponent */
  252.       float q = a * b * pow(pow(b * x, re) + pow(a * y, re), -1 / re);
  253.       float r = A * B * pow(pow(B * x, re) + pow(A * y, re), -1 / re);
  254.       result = smoothstep(q, r, 1);
  255.     }
  256.     }
  257.   return result;
  258. }
  259.  
  260.  
  261.  
  262.  
  263.  
  264. /* Volumetric light shaping
  265.  * Inputs:
  266.  *   - the point being shaded, in the local light space
  267.  *   - all information about the light shaping, including z smooth depth
  268.  *     clipping, superellipse x-y shaping, and distance falloff.
  269.  * Return value:
  270.  *   - attenuation factor based on the falloff and shaping
  271.  */
  272. float ShapeLightVolume(point PL;    /* Point in light space */
  273.                string lighttype;    /* what kind of light */
  274.                vector axis;    /* light axis */
  275.                float znear, zfar;    /* z clipping */
  276.                float nearedge, faredge;
  277.                float falloff, falloffdist;    /* distance falloff */
  278.                float maxintensity;
  279.                float shearx, sheary;    /* shear the direction */
  280.                float width, height;    /* xy superellipse */
  281.                float hedge, wedge, roundness;
  282.                float beamdistribution;    /* angle falloff */
  283.   )
  284. {
  285.   /* Examine the z depth of PL to apply the (possibly smooth) cuton and
  286.    * cutoff.
  287.    */
  288.   float atten = 1;
  289.   float PLlen = length(PL);
  290.   float Pz;
  291.   if(lighttype == "spot")
  292.     {
  293.       Pz = zcomp(PL);
  294.     }
  295.   else
  296.     {
  297.       /* For omni or area lights, use distance from the light */
  298.       Pz = PLlen;
  299.     }
  300.   atten *= smoothstep(znear - nearedge, znear, Pz);
  301.   atten *= 1 - smoothstep(zfar, zfar + faredge, Pz);
  302.  
  303.   /* Distance falloff */
  304.   if(falloff != 0)
  305.     {
  306.       if(PLlen > falloffdist)
  307.     {
  308.       atten *= pow(falloffdist / PLlen, falloff);
  309.     }
  310.       else
  311.     {
  312.       float s = log(1 / maxintensity);
  313.       float beta = -falloff / s;
  314.       atten *= (maxintensity * exp(s * pow(PLlen / falloffdist, beta)));
  315.     }
  316.     }
  317.  
  318.   /* Clip to superellipse */
  319.   if(lighttype != "omni" && beamdistribution > 0)
  320.     atten *= pow(zcomp(normalize(vector PL)), beamdistribution);
  321.   if(lighttype == "spot")
  322.     {
  323.       atten *=
  324.     1 - clipSuperellipse(PL / Pz - point(shearx, sheary, 0), width,
  325.                  height, width + wedge, height + hedge,
  326.                  roundness);
  327.     }
  328.   return atten;
  329. }
  330.  
  331.  
  332.  
  333.  
  334. /* Evaluate the occlusion between two points, P1 and P2, due to a fake
  335.  * blocker.  Return 0 if the light is totally blocked, 1 if it totally
  336.  * gets through.
  337.  */
  338. float BlockerContribution(point P1, P2;
  339.               string blockercoords;
  340.               float blockerwidth, blockerheight;
  341.               float blockerwedge, blockerhedge;
  342.               float blockerround;
  343.   )
  344. {
  345.   float unoccluded = 1;
  346.   /* Get the surface and light positions in blocker coords */
  347.   point Pb1 = transform(blockercoords, P1);
  348.   point Pb2 = transform(blockercoords, P2);
  349.   /* Blocker works only if it's straddled by ray endpoints. */
  350.   if(zcomp(Pb2) * zcomp(Pb1) < 0)
  351.     {
  352.       vector Vlight = (Pb1 - Pb2);
  353.       point Pplane = Pb1 - Vlight * (zcomp(Pb1) / zcomp(Vlight));
  354.       unoccluded *=
  355.     clipSuperellipse(Pplane, blockerwidth, blockerheight,
  356.              blockerwidth + blockerwedge,
  357.              blockerheight + blockerhedge, blockerround);
  358.     }
  359.   return unoccluded;
  360. }
  361.  
  362.  
  363.  
  364.  
  365. light k3d_uberlight(
  366.              /* Basic intensity and color of the light */
  367.              string lighttype = "spot"; float intensity = 1;
  368.              color lightcolor = color(1, 1, 1);
  369.              /* Z shaping and distance falloff */
  370.              float cuton = 0.01, cutoff = 1.0e6, nearedge =
  371.              0, faredge = 0;
  372.              float falloff = 0, falloffdist = 1, maxintensity = 1;
  373.              float parallelrays = 0;
  374.              /* xy shaping of the cross-section and angle falloff */
  375.              float shearx = 0, sheary = 0;
  376.              float width = 1, height = 1, wedge = .1, hedge = .1;
  377.              float roundness = 1;
  378.              float beamdistribution = 0;
  379.              /* Cookie or slide to control light cross-sectional color */
  380.              string slidename = "";
  381.              /* Noisy light */
  382.              float noiseamp = 0, noisefreq = 4;
  383.              vector noiseoffset = 0;
  384.              /* Shadow mapped shadows */
  385.              string shadowmap = "";
  386.              float shadowblur = 0.01, shadowbias = .01, shadownsamps =
  387.              16;
  388.              color shadowcolor = 0;
  389.              /* Ray traced shadows */
  390.              float raytraceshadow = 0, nshadowrays = 1;
  391.              vector shadowcheat = vector "shader"(0, 0, 0);
  392.              /* Fake blocker shadow */
  393.              string blockercoords = "";
  394.              float blockerwidth = 1, blockerheight = 1;
  395.              float blockerwedge = .1, blockerhedge =
  396.              .1, blockerround = 1;
  397.              /* Miscellaneous controls */
  398.              float nonspecular = 0;
  399.              output varying float __nonspecular = 0;
  400.              output float __nondiffuse = 0;
  401.              output float __foglight = 1;)
  402. {
  403.   /* For simplicity, assume that the light is at the origin of shader
  404.    * space and aimed in the +z direction.  So to move or orient the
  405.    * light, you transform the coordinate system in the RIB stream, prior
  406.    * to instancing the light shader.  But that sure simplifies the
  407.    * internals of the light shader!  Anyway, let PL be the position of
  408.    * the surface point we're shading, expressed in the local light
  409.    * shader coordinates.
  410.    */
  411.   point PL = transform("shader", Ps);
  412.  
  413.   /* For PRMan, we've gotta do it the hard way */
  414.   point from = point "shader"(0, 0, 0);
  415.   vector axis = normalize(vector "shader"(0, 0, 1));
  416.  
  417.   uniform float angle;
  418.   if(lighttype == "spot")
  419.     {                /* Spot light */
  420.       uniform float maxradius = 1.4142136 * max(height + hedge + abs(sheary),
  421.                         width + wedge + abs(shearx));
  422.       angle = atan(maxradius);
  423.     }
  424.   else if(lighttype == "arealight")
  425.     {                /* BMRT area light */
  426.       angle = PI / 2;
  427.     }
  428.   else
  429.     {                /* Omnidirectional light */
  430.       angle = PI;
  431.     }
  432.   __nonspecular = nonspecular;
  433.  
  434.   illuminate(from, axis, angle)
  435.   {
  436.     /* Accumulate attenuation of the light as it is affected by various
  437.      * blockers and whatnot.  Start with no attenuation (i.e., a 
  438.      * multiplicative attenuation of 1.
  439.      */
  440.     float atten = 1.0;
  441.     color lcol = lightcolor;
  442.  
  443.     /* Basic light shaping - the volumetric shaping is all encapsulated
  444.      * in the ShapeLightVolume function.
  445.      */
  446.     atten *=
  447.       ShapeLightVolume(PL, lighttype, axis, cuton, cutoff, nearedge, faredge,
  448.                falloff, falloffdist, maxintensity / intensity, shearx,
  449.                sheary, width, height, hedge, wedge, roundness,
  450.                beamdistribution);
  451.  
  452.     /* Project a slide or use a cookie */
  453.     if(slidename != "")
  454.       {
  455.     point Pslide = PL / point(width + wedge, height + hedge, 1);
  456.     float zslide = zcomp(Pslide);
  457.     float xslide = 0.5 + 0.5 * xcomp(Pslide) / zslide;
  458.     float yslide = 0.5 - 0.5 * ycomp(Pslide) / zslide;
  459.     lcol *= color texture(slidename, xslide, yslide);
  460.       }
  461.  
  462.     /* If the volume says we aren't being lit, skip the remaining tests */
  463.     if(atten > 0)
  464.       {
  465.     /* Apply noise */
  466.     if(noiseamp > 0)
  467.       {
  468. #pragma nolint
  469.         float n = noise(noisefreq * (PL + noiseoffset) * point(1, 1, 0));
  470.         n = smoothstep(0, 1, 0.5 + noiseamp * (n - 0.5));
  471.         atten *= n;
  472.       }
  473.  
  474.     /* Apply shadow mapped shadows */
  475.     float unoccluded = 1;
  476.     if(shadowmap != "")
  477.       unoccluded *=
  478.         1 - shadow(shadowmap, Ps, "blur", shadowblur, "samples",
  479.                shadownsamps, "bias", shadowbias);
  480.     point shadoworigin;
  481.     if(parallelrays == 0)
  482.       shadoworigin = from;
  483.     else
  484.       shadoworigin = point "shader"(xcomp(PL), ycomp(PL), cuton);
  485.  
  486.     /* Apply blocker fake shadows */
  487.     if(blockercoords != "")
  488.       {
  489.         unoccluded *=
  490.           BlockerContribution(Ps, shadoworigin, blockercoords,
  491.                   blockerwidth, blockerheight, blockerwedge,
  492.                   blockerhedge, blockerround);
  493.       }
  494.     lcol = mix(shadowcolor, lcol, unoccluded);
  495.     __nonspecular = 1 - unoccluded * (1 - __nonspecular);
  496.       }
  497.     Cl = (atten * intensity) * lcol;
  498.     if(parallelrays != 0)
  499.       L = axis * length(Ps - from);
  500.   }
  501. }
  502.