home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / shade.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  10KB  |  377 lines

  1. /* $Id: shade.c,v 1.3.2.1 1999/11/29 13:41:15 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  8.  * 
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  * 
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28.  
  29.  
  30.  
  31. #ifdef PC_HEADER
  32. #include "all.h"
  33. #else
  34. #ifndef XFree86Server
  35. #include <math.h>
  36. #include <stdio.h>
  37. #else
  38. #include "GL/xf86glx.h"
  39. #endif
  40. #include "light.h"
  41. #include "macros.h"
  42. #include "mmath.h"
  43. #include "shade.h"
  44. #include "pipeline.h"
  45. #include "types.h"
  46. #include "simple_list.h"
  47. #endif
  48.  
  49.  
  50.  
  51.  
  52.  
  53. #define GET_SHINE_TAB_ENTRY( tab, dp, result )    \
  54. do {                            \
  55.    int k = (int) (dp * SHINE_TABLE_SIZE);         \
  56.    result = tab->tab[k];                \
  57. } while(0)
  58.  
  59.  
  60. /* Combinatorics:  
  61.  *     rgba_spec/rgba/rgba_fast/ci
  62.  *     one_side/two_side
  63.  *     compacted_normals/ordinary_normals
  64.  *     cull_mask/no_cull_mask
  65.  *
  66.  * We end up with an award-winning 32 seperate lighting functions.
  67.  */
  68.  
  69.  
  70. /* Table of all the shading functions.
  71.  */
  72. gl_shade_func gl_shade_func_tab[0x20];
  73.  
  74.  
  75. /* The original case where the normal for vertex[j] is normal[j],
  76.  * both stride-aware, and every normal is present.
  77.  */
  78. #define NEXT_NORMAL        STRIDE_F(normal, nstride), mask++
  79. #define NEXT_VERTEX_NORMAL STRIDE_F(normal, nstride), mask++
  80. #define STATE_CHANGE(a,b)  1
  81. #define COMPACTED          0
  82.  
  83. #define TAG(x)           x##_one_sided_masked
  84. #define INVALID(x)       0
  85. #define IDX              CULL_MASK_ACTIVE
  86. #define LIGHT_FRONT(x)   1
  87. #define LIGHT_REAR(x)    0
  88. #define LIGHT_SIDE(x,y)  1
  89. #define CULL(x)          !((x)&VERT_FACE_FLAGS)
  90. #define NR_SIDES         1
  91. #include "shade_tmp.h" 
  92.  
  93. #define TAG(x)           x##_one_sided
  94. #define INVALID(x)       0
  95. #define IDX              0
  96. #define LIGHT_FRONT(x)   1
  97. #define LIGHT_REAR(x)    0
  98. #define LIGHT_SIDE(x,y)  1
  99. #define CULL(x)          0 
  100. #define NR_SIDES         1
  101. #include "shade_tmp.h" 
  102.  
  103. #define TAG(x)           x##_two_sided_masked
  104. #define INVALID(x)       ((x)&invalid)
  105. #define IDX              SHADE_TWOSIDE|CULL_MASK_ACTIVE
  106. #define LIGHT_FRONT(f)   ((f)&VERT_FACE_FRONT)
  107. #define LIGHT_REAR(f)    ((f)&VERT_FACE_REAR)
  108. #define LIGHT_SIDE(x,y)  ((x)&(y))
  109. #define CULL(x)          !((x)&VERT_FACE_FLAGS)
  110. #define NR_SIDES         2
  111. #include "shade_tmp.h"
  112.  
  113. #define TAG(x)           x##_two_sided
  114. #define INVALID(x)       0
  115. #define IDX              SHADE_TWOSIDE
  116. #define LIGHT_FRONT(f)   1
  117. #define LIGHT_REAR(f)    1
  118. #define LIGHT_SIDE(x,y)  1
  119. #define CULL(x)          0
  120. #define NR_SIDES         2
  121. #include "shade_tmp.h"
  122.  
  123. #undef NEXT_NORMAL 
  124. #undef NEXT_VERTEX_NORMAL 
  125. #undef STATE_CHANGE
  126. #undef COMPACTED
  127.  
  128. /* The 'compacted normal' case, where we have a sparse list of normals
  129.  * with flags indicating a new (valid) normal, as now built by the
  130.  * 'glVertex' API routines.   We have a small bonus in that we know
  131.  * in advance that the normal stride must be 3 floats.
  132.  */
  133. #define NEXT_NORMAL         ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
  134. #define NEXT_VERTEX_NORMAL  ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
  135. #define STATE_CHANGE(a,b)   (a & b)
  136. #define COMPACTED            1
  137.  
  138.  
  139. #define TAG(x)           x##_one_sided_masked_compacted
  140. #define INVALID(x)       0
  141. #define IDX              COMPACTED_NORMALS|CULL_MASK_ACTIVE
  142. #define LIGHT_FRONT(x)   1
  143. #define LIGHT_REAR(x)    0
  144. #define LIGHT_SIDE(x,y)  1
  145. #define CULL(x)          !((x)&VERT_FACE_FLAGS)
  146. #define NR_SIDES         1
  147. #include "shade_tmp.h" 
  148.  
  149. #define TAG(x)           x##_one_sided_compacted
  150. #define INVALID(x)       0
  151. #define IDX              COMPACTED_NORMALS
  152. #define LIGHT_FRONT(x)   1
  153. #define LIGHT_REAR(x)    0
  154. #define LIGHT_SIDE(x,y)  1
  155. #define CULL(x)          0
  156. #define NR_SIDES         1
  157. #include "shade_tmp.h" 
  158.  
  159. #define TAG(x)           x##_two_sided_masked_compacted
  160. #define INVALID(x)       ((x)&invalid)
  161. #define IDX              COMPACTED_NORMALS|SHADE_TWOSIDE
  162. #define LIGHT_FRONT(f)   ((f)&VERT_FACE_FRONT)
  163. #define LIGHT_REAR(f)    ((f)&VERT_FACE_REAR)
  164. #define LIGHT_SIDE(x,y)  ((x)&(y))
  165. #define CULL(x)          !((x)&VERT_FACE_FLAGS)
  166. #define NR_SIDES         2
  167. #include "shade_tmp.h"
  168.  
  169. #define TAG(x)           x##_two_sided_compacted
  170. #define INVALID(x)       0
  171. #define IDX              COMPACTED_NORMALS|CULL_MASK_ACTIVE|SHADE_TWOSIDE
  172. #define LIGHT_FRONT(f)   1
  173. #define LIGHT_REAR(f)    1
  174. #define LIGHT_SIDE(x,y)  1
  175. #define CULL(x)          0
  176. #define NR_SIDES         2
  177. #include "shade_tmp.h"
  178.  
  179. #undef COMPACTED
  180. #undef NEXT_NORMAL 
  181. #undef NEXT_VERTEX_NORMAL 
  182. #undef STATE_CHANGE
  183.  
  184.  
  185.  
  186. void gl_init_shade( void )
  187. {
  188.    init_shade_tab_one_sided();
  189.    init_shade_tab_one_sided_masked();
  190.    init_shade_tab_one_sided_compacted();
  191.    init_shade_tab_one_sided_masked_compacted();
  192.  
  193.    init_shade_tab_two_sided();
  194.    init_shade_tab_two_sided_masked();
  195.    init_shade_tab_two_sided_compacted();
  196.    init_shade_tab_two_sided_masked_compacted();
  197. }
  198.  
  199. void gl_update_lighting_function( GLcontext *ctx )
  200. {
  201.    GLuint idx;
  202.  
  203.    if (ctx->Visual->RGBAflag) {
  204.       if (ctx->Light.NeedVertices) {
  205.      if (ctx->Texture.Enabled && 
  206.          ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 
  207.         idx = SHADE_RGBA_SPEC;
  208.      else
  209.         idx = SHADE_RGBA_VERTICES;     
  210.       }  
  211.       else
  212.      idx = SHADE_RGBA_NORMALS;
  213.    }
  214.    else
  215.       idx = 0;
  216.  
  217.    if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
  218.       idx |= SHADE_TWOSIDE;
  219.    }
  220.  
  221.  
  222.    ctx->shade_func_flags = idx;
  223. }
  224.  
  225.  
  226.  
  227. /* This has been split off to allow the normal shade routines to
  228.  * get a little closer to the vertex buffer, and to use the 
  229.  * GLvector objects directly.
  230.  */
  231. void gl_shade_rastpos( GLcontext *ctx,
  232.                GLfloat vertex[4],
  233.                GLfloat normal[3],
  234.                GLfloat Rcolor[4],
  235.                GLuint *index )
  236. {
  237.    GLfloat (*base)[3] = ctx->Light.BaseColor;
  238.    GLubyte *sumA = ctx->Light.BaseAlpha;
  239.    struct gl_light *light;
  240.    GLfloat color[4];
  241.    GLfloat diffuse = 0, specular = 0;
  242.  
  243.    COPY_3V(color, base[0]);
  244.    color[3] = UBYTE_COLOR_TO_FLOAT_COLOR( sumA[0] );
  245.  
  246.    foreach (light, &ctx->Light.EnabledList) {
  247.       GLfloat n_dot_h;
  248.       GLfloat attenuation = 1.0;
  249.       GLfloat VP[3];  
  250.       GLfloat n_dot_VP;
  251.       GLfloat *h;
  252.       GLfloat contrib[3];
  253.       GLboolean normalized;
  254.  
  255.       if (!(light->Flags & LIGHT_POSITIONAL)) {
  256.      COPY_3V(VP, light->VP_inf_norm);
  257.      attenuation = light->VP_inf_spot_attenuation;
  258.       }
  259.       else {
  260.      GLfloat d; 
  261.      
  262.      SUB_3V(VP, light->Position, vertex);
  263.      d = LEN_3FV( VP );
  264.      
  265.      if ( d > 1e-6) {
  266.         GLfloat invd = 1.0F / d;
  267.         SELF_SCALE_SCALAR_3V(VP, invd);
  268.      }
  269.      attenuation = 1.0F / (light->ConstantAttenuation + d * 
  270.                    (light->LinearAttenuation + d * 
  271.                 light->QuadraticAttenuation));
  272.      
  273.      if (light->Flags & LIGHT_SPOT) 
  274.      {
  275.         GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
  276.         
  277.         if (PV_dot_dir<light->CosCutoff) {
  278.            continue; 
  279.         }
  280.         else 
  281.         {
  282.            double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  283.            int k = (int) x;
  284.            GLfloat spot = (GLfloat) (light->SpotExpTable[k][0]
  285.                    + (x-k)*light->SpotExpTable[k][1]);
  286.            attenuation *= spot;
  287.         }
  288.      }
  289.       }
  290.  
  291.       if (attenuation < 1e-3) 
  292.      continue;
  293.  
  294.       n_dot_VP = DOT3( normal, VP );
  295.  
  296.       if (n_dot_VP < 0.0F) {
  297.      ACC_SCALE_SCALAR_3V(color, attenuation, light->MatAmbient[0]);
  298.      continue;
  299.       } 
  300.  
  301.       COPY_3V(contrib, light->MatAmbient[0]);
  302.       ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[0]);
  303.       diffuse += n_dot_VP * light->dli * attenuation;
  304.  
  305.       if (light->IsMatSpecular[0]) {
  306.      if (ctx->Light.Model.LocalViewer) {
  307.         GLfloat v[3];
  308.         COPY_3V(v, vertex);
  309.         NORMALIZE_3FV(v);
  310.         SUB_3V(VP, VP, v);
  311.         h = VP;
  312.         normalized = 0;
  313.      }
  314.      else if (light->Flags & LIGHT_POSITIONAL) {
  315.         h = VP;
  316.         ACC_3V(h, ctx->EyeZDir);
  317.         normalized = 0;
  318.      }
  319.          else {
  320.         h = light->h_inf_norm;
  321.         normalized = 1;
  322.      }
  323.      
  324.      n_dot_h = DOT3(normal, h);
  325.  
  326.      if (n_dot_h > 0.0F) {
  327.         struct gl_material *mat = &ctx->Light.Material[0];
  328.         GLfloat spec_coef;
  329.         GLfloat shininess = mat->Shininess;
  330.  
  331.         if (!normalized) {
  332.            n_dot_h *= n_dot_h;
  333.            n_dot_h /= LEN_SQUARED_3FV( h );
  334.            shininess *= .5;
  335.         }
  336.         
  337.         if (n_dot_h>1.0) {
  338.            spec_coef = (GLfloat) pow( n_dot_h, shininess );
  339.         }
  340.             else {
  341.            struct gl_shine_tab *tab = ctx->ShineTable[0];
  342.            GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
  343.         }
  344.  
  345.         if (spec_coef > 1.0e-10) {
  346.            ACC_SCALE_SCALAR_3V( contrib, spec_coef,
  347.                     light->MatSpecular[0]);
  348.            specular += spec_coef * light->sli * attenuation;
  349.         }
  350.      }
  351.       }
  352.  
  353.       ACC_SCALE_SCALAR_3V( color, attenuation, contrib );
  354.    } 
  355.  
  356.    if (ctx->Visual->RGBAflag) {
  357.       Rcolor[0] = CLAMP(color[0], 0.0F, 1.0F);
  358.       Rcolor[1] = CLAMP(color[1], 0.0F, 1.0F);
  359.       Rcolor[2] = CLAMP(color[2], 0.0F, 1.0F);
  360.       Rcolor[3] = CLAMP(color[3], 0.0F, 1.0F);
  361.    }
  362.    else {
  363.       struct gl_material *mat = &ctx->Light.Material[0];
  364.       GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
  365.       GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
  366.       GLfloat ind = mat->AmbientIndex
  367.                   + diffuse * (1.0F-specular) * d_a
  368.                   + specular * s_a;
  369.       if (ind > mat->SpecularIndex) {
  370.      ind = mat->SpecularIndex;
  371.       }
  372.       *index = (GLuint) (GLint) ind;
  373.    }
  374.  
  375. }
  376.  
  377.