home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / mtvraytrace / part02 / shade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-26  |  4.5 KB  |  166 lines

  1. /***********************************************************************
  2.  * $Author: markv $
  3.  * $Revision: 1.2 $
  4.  * $Date: 88/09/12 12:58:01 $
  5.  * $Log:    shade.c,v $
  6.  * Revision 1.2  88/09/12  12:58:01  markv
  7.  * Added specular reflections and shadow caching.  When a object
  8.  * is found between a light source and the current point we are trying
  9.  * to shade, that object is cached (indexed by recursion level) in the
  10.  * lightsource.  Next time we test a shadow against the light source,
  11.  * we test this object first.  If it is between us and the light source,
  12.  * we can correctly shadow the object without calling Intersect().
  13.  * 
  14.  * Note: specular highlights call the unix pow() function, which seems
  15.  * to be REALLY expensive.  Optimizations could be made here.
  16.  * 
  17.  * Revision 1.1  88/09/11  11:00:44  markv
  18.  * Initial revision
  19.  *  
  20.  ***********************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include "defs.h"
  25. #include "extern.h"
  26.  
  27. /***********************************************************************
  28.  * Shade(level, weight, P, N, I, hit, col)
  29.  *
  30.  * Wow! Too many parameters!
  31.  *
  32.  * Shade is the driving force of the raytracer.  It calculates the actual
  33.  * luminance at point P, given N, the normal, and I the incident vector.
  34.  * We also pass in the hit, because the normal generating code might need it.
  35.  * The color is returned in col.
  36.  ***********************************************************************/
  37.  
  38. Shade(level, weight, P, N, I, hit, col) 
  39.  int level ;
  40.  Flt weight ;
  41.  Vec P, N, I ;
  42.  Isect * hit;
  43.  Color col ;
  44. {
  45.     Ray     tray ;
  46.     Color     tcol ;
  47.     Vec     L, H, R ;
  48.     Flt     t ;
  49.     Flt    diff ;
  50.     Flt     spec ;
  51. #ifdef SHADOW_CACHING
  52.     Object    * cached ;
  53. #endif /* SHADOW_CACHING */
  54.     Isect nhit ;
  55.     Surface    * surf ;
  56.     int l ;
  57.  
  58.     col[0] = col[1] = col[2] = 0.0 ;
  59.     surf = hit -> isect_prim -> o_surf ;
  60.  
  61.     for (l = 0; l < nLights; l++) {
  62.         VecSub(Lights[l].light_pos, P, L);
  63.         if (VecDot(N,L) >= 0.0) {
  64.             t = VecNormalize(L);
  65.             VecCopy(P, tray.P);
  66.             VecCopy(L, tray.D);
  67.             nShadows ++ ;
  68. #ifdef SHADOW_CACHING
  69.             cached = Lights[l].light_obj_cache[level] ;
  70.             if (cached 
  71.                 && (cached -> o_procs -> intersect) 
  72.                     (cached, &tray, &nhit) 
  73.                 && nhit.isect_t < t) {
  74.                 /* 
  75.                  * we are in shadow, continue...
  76.                  */
  77.                 nShadowCacheHits ++ ;
  78.                 continue ;
  79.             }
  80. #endif /* SHADOW_CACHING */
  81.             if (Shadow(&tray, &nhit, t)) {
  82.                 diff = VecDot(N,L) * surf -> surf_kd 
  83.                     * Lights[l].light_brightness ;
  84. #ifdef SHADOW_CACHING
  85.                 Lights[l].light_obj_cache[level] = NULL ;
  86. #endif /* SHADOW_CACHING */
  87.                 VecAddS(diff, surf -> surf_color, col, col) ;
  88.                 SpecularDirection(I, N, R) ;
  89.                 VecNormalize(R) ;
  90.                 if (surf -> surf_shine > rayeps) {
  91.                     spec = VecDot(R,L) ;
  92.                     if (spec > rayeps) {
  93.                         spec = pow(spec, surf -> surf_shine ) * Lights[l].light_brightness ;
  94.                         col[0] += spec ; 
  95.                         col[1] += spec ; 
  96.                         col[2] += spec ;
  97.                     }
  98.                 }
  99.             } else {
  100. #ifdef SHADOW_CACHING
  101.                 Lights[l].light_obj_cache[level] = 
  102.                     nhit.isect_prim ;
  103. #endif /* SHADOW_CACHING */
  104.             }
  105.                 
  106.         }
  107.     }
  108.  
  109.     VecCopy(P, tray.P);
  110.  
  111.     if(surf -> surf_ks * weight > minweight) {
  112.         nReflected ++ ;
  113.         SpecularDirection(I, N, tray.D);
  114.         VecNormalize(tray.D);
  115.         Trace(level + 1, surf -> surf_ks * weight, &tray, tcol);
  116.         VecAddS(surf -> surf_ks, tcol, col, col);
  117.     }
  118.  
  119.     if (surf -> surf_kt * weight > minweight) { 
  120.         nRefracted ++ ;
  121.         if (hit -> isect_enter) 
  122.             TransmissionDirection(NULL, surf, I, N, tray.D) ;
  123.         else    
  124.             TransmissionDirection(surf, NULL, I, N, tray.D) ;
  125.         Trace(level + 1, surf -> surf_kt * weight, &tray, tcol) ;
  126.         VecAddS(surf -> surf_kt, tcol, col, col) ;
  127.     }
  128. }
  129.  
  130. /***********************************************************************
  131.  * SpecularDirection(I, N, R)
  132.  * 
  133.  * Given an incident vector I, and the normal N, calculate the 
  134.  * direction of the reflected ray R.
  135.  ***********************************************************************/
  136.  
  137. SpecularDirection(I, N, R)
  138.  Vec I, N, R;
  139. {
  140.     VecComb(1.0/fabs(VecDot(I,N)), I, 2.0, N, R);
  141.     VecNormalize(R);
  142. }
  143.  
  144. /***********************************************************************
  145.  * TransmissionDirection(m1, m2, I, N, T)
  146.  *
  147.  * calculates the direction of the transmitted ray
  148.  ***********************************************************************/
  149.  
  150. TransmissionDirection(m1, m2, I, N, T)
  151.  Surface *m1, *m2;
  152.  Vec I, N, T ;
  153. {
  154.     Flt n1, n2, eta, c1, cs2 ;
  155.     n1 = m1 ? m1 -> surf_ior : 1.0 ;
  156.     n2 = m2 ? m2 -> surf_ior : 1.0 ;
  157.     eta = n1/n2 ;
  158.  
  159.     c1 = -VecDot(I,N);
  160.     cs2 = 1.0 - eta * eta*(1.0 - c1*c1);
  161.     if (cs2 < 0.0)
  162.         return 0;
  163.     VecComb(eta, I, eta*c1-sqrt(cs2), N, T);
  164.     return(1);
  165. }
  166.