home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GRAPHICS / rayshade.lzh / shade.c < prev    next >
Text File  |  1990-05-08  |  11KB  |  396 lines

  1. /*
  2.  * shade.c
  3.  *
  4.  * Copyright (C) 1989, Craig E. Kolb
  5.  *
  6.  * This software may be freely copied, modified, and redistributed,
  7.  * provided that this copyright notice is preserved on all copies.
  8.  *
  9.  * There is no warranty or other guarantee of fitness for this software,
  10.  * it is provided solely .  Bug reports or fixes may be sent
  11.  * to the author, who may or may not act on them as he desires.
  12.  *
  13.  * You may not include this software in a program or other software product
  14.  * without supplying the source, or without informing the end-user that the
  15.  * source is available for no extra charge.
  16.  *
  17.  * If you modify this software, you should include a notice giving the
  18.  * name of the person performing the modification, the date of modification,
  19.  * and the reason for such modification.
  20.  *
  21.  * $Id: shade.c,v 3.0.1.3 90/04/04 19:04:19 craig Exp $
  22.  *
  23.  * $Log:    shade.c,v $
  24.  * Revision 3.0.1.3  90/04/04  19:04:19  craig
  25.  * patch5: Corrected free()-related problems.
  26.  * 
  27.  * Revision 3.0.1.2  90/03/07  21:31:21  craig
  28.  * patch4: Replaced call to LightCoordSys() with call to VectCoordSys().
  29.  * 
  30.  * Revision 3.0.1.1  89/11/16  20:34:42  craig
  31.  * patch1: Atmospheric effects are now applied to background rays.
  32.  * 
  33.  * Revision 3.0  89/10/27  02:06:03  craig
  34.  * Baseline for first official release.
  35.  * 
  36.  */
  37. #include <math.h>
  38. #include <stdio.h>
  39. #include "constants.h"
  40. #include "typedefs.h"
  41. #include "funcdefs.h"
  42. #include "atmosphere.h"
  43.  
  44. int    level, maxlevel;    /* Current tree depth, max depth */
  45. double    DefIndex = 1.0;        /* Default index of refraction. */
  46. double    TreeCutoff = UNSET;    /* Minimum contribution of any ray. */
  47.  
  48. /*
  49.  * Calculate color of ray.
  50.  */
  51. ShadeRay(hitinfo, ray, dist, back, color, contrib)
  52. HitInfo *hitinfo;        /* Information about point of intersection. */
  53. Ray *ray;            /* Direction and origin of ray. */
  54. double dist;            /* Distance from origin of intersection. */
  55. Color *back;            /* "Background" color */
  56. Color *color;            /* Color to assign current ray. */
  57. double contrib;            /* Contribution of this ray to final color */
  58. {
  59.     Vector hit;
  60.     double realdist;
  61.     extern unsigned long HitRays;
  62.     extern Fog *GlobalFog;
  63.     extern Mist *GlobalMist;
  64.  
  65.     if (dist <= 0.) {
  66.         /*
  67.          * No valid intersection.  Set distance for atmospheric
  68.          * effects and set color of ray to background.
  69.          */
  70.         realdist = FAR_AWAY;
  71.         *color = *back;
  72.         addscaledvec(ray->pos, realdist, ray->dir, &hit);
  73.     } else {
  74.         realdist = dist;
  75.         /*
  76.          * If we got here, then a ray hit something, so...
  77.          */
  78.         HitRays++;
  79.  
  80.         (void)normalize(&hitinfo->norm);
  81.         /*
  82.           * "hit" is the location of intersection in world space.
  83.          * hitinfo->pos is the intersection point in object space.
  84.          */
  85.         addscaledvec(ray->pos, dist, ray->dir, &hit);
  86.         /*
  87.          * Calculate ray color.
  88.          */
  89.         shade(&hit, ray, &hitinfo->norm, hitinfo->prim, &hitinfo->surf,
  90.             back, color, contrib);
  91.     }
  92.     /*
  93.      * If fog or mist is present, modify computed color.
  94.      */
  95.     if (GlobalFog)
  96.         ComputeFog(GlobalFog, realdist, color);
  97.     if (GlobalMist)
  98.         ComputeMist(GlobalMist, &ray->pos, &hit, realdist, color);
  99. }
  100.  
  101. shade(pos, ray, nrm, prim, surf, back, color, contrib)
  102. Vector *pos, *nrm;
  103. Ray *ray;
  104. Primitive *prim;
  105. Surface *surf;
  106. Color *back, *color;
  107. double contrib;
  108. {
  109.     int lnum, entering;
  110.     double dist, k;
  111.     Color newcol;
  112.     Ray NewRay;
  113.     HitInfo hitinfo;
  114.     Vector refl;
  115.     Light *lp;
  116.     extern int nlight;
  117.     extern Light light[];
  118.     extern unsigned long ReflectRays, RefractRays;
  119.     extern double TraceRay();
  120.  
  121.     /*
  122.      * Ambient color is always included.
  123.      */
  124.     *color = surf->amb;
  125.  
  126.     /*
  127.      * Calculate direction of reflected ray.
  128.      */
  129.     k = -dotp(&ray->dir, nrm);
  130.     addscaledvec(ray->dir, 2.*k, *nrm, &refl);
  131.  
  132.     /*
  133.      * Calculate intensity contributed by each light source.
  134.      */
  135.     for(lnum = 0, lp = light;lnum < nlight; lnum++, lp++) {
  136.         if (lp->type == EXTENDED)
  137.             extended_lightray(pos, nrm, &refl, lp,
  138.                       prim, surf, color);
  139.         else
  140.             generic_lightray(pos, nrm, &refl, lp,
  141.                      prim, surf, color);
  142.     }
  143.  
  144.  
  145.     if (level >= maxlevel)
  146.         /*
  147.          * Don't spawn any refracted/reflected rays.
  148.          */
  149.         return;
  150.     /*
  151.      * Specular reflection.
  152.      */
  153.     if(surf->refl > 0. && contrib * surf->refl > TreeCutoff) {
  154.         level++;
  155.         NewRay.shadow = FALSE;
  156.         NewRay.pos = *pos;        /* Origin == hit point */
  157.         NewRay.dir = refl;        /* Direction == reflection */
  158.         NewRay.media = ray->media;    /* Medium == old medium */
  159.         ReflectRays++;
  160.         dist = TraceRay(prim, &NewRay, &hitinfo);
  161.         ShadeRay(&hitinfo, &NewRay, dist, back, &newcol,
  162.                 contrib*surf->refl);
  163.         AddScaledColor(*color, surf->refl, newcol, color);
  164.         level--;
  165.     }
  166.     /*
  167.      * Specular transmission (refraction).
  168.      */
  169.     if(surf->transp > 0. && contrib * surf->transp > TreeCutoff) {
  170.         NewRay.shadow = FALSE;
  171.         NewRay.pos = *pos;        /* Origin == hit point */
  172.         NewRay.media = ray->media;    /* Media == old media */
  173.         if (k < 0.) {
  174.             /*
  175.              * Normal points "away" from incoming ray.
  176.              * Hit "inside" surface -- assume we're exiting.
  177.              * Pop medium from stack.
  178.              */
  179.             if (NewRay.media == (SurfaceList *)0)
  180.                 /*
  181.                  * We had a funky intersection at some
  182.                  * point -- e.g. we hit at the intersection
  183.                  * of two refracting surfaces. Skip it.
  184.                  */
  185.                 return;
  186.             NewRay.media = NewRay.media->next;
  187.             if (refract(&NewRay.dir, surf->kref,
  188.                 NewRay.media ? NewRay.media->surf->kref :
  189.                 DefIndex, ray->dir, *nrm, k))
  190.                 return;
  191.             entering = FALSE;
  192.         } else {
  193.             /*
  194.              * Entering surface.
  195.              */
  196.             if (refract(&NewRay.dir,
  197.                 NewRay.media ? NewRay.media->surf->kref :
  198.                 DefIndex, surf->kref, ray->dir, *nrm, k))
  199.                 return;
  200.             NewRay.media = add_surface(surf, NewRay.media);
  201.             entering = TRUE;
  202.         }
  203.         level++;
  204.         RefractRays++;
  205.         dist = TraceRay((Primitive *)NULL, &NewRay, &hitinfo);
  206.         ShadeRay(&hitinfo, &NewRay, dist, back, &newcol,
  207.                 contrib * surf->transp);
  208.         AddScaledColor(*color, surf->transp, newcol, color);
  209.         if (entering)
  210.             free((char *)NewRay.media);
  211.         level--;
  212.     }
  213. }
  214.  
  215. /*
  216.  * Sample an extended (area) light source.
  217.  */
  218. extended_lightray(pos, norm, refl, lp, obj, surf, color)
  219. Vector *pos, *norm, *refl;
  220. Light *lp;
  221. Primitive *obj;
  222. Surface *surf;
  223. Color *color;
  224. {
  225.     int uSample, vSample;
  226.     double jit, vbase, ubase, vpos, upos;
  227.     Color newcol;
  228.     Vector Uaxis, Vaxis, toLight, SampleDir;
  229.     extern double lightdist, JitterWeight, SampleSpacing;
  230.     extern int JitSamples, Jittered, SampleNumber;
  231.  
  232.     /*
  233.      * Determinte two orthoganal vectors which line in the plane
  234.      * whose normal is defined by the vector from the center
  235.      * of the light source to the point of intersection and
  236.      * which passes through the center of the light source.
  237.       */
  238.     vecsub(lp->pos, *pos, &toLight);
  239.     VectCoordSys(&toLight, &Uaxis, &Vaxis);
  240.  
  241.     jit = 2. * lp->radius * SampleSpacing;
  242.  
  243.     if (Jittered) {
  244.         /*
  245.          * Sample a single point, determined by SampleNumber,
  246.          * on the extended source.
  247.          */
  248.         vpos = -lp->radius + (SampleNumber % JitSamples) * jit;
  249.         upos = -lp->radius + (SampleNumber / JitSamples) * jit;
  250.         vpos += nrand() * jit;
  251.         upos += nrand() * jit;
  252.         veccomb(upos, Uaxis, vpos, Vaxis, &SampleDir);
  253.         vecadd(toLight, SampleDir, &SampleDir);
  254.         /*
  255.          * Lightdist, the distance to the light source, is
  256.          * used by inshadow(), called from Lighting().
  257.          */
  258.         lightdist = normalize(&SampleDir);
  259.         Lighting(pos,norm,refl,lp,obj,surf,&SampleDir,color);
  260.         return;
  261.     }
  262.  
  263.     newcol.r = newcol.g = newcol.b = 0.;
  264.  
  265.     /*
  266.      * Sample JitSamples^2 -4 points arranged in a square lying on the
  267.      * plane calculated above.  The size of the square is equal to
  268.      * the diameter of the light source.  We sample the square at equal
  269.      * intervals in the U and V direction, with "jitter" thrown in to mask
  270.      * aliasing.  The corners of the square are skipped to speed up
  271.      * the calculation and to more closely model a circular source.
  272.      */
  273.     ubase = -lp->radius;
  274.     for(uSample = 1;uSample <= JitSamples;uSample++, ubase += jit) {
  275.         vbase = -lp->radius;
  276.         for(vSample=1;vSample <= JitSamples;vSample++,vbase += jit) {
  277.             /*
  278.              * Skip corners.
  279.              */
  280.             if ((uSample == 1 || uSample == JitSamples) &&
  281.                 (vSample == 1 || vSample == JitSamples))
  282.                 continue;
  283.             vpos = vbase + nrand() * jit;
  284.             upos = ubase + nrand() * jit;
  285.             veccomb(upos, Uaxis, vpos, Vaxis, &SampleDir);
  286.             vecadd(toLight, SampleDir, &SampleDir);
  287.             lightdist = normalize(&SampleDir);
  288.             Lighting(pos, norm, refl, lp, obj, surf,
  289.                 &SampleDir, &newcol);
  290.         }
  291.     }
  292.  
  293.     AddScaledColor(*color, JitterWeight, newcol, color);
  294. }
  295.  
  296. /*
  297.  * Lighting calculations for a point or directional light source.
  298.  */
  299. generic_lightray(pos, norm, reflect, lp, obj, surf, color)
  300. Vector *pos, *norm, *reflect;
  301. Light *lp;
  302. Primitive *obj;
  303. Surface *surf;
  304. Color *color;
  305. {
  306.     Vector Nlightray;
  307.  
  308.     lightray(lp, pos, &Nlightray);
  309.  
  310.     Lighting(pos, norm, reflect, lp, obj, surf, &Nlightray, color);
  311. }
  312.  
  313. /*
  314.  * Compute shading function (diffuse reflection and specular highlight)
  315.  * given the point of intersection, incident ray, normal to the surface,
  316.  * direction of the reflected ray,
  317.  * the current light source, the object hit, the surface hit, and
  318.  * the ray to the current light source.
  319.  *
  320.  * This function *adds* the computed color to "color".
  321.  */
  322. Lighting(pos, norm, refl, lp, obj, surf, tolight, color)
  323. Vector *pos, *norm, *refl, *tolight;
  324. Light *lp;
  325. Primitive *obj;
  326. Surface *surf;
  327. Color *color;
  328. {
  329.     Color bright;
  330.     double intens;
  331.  
  332.     /*
  333.      * Diffuse reflection.
  334.      * Falls off as the cosine of the angle between
  335.      * the normal and the ray to the light.
  336.      */
  337.     intens = dotp(norm, tolight);
  338.     if(intens <= 0.) {
  339.         /*
  340.          * Object does not face light source.
  341.          * If the surface is translucent, add in
  342.          * diffuse and specular components due to
  343.          * light hitting the other side of the surface.
  344.          * (This is a "poor man's" diffuse transmission
  345.          * and specularly transmitted highlights.  Note
  346.          * that we ignore index of refraction here...)
  347.          */
  348.         if (surf->translucency == 0.)
  349.             return;
  350.         if (inshadow(&bright, obj, lp, pos, tolight))
  351.             return;
  352.         /*
  353.          * We use -translucency to counter the fact
  354.          * that intens is < 0.
  355.          */
  356.         intens *= -surf->translucency;
  357.         color->r += surf->diff.r * intens * bright.r;
  358.         color->g += surf->diff.g * intens * bright.g;
  359.         color->b += surf->diff.b * intens * bright.b;
  360.         intens = -dotp(refl, tolight);
  361.         if (intens <= 0.)
  362.             return;
  363.         intens = surf->translucency * pow(intens, surf->stcoef);
  364.         color->r += surf->spec.r * intens * bright.r;
  365.         color->g += surf->spec.g * intens * bright.g;
  366.         color->b += surf->spec.b * intens * bright.b;
  367.         return;
  368.     }
  369.     /*
  370.      * Add diffuse reflection component.
  371.      */
  372.     if (inshadow(&bright, obj, lp, pos, tolight))
  373.         return;        /* Object in shadow. */
  374.     color->r += surf->diff.r * intens * bright.r;
  375.     color->g += surf->diff.g * intens * bright.g;
  376.     color->b += surf->diff.b * intens * bright.b;
  377.     /*
  378.      * Specularly reflected highlights.
  379.      * Fall off as the cosine of the angle
  380.      * between the reflected ray and the ray to the light source.
  381.      */
  382.     if (surf->coef < EPSILON)
  383.         return;
  384.     intens = dotp(refl, tolight);
  385.     if(intens <= 0.)
  386.         return;
  387.     /*
  388.      * Specular highlight = cosine of the angle raised to the
  389.      * appropriate power.
  390.      */
  391.     intens = pow(intens, surf->coef);
  392.     color->r += surf->spec.r * intens * bright.r;
  393.     color->g += surf->spec.g * intens * bright.g;
  394.     color->b += surf->spec.b * intens * bright.b;
  395. }
  396.