home *** CD-ROM | disk | FTP | other *** search
/ Altsys Virtuoso 2.0K / virtuoso_20k.iso / DemoApps / Graphics / Viewers / raytracers / rpi / Source / shade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-08  |  4.5 KB  |  182 lines

  1.  
  2. /*
  3.  * (c) 1988 by George Kyriazis
  4.  */
  5.  
  6. /*
  7.  * here is the shading function
  8.  */
  9.  
  10. #include    "ray.h"
  11. #include    "vector.h"
  12. #include    <math.h>
  13.  
  14. struct    color    trace();
  15. struct    intersect    intersect();
  16. struct    ray    sample_ray();
  17.  
  18. /*
  19.  * Shadow check.  Check if the ray from the intersection point to the
  20.  * light, intersection any objects inbetween.  If it does, we have a
  21.  * shadow.
  22.  * One improvement that can be made is to check the transparencies of all
  23.  * the intersecting objects and make the shadow have a different intensity
  24.  * depending on the transparency of the objects
  25.  */
  26. int    shadow(r)
  27. struct    ray    r;
  28. {
  29.     struct    intersect    i;
  30.     struct    ray    r2;
  31. /* to have a shadow, the light ray must intersect an object */
  32. /* first sample the ray around the shadow ray */
  33.     r2 = sample_ray(r, r.theta);
  34.     i = intersect(r2);
  35.  
  36.     if( i.obj == NULL )
  37.         return FALSE;
  38.     else
  39.         return (r.obj != i.obj);
  40. }
  41.  
  42. /*
  43.  * calculate the reflection vector.
  44.  * D. Rogers: "Procedural elements for computer graphics". 5-12. p. 367
  45.  */
  46. struct    vector    reflect(n,v1)
  47. struct    vector    n, v1;
  48. {
  49.     struct    vector    v2;
  50.  
  51.     v2 = vsub( v1, svproduct( 2 * vdot(n, v1), n) );
  52.  
  53.  
  54.     return v2;
  55. }
  56.  
  57. /*
  58.  * calculate the refracted vector.
  59.  * D. Rogers: "Procedural elements for computer graphics". 5-12. p. 367
  60.  */
  61. struct    vector    refract(n, v1, index)
  62. struct    vector    n, v1;
  63. double    index;
  64. {
  65.     double    p, t;
  66.     struct    vector    v2;
  67.  
  68.     v2.x = 0.; v2.y = 0.; v2.z = 0.;
  69.  
  70.     p = vdot(n, v1);
  71.     if(p < 0) {
  72.         t = 1 - ( 1 - p*p ) / ( index*index );
  73.         if( t <= 0 )
  74.             return v2;
  75.         t = -p/index - sqrt(t);
  76.     } else {
  77.         index = 1 / index;
  78.         t = 1 - ( 1 - p*p ) / ( index*index );
  79.         if( t <= 0 )
  80.             return v2;
  81.         t = -p/index + sqrt(t);
  82.     }
  83.  
  84.     v2 = vadd( svproduct(1/index, v1), svproduct(t, n) );
  85.  
  86.     return v2;
  87. }
  88.  
  89. /*
  90.  * the actual shading function.  Recursively calls trace()
  91.  */
  92. struct    color    shade(i, r, n)
  93. struct    intersect    i;
  94. struct    ray    r;
  95. int    n;        /* recursion level */
  96. {
  97.     struct    color    col;
  98.     struct    vector    pt;
  99.     struct    ray    shadow_ray;
  100.     struct    vector    ldir;
  101.     int    shad;
  102.     double    ldot;
  103.     double    spec;
  104.     struct    vector    rr;    /* reflected light direction */
  105.     struct    ray    reflected, refracted;    /* refl, refr directions */
  106.     struct    color    c;
  107.  
  108. /* if the recursion level has been exceeded, return peacefully*/
  109.     if(n > MAXLEVEL) {
  110.         col.r = col.g = col.b = 0.;
  111.         return col;
  112.     }
  113.  
  114. /* initially get the ambient color */
  115.     col = i.obj->ambient;
  116.  
  117. /* first calculate the intersection point */
  118.     pt = vadd( r.pos, svproduct(i.t, r.dir) );
  119.  
  120. /* for the light source first get the vector from it to the intersection */
  121.     ldir = norm( vsub(light.org, pt) );
  122. /* then calc the dot product between the light direction and the normal   */
  123. /* negative because the light direction is reverse (comes from the light) */
  124.     ldot = vdot(i.n, ldir);
  125. /* and find if that shadow ray is stopped by an object */
  126.     shadow_ray.pos = pt;
  127.     shadow_ray.dir = ldir;
  128.     shadow_ray.obj = i.obj;
  129. /* the following is the spreading angle of the ray */
  130.     shadow_ray.theta = light.angle;
  131.     shad = shadow(shadow_ray);
  132.     if( (ldot>0) && !shad ) {
  133. /* statistics */
  134.         shadowline++;
  135. /* add some diffuse color. */
  136.         col.r += ldot * i.obj->diffuse.r;
  137.         col.g += ldot * i.obj->diffuse.g;
  138.         col.b += ldot * i.obj->diffuse.b;
  139. /* now calc the specular color */
  140. /* first calculate the reflected light vector */
  141.         rr = reflect(i.n, ldir);
  142. /* then take the dot of the reflected ray with the viewing direction */
  143. /* that is the specular component. The minus is there for obvious reasons */
  144.         spec = vdot(rr, r.dir);
  145.         spec = (spec < 0) ? 0 : spec;
  146. /* remember the specular width factor?  We use it here! */
  147.         spec = pow(spec, i.obj->width);
  148.         col.r += spec * i.obj->specular.r;
  149.         col.g += spec * i.obj->specular.g;
  150.         col.b += spec * i.obj->specular.b;
  151.     }
  152.  
  153. /* setup the reflected ray */
  154.     reflected.pos = pt;
  155.     reflected.dir = reflect(i.n, r.dir);
  156.     reflected.obj = i.obj;
  157.     reflected.theta = i.obj->refl_diffuse;
  158. /* calculate the reflection */
  159.     reflectline++;
  160.     c = trace(reflected, n+1);
  161.     col.r += c.r * i.obj->refl_color.r * i.obj->reflection;
  162.     col.g += c.g * i.obj->refl_color.g * i.obj->reflection;
  163.     col.b += c.b * i.obj->refl_color.b * i.obj->reflection;
  164. /* now setup the refracted ray */
  165.     refracted.pos = pt;
  166.     refracted.dir = refract(i.n, r.dir, i.obj->index);
  167.     refracted.obj = i.obj;
  168.     refracted.theta = i.obj->refr_diffuse;
  169.     if( (refracted.dir.x == 0.) &&
  170.         (refracted.dir.y == 0.) &&
  171.         (refracted.dir.z == 0.) )
  172.         return col;
  173. /* and calculate the reflection */
  174.     refractline++;
  175.     c = trace(refracted, n+1);
  176.     col.r += c.r * i.obj->refr_color.r * i.obj->refraction;
  177.     col.g += c.g * i.obj->refr_color.g * i.obj->refraction;
  178.     col.b += c.b * i.obj->refr_color.b * i.obj->refraction;
  179.  
  180.     return col;
  181. }
  182.