home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / mg / common / mgshade.c < prev   
Encoding:
C/C++ Source or Header  |  1993-09-10  |  4.5 KB  |  168 lines

  1. /*
  2.  * Software shaders.
  3.  * These operate in the mg environment.
  4.  */
  5. #include "mgP.h"
  6.  
  7. #define    DOT(a,b)  ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z)
  8.  
  9. #define    CCMUL(A,B,C)  ((C).r=(A).r*(B).r, (C).g=(A).g*(B).g, (C).b=(A).b*(B).b)
  10. #define    CCADD(A,B,C)  ((C).r=(A).r+(B).r, (C).g=(A).g+(B).g, (C).b=(A).b+(B).b, (C).a = (A).a + (B).a)
  11.  
  12. #define CSCALE(s, A, B) ( (B).r = (A).r * s, (B).g = (A).g * s, (B).b = (A).b * s, (B).a = (A).b * s)
  13.  
  14.  
  15. #define    CCSADD(A,B,s,C)    \
  16.      ((C).r += (s)*(A).r*(B).r, \
  17.       (C).g += (s)*(A).g*(B).g, \
  18.       (C).b += (s)*(A).b*(B).b)
  19.  
  20. /*
  21.  * Transform a vector covariantly
  22.  */
  23. static void
  24. cotransform(register Transform Tinv, register Point3 *in, Point3 *out)
  25. {
  26.     out->x = Tinv[0][0]*in->x + Tinv[0][1]*in->y + Tinv[0][2]*in->z;
  27.     out->y = Tinv[1][0]*in->x + Tinv[1][1]*in->y + Tinv[1][2]*in->z;
  28.     out->z = Tinv[2][0]*in->x + Tinv[2][1]*in->y + Tinv[2][2]*in->z;
  29. }
  30.  
  31. static float euck1 = 1.0;        /* inverse power falloff */
  32. static float euck2 = 0.0;        /* safety zone around light */
  33. static float fog = 0.0;            /* fog control */
  34. static float hypk1 = .5;        /* controls exponential falloff */
  35. static float hypk2 = .0;        /* controls exponential falloff */
  36. static float sphk1 = .5;        /* controls exponential falloff */
  37. static float sphk2 = 0.0;        /* safety zone around light */
  38.  
  39. /*
  40.  * Euclidean shader
  41.  *
  42.  * We depend on the following mg features:
  43.  *    _mgc->xstk->hasinv (cleared whenever transform changes)
  44.  *    _mgc->W2C, C2W (initialized from camera at mgworldbegin())
  45.  */
  46.  
  47. int mg_eucshade(int nv, HPoint3 *v, Point3 *n, ColorA *c, ColorA *cs)
  48. {
  49.     struct mgxstk *mx = _mgc->xstk;
  50.     struct mgastk *ma = _mgc->astk;
  51.     struct LtLight *l;
  52.     int i;
  53.     HPoint3 V;
  54.     Point3 N, I;
  55.     float s;
  56.     Color Ca;
  57.  
  58.     euck1 = ma->lighting.attenmult;
  59.     euck2 = ma->lighting.attenmult2;
  60.     fog = ma->lighting.attenconst;
  61. #define    EYE    ((HPoint3 *) (_mgc->C2W[3]))    /* Eye (camera) position as an HPoint3 */
  62.  
  63.     if(!mx->hasinv) {
  64.     TmInvert(mx->T, mx->Tinv);
  65.     mx->hasinv = 1;
  66.     }
  67.  
  68.     /* "ambient" color */
  69.     
  70.     Ca.r = Ca.g = Ca.b = 0;
  71.     CCSADD(ma->mat.ambient, ma->lighting.ambient, ma->mat.ka, Ca);
  72.  
  73.     for(i = 0; i < nv; i++, v++, n++, c++, cs++) {
  74.     ColorA *thiscolor = c;
  75.  
  76.                     /* Transform point by T */
  77.     HPt3Transform(mx->T, v, &V);    /* V = v in world coords */
  78.     HPt3SubPt3(EYE, &V, &I);    /* I = EYE - V (point-to-eye vector) */
  79.  
  80.                     /* Transform normal by T'^-1 */
  81.     cotransform(mx->Tinv, n, &N);
  82.     s = 1/sqrt(DOT(N,N));
  83.     if(DOT(N,I) < 0) {
  84.         s = -s;            /* Flip normal to face the viewer */
  85.  
  86.         /* Hack: use otherwise-useless emission color, if defined,
  87.          * as the back-side material color.
  88.          */
  89.         if(ma->mat.valid & MTF_EMISSION)
  90.         thiscolor = (ColorA*)&ma->mat.emission;
  91.     }
  92.  
  93.     N.x *= s;  N.y *= s;  N.z *= s;
  94.     
  95.                     /* Ambient term */
  96.     *(Color *)cs = Ca;
  97.  
  98.     for(l = ma->lighting.lights; l != NULL; l = l->next) {
  99.         register Point3 *L;
  100.         Point3 Lt;
  101.         float bright, ls, ll, ln, power;
  102.  
  103.                     /* Diffuse term */
  104.         bright = l->intensity;
  105.         if(l->globalposition.w == 0) {
  106.         L = (Point3 *)&l->globalposition;
  107.         ll = DOT(*L,*L);
  108.         } else {
  109.         HPt3SubPt3(&l->globalposition, &V, &Lt);
  110.         L = ≪
  111.         ll = DOT(Lt,Lt);
  112.         /* ll = (ll > euck2) ? ll : euck2; */
  113.          power = pow(ll, -euck1/2.0);
  114.             /* Inverse square falloff */
  115.          bright *= power;
  116.         }
  117.  
  118.         ln = DOT(*L,N);
  119.         if(ln <= 0)            /* Ignore lights shining from behind */
  120.         continue;
  121.  
  122.         ls = sqrt(ll);
  123.         s = ma->mat.kd * bright * (ln/ls);
  124.                     /* cosine law: L.N diffuse shading */
  125.  
  126.         CCSADD(l->color, *thiscolor, s, *cs);
  127.  
  128.         if(ma->mat.ks > 0) {    /* Specular term */
  129.         Point3 H;        /* H: halfway between L and I */
  130.  
  131.         H.x = L->x/ls + I.x, H.y = L->y/ls + I.y, H.z = L->z/ls + I.z;
  132.  
  133.         s = DOT(H,N) / sqrt(DOT(H,H));
  134.                     /* cos angle(H,N) */
  135.  
  136.             /* Note we need s>=0 for specular term to make sense.
  137.              * This should be true since we checked
  138.              * that both L.N and I.N are positive above.
  139.              */
  140.  
  141.                     /* shininess = specular exponent */
  142.         s = ma->mat.ks * bright * pow(s, ma->mat.shininess);
  143.  
  144.         CCSADD(l->color, ma->mat.specular, s, *cs);
  145.         }
  146.     }
  147.     /* insert fog code */
  148.      if (fog)    {
  149.         float k1, k2;
  150.         float d = HPt3Distance(&V, EYE);
  151.         ColorA surfcolor, fogcolor;
  152.         d = d - euck2;        /* fog-free sphere of radius euck2 */
  153.         if (d < 0) d = 0;
  154.         k1 = exp( -fog * d);
  155.         k2 = 1.0 - k1;
  156.         CSCALE(k1, *cs, surfcolor); 
  157.         CSCALE(k2, _mgc->background, fogcolor); 
  158.         CCADD(surfcolor, fogcolor, *cs);
  159.         }
  160.          
  161.     if(cs->r < 0) cs->r = 0; else if(cs->r > 1) cs->r = 1;
  162.     if(cs->g < 0) cs->g = 0; else if(cs->g > 1) cs->g = 1;
  163.     if(cs->b < 0) cs->b = 0; else if(cs->b > 1) cs->b = 1;
  164.     cs->a = c->a;
  165.     }
  166.     return 0;
  167. }
  168.