home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / pxm_ray / pxm_ray.lha / pxm-ray / pixel_shade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-09  |  4.5 KB  |  186 lines

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