home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / tnl / t_vb_lighttmp.h < prev    next >
Text File  |  2002-10-29  |  30KB  |  1,004 lines

  1. /* $Id: t_vb_lighttmp.h,v 1.26 2002/10/29 20:29:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2001  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.  * Authors:
  28.  *    Brian Paul
  29.  *    Keith Whitwell <keith@tungstengraphics.com>
  30.  */
  31.  
  32.  
  33. #if (IDX & LIGHT_FLAGS)
  34. #  define VSTRIDE (4 * sizeof(GLfloat))
  35. #  define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/
  36. #  define CHECK_MATERIAL(x)  (flags[x] & VERT_BIT_MATERIAL)
  37. #  define CHECK_END_VB(x)    (flags[x] & VERT_BIT_END_VB)
  38. #  if (IDX & LIGHT_COLORMATERIAL)
  39. #    define CMSTRIDE STRIDE_F(CMcolor, CMstride)
  40. #    define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0)
  41. #    define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL))
  42. #    define DO_ANOTHER_NORMAL(x) \
  43.      ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
  44. #    define REUSE_LIGHT_RESULTS(x) \
  45.      ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
  46. #  else
  47. #    define CMSTRIDE (void)0
  48. #    define CHECK_COLOR_MATERIAL(x) 0
  49. #    define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL))
  50. #    define DO_ANOTHER_NORMAL(x) \
  51.       ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
  52. #    define REUSE_LIGHT_RESULTS(x) \
  53.       ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
  54. #  endif
  55. #else
  56. #  define VSTRIDE vstride
  57. #  define NSTRIDE nstride
  58. #  define CHECK_MATERIAL(x)   0               /* no materials on array paths */
  59. #  define CHECK_END_VB(XX)     (XX >= nr)
  60. #  if (IDX & LIGHT_COLORMATERIAL)
  61. #     define CMSTRIDE STRIDE_F(CMcolor, CMstride)
  62. #     define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */
  63. #     define CHECK_VALIDATE(x) (x < nr)
  64. #     define DO_ANOTHER_NORMAL(x) 0        /* always stop to recalc colormat */
  65. #  else
  66. #     define CMSTRIDE (void)0
  67. #     define CHECK_COLOR_MATERIAL(x) 0        /* no colormaterial */
  68. #     define CHECK_VALIDATE(x) (0)
  69. #     define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */
  70. #  endif
  71. #  define REUSE_LIGHT_RESULTS(x) 0         /* always have a new normal */
  72. #endif
  73.  
  74.  
  75.  
  76. #if (IDX & LIGHT_TWOSIDE)
  77. #  define NR_SIDES 2
  78. #else
  79. #  define NR_SIDES 1
  80. #endif
  81.  
  82.  
  83. /* define TRACE if to trace lighting code */
  84.  
  85.  
  86. /*
  87.  * ctx is the current context
  88.  * VB is the vertex buffer
  89.  * stage is the lighting stage-private data
  90.  * input is the vector of eye or object-space vertex coordinates
  91.  */
  92. static void TAG(light_rgba_spec)( GLcontext *ctx,
  93.                   struct vertex_buffer *VB,
  94.                   struct gl_pipeline_stage *stage,
  95.                   GLvector4f *input )
  96. {
  97.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  98.    GLfloat (*base)[3] = ctx->Light._BaseColor;
  99.    GLchan sumA[2];
  100.    GLuint j;
  101.  
  102.    const GLuint vstride = input->stride;
  103.    const GLfloat *vertex = (GLfloat *)input->data;
  104.    const GLuint nstride = VB->NormalPtr->stride;
  105.    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
  106.  
  107.    GLfloat *CMcolor;
  108.    GLuint CMstride;
  109.  
  110.    GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
  111.    GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
  112.    GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
  113.    GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
  114.  
  115.    const GLuint nr = VB->Count;
  116.    const GLuint *flags = VB->Flag;
  117.    struct gl_material (*new_material)[2] = VB->Material;
  118.    const GLuint *new_material_mask = VB->MaterialMask;
  119.  
  120.    (void) flags;
  121.    (void) nstride;
  122.    (void) vstride;
  123.  
  124. #ifdef TRACE
  125.    fprintf(stderr, "%s\n", __FUNCTION__ );
  126. #endif
  127.  
  128.    if (IDX & LIGHT_COLORMATERIAL) {
  129.       if (VB->ColorPtr[0]->Type != GL_FLOAT || 
  130.       VB->ColorPtr[0]->Size != 4)
  131.      import_color_material( ctx, stage );
  132.  
  133.       CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
  134.       CMstride = VB->ColorPtr[0]->StrideB;
  135.    }
  136.  
  137.    VB->ColorPtr[0] = &store->LitColor[0];
  138.    VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
  139.    UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  140.  
  141.    if (IDX & LIGHT_TWOSIDE) {
  142.       VB->ColorPtr[1] = &store->LitColor[1];
  143.       VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
  144.       UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
  145.    }
  146.  
  147.    /* Side-effects done, can we finish now?
  148.     */
  149.    if (stage->changed_inputs == 0)
  150.       return;
  151.  
  152.    for ( j=0 ;
  153.      j<nr ;
  154.      j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
  155.    {
  156.       GLfloat sum[2][3], spec[2][3];
  157.       struct gl_light *light;
  158.  
  159.       if ( CHECK_COLOR_MATERIAL(j) )
  160.      _mesa_update_color_material( ctx, CMcolor );
  161.  
  162.       if ( CHECK_MATERIAL(j) )
  163.      _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
  164.  
  165.       if ( CHECK_VALIDATE(j) ) {
  166.      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  167.      UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  168.      if (IDX & LIGHT_TWOSIDE) 
  169.         UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
  170.       }
  171.  
  172.       COPY_3V(sum[0], base[0]);
  173.       ZERO_3V(spec[0]);
  174.  
  175.       if (IDX & LIGHT_TWOSIDE) {
  176.      COPY_3V(sum[1], base[1]);
  177.      ZERO_3V(spec[1]);
  178.       }
  179.  
  180.       /* Add contribution from each enabled light source */
  181.       foreach (light, &ctx->Light.EnabledList) {
  182.      GLfloat n_dot_h;
  183.      GLfloat correction;
  184.      GLint side;
  185.      GLfloat contrib[3];
  186.      GLfloat attenuation;
  187.      GLfloat VP[3];  /* unit vector from vertex to light */
  188.      GLfloat n_dot_VP;       /* n dot VP */
  189.      GLfloat *h;
  190.  
  191.      /* compute VP and attenuation */
  192.      if (!(light->_Flags & LIGHT_POSITIONAL)) {
  193.         /* directional light */
  194.         COPY_3V(VP, light->_VP_inf_norm);
  195.         attenuation = light->_VP_inf_spot_attenuation;
  196.      }
  197.      else {
  198.         GLfloat d;     /* distance from vertex to light */
  199.  
  200.         SUB_3V(VP, light->_Position, vertex);
  201.  
  202.         d = (GLfloat) LEN_3FV( VP );
  203.  
  204.         if (d > 1e-6) {
  205.            GLfloat invd = 1.0F / d;
  206.            SELF_SCALE_SCALAR_3V(VP, invd);
  207.         }
  208.  
  209.         attenuation = 1.0F / (light->ConstantAttenuation + d *
  210.                   (light->LinearAttenuation + d *
  211.                    light->QuadraticAttenuation));
  212.  
  213.         /* spotlight attenuation */
  214.         if (light->_Flags & LIGHT_SPOT) {
  215.            GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
  216.  
  217.            if (PV_dot_dir<light->_CosCutoff) {
  218.           continue; /* this light makes no contribution */
  219.            }
  220.            else {
  221.           GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  222.           GLint k = (GLint) x;
  223.           GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
  224.                     + (x-k)*light->_SpotExpTable[k][1]);
  225.           attenuation *= spot;
  226.            }
  227.         }
  228.      }
  229.  
  230.      if (attenuation < 1e-3)
  231.         continue;        /* this light makes no contribution */
  232.  
  233.      /* Compute dot product or normal and vector from V to light pos */
  234.      n_dot_VP = DOT3( normal, VP );
  235.  
  236.      /* Which side gets the diffuse & specular terms? */
  237.      if (n_dot_VP < 0.0F) {
  238.         ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
  239.         if (!(IDX & LIGHT_TWOSIDE)) {
  240.            continue;
  241.         }
  242.         side = 1;
  243.         correction = -1;
  244.         n_dot_VP = -n_dot_VP;
  245.      }
  246.          else {
  247.         if (IDX & LIGHT_TWOSIDE) {
  248.            ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
  249.         }
  250.         side = 0;
  251.         correction = 1;
  252.      }
  253.  
  254.      /* diffuse term */
  255.      COPY_3V(contrib, light->_MatAmbient[side]);
  256.      ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
  257.      ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
  258.  
  259.      /* specular term - cannibalize VP... */
  260.      if (ctx->Light.Model.LocalViewer) {
  261.         GLfloat v[3];
  262.         COPY_3V(v, vertex);
  263.         NORMALIZE_3FV(v);
  264.         SUB_3V(VP, VP, v);                /* h = VP + VPe */
  265.         h = VP;
  266.         NORMALIZE_3FV(h);
  267.      }
  268.      else if (light->_Flags & LIGHT_POSITIONAL) {
  269.         h = VP;
  270.         ACC_3V(h, ctx->_EyeZDir);
  271.         NORMALIZE_3FV(h);
  272.      }
  273.          else {
  274.         h = light->_h_inf_norm;
  275.      }
  276.  
  277.      n_dot_h = correction * DOT3(normal, h);
  278.  
  279.      if (n_dot_h > 0.0F) {
  280.         GLfloat spec_coef;
  281.         struct gl_shine_tab *tab = ctx->_ShineTable[side];
  282.         GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
  283.  
  284.         if (spec_coef > 1.0e-10) {
  285.            spec_coef *= attenuation;
  286.            ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
  287.                     light->_MatSpecular[side]);
  288.         }
  289.      }
  290.       } /*loop over lights*/
  291.  
  292.       UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
  293.       UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
  294.       Fcolor[j][3] = sumA[0];
  295.  
  296.       if (IDX & LIGHT_TWOSIDE) {
  297.      UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
  298.      UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
  299.      Bcolor[j][3] = sumA[1];
  300.       }
  301.    }
  302. }
  303.  
  304.  
  305. static void TAG(light_rgba)( GLcontext *ctx,
  306.                  struct vertex_buffer *VB,
  307.                  struct gl_pipeline_stage *stage,
  308.                  GLvector4f *input )
  309. {
  310.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  311.    GLuint j;
  312.  
  313.    GLfloat (*base)[3] = ctx->Light._BaseColor;
  314.    GLchan sumA[2];
  315.  
  316.    const GLuint vstride = input->stride;
  317.    const GLfloat *vertex = (GLfloat *) input->data;
  318.    const GLuint nstride = VB->NormalPtr->stride;
  319.    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
  320.  
  321.    GLfloat *CMcolor;
  322.    GLuint CMstride;
  323.  
  324.    GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
  325.    GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
  326.    GLchan (*color[2])[4];
  327.    const GLuint *flags = VB->Flag;
  328.  
  329.    struct gl_material (*new_material)[2] = VB->Material;
  330.    const GLuint *new_material_mask = VB->MaterialMask;
  331.    const GLuint nr = VB->Count;
  332.  
  333. #ifdef TRACE
  334.    fprintf(stderr, "%s\n", __FUNCTION__ );
  335. #endif
  336.  
  337.    (void) flags;
  338.    (void) nstride;
  339.    (void) vstride;
  340.  
  341.    color[0] = Fcolor;
  342.    color[1] = Bcolor;
  343.  
  344.    if (IDX & LIGHT_COLORMATERIAL) {
  345.       if (VB->ColorPtr[0]->Type != GL_FLOAT || 
  346.       VB->ColorPtr[0]->Size != 4)
  347.      import_color_material( ctx, stage );
  348.  
  349.       CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
  350.       CMstride = VB->ColorPtr[0]->StrideB;
  351.    }
  352.  
  353.    VB->ColorPtr[0] = &store->LitColor[0];
  354.    UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  355.  
  356.    if (IDX & LIGHT_TWOSIDE) {
  357.       VB->ColorPtr[1] = &store->LitColor[1];
  358.       UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
  359.    }
  360.  
  361.    if (stage->changed_inputs == 0)
  362.       return;
  363.  
  364.    for ( j=0 ;
  365.      j<nr ;
  366.      j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
  367.    {
  368.       GLfloat sum[2][3];
  369.       struct gl_light *light;
  370.  
  371.       if ( CHECK_COLOR_MATERIAL(j) )
  372.      _mesa_update_color_material( ctx, CMcolor );
  373.  
  374.       if ( CHECK_MATERIAL(j) )
  375.      _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
  376.  
  377.       if ( CHECK_VALIDATE(j) ) {
  378.      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  379.      UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  380.      if (IDX & LIGHT_TWOSIDE)
  381.         UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
  382.       }
  383.  
  384.       COPY_3V(sum[0], base[0]);
  385.  
  386.       if ( IDX & LIGHT_TWOSIDE )
  387.      COPY_3V(sum[1], base[1]);
  388.  
  389.       /* Add contribution from each enabled light source */
  390.       foreach (light, &ctx->Light.EnabledList) {
  391.  
  392.      GLfloat n_dot_h;
  393.      GLfloat correction;
  394.      GLint side;
  395.      GLfloat contrib[3];
  396.      GLfloat attenuation = 1.0;
  397.      GLfloat VP[3];          /* unit vector from vertex to light */
  398.      GLfloat n_dot_VP;       /* n dot VP */
  399.      GLfloat *h;
  400.  
  401.      /* compute VP and attenuation */
  402.      if (!(light->_Flags & LIGHT_POSITIONAL)) {
  403.         /* directional light */
  404.         COPY_3V(VP, light->_VP_inf_norm);
  405.         attenuation = light->_VP_inf_spot_attenuation;
  406.      }
  407.      else {
  408.         GLfloat d;     /* distance from vertex to light */
  409.  
  410.  
  411.         SUB_3V(VP, light->_Position, vertex);
  412.  
  413.         d = (GLfloat) LEN_3FV( VP );
  414.  
  415.         if ( d > 1e-6) {
  416.            GLfloat invd = 1.0F / d;
  417.            SELF_SCALE_SCALAR_3V(VP, invd);
  418.         }
  419.  
  420.             attenuation = 1.0F / (light->ConstantAttenuation + d *
  421.                                   (light->LinearAttenuation + d *
  422.                                    light->QuadraticAttenuation));
  423.  
  424.         /* spotlight attenuation */
  425.         if (light->_Flags & LIGHT_SPOT) {
  426.            GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
  427.  
  428.            if (PV_dot_dir<light->_CosCutoff) {
  429.           continue; /* this light makes no contribution */
  430.            }
  431.            else {
  432.           GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  433.           GLint k = (GLint) x;
  434.           GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
  435.                   + (x-k)*light->_SpotExpTable[k][1]);
  436.           attenuation *= spot;
  437.            }
  438.         }
  439.      }
  440.  
  441.      if (attenuation < 1e-3)
  442.         continue;        /* this light makes no contribution */
  443.  
  444.      /* Compute dot product or normal and vector from V to light pos */
  445.      n_dot_VP = DOT3( normal, VP );
  446.  
  447.      /* which side are we lighting? */
  448.      if (n_dot_VP < 0.0F) {
  449.         ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
  450.  
  451.         if (!(IDX & LIGHT_TWOSIDE))
  452.            continue;
  453.  
  454.         side = 1;
  455.         correction = -1;
  456.         n_dot_VP = -n_dot_VP;
  457.      }
  458.          else {
  459.         if (IDX & LIGHT_TWOSIDE) {
  460.            ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
  461.         }
  462.         side = 0;
  463.         correction = 1;
  464.      }
  465.  
  466.      COPY_3V(contrib, light->_MatAmbient[side]);
  467.  
  468.      /* diffuse term */
  469.      ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
  470.  
  471.      /* specular term - cannibalize VP... */
  472.      {
  473.         if (ctx->Light.Model.LocalViewer) {
  474.            GLfloat v[3];
  475.            COPY_3V(v, vertex);
  476.            NORMALIZE_3FV(v);
  477.            SUB_3V(VP, VP, v);                /* h = VP + VPe */
  478.            h = VP;
  479.            NORMALIZE_3FV(h);
  480.         }
  481.         else if (light->_Flags & LIGHT_POSITIONAL) {
  482.            h = VP;
  483.            ACC_3V(h, ctx->_EyeZDir);
  484.            NORMALIZE_3FV(h);
  485.         }
  486.             else {
  487.            h = light->_h_inf_norm;
  488.         }
  489.  
  490.         n_dot_h = correction * DOT3(normal, h);
  491.  
  492.         if (n_dot_h > 0.0F)
  493.         {
  494.            GLfloat spec_coef;
  495.            struct gl_shine_tab *tab = ctx->_ShineTable[side];
  496.  
  497.            GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
  498.  
  499.            ACC_SCALE_SCALAR_3V( contrib, spec_coef,
  500.                     light->_MatSpecular[side]);
  501.         }
  502.      }
  503.  
  504.      ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
  505.       }
  506.  
  507.       UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
  508.       Fcolor[j][3] = sumA[0];
  509.  
  510.       if (IDX & LIGHT_TWOSIDE) {
  511.      UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
  512.      Bcolor[j][3] = sumA[1];
  513.       }
  514.    }
  515. }
  516.  
  517.  
  518.  
  519.  
  520. /* As below, but with just a single light.
  521.  */
  522. static void TAG(light_fast_rgba_single)( GLcontext *ctx,
  523.                      struct vertex_buffer *VB,
  524.                      struct gl_pipeline_stage *stage,
  525.                      GLvector4f *input )
  526.  
  527. {
  528.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  529.    const GLuint nstride = VB->NormalPtr->stride;
  530.    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
  531.    GLfloat *CMcolor;
  532.    GLuint CMstride;
  533.    GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
  534.    GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
  535.    const struct gl_light *light = ctx->Light.EnabledList.next;
  536.    const GLuint *flags = VB->Flag;
  537.    GLchan basechan[2][4];
  538.    GLuint j = 0;
  539.    struct gl_material (*new_material)[2] = VB->Material;
  540.    const GLuint *new_material_mask = VB->MaterialMask;
  541.    GLfloat base[2][3];
  542.    const GLuint nr = VB->Count;
  543.  
  544. #ifdef TRACE
  545.    fprintf(stderr, "%s\n", __FUNCTION__ );
  546. #endif
  547.  
  548.    (void) input;        /* doesn't refer to Eye or Obj */
  549.    (void) flags;
  550.    (void) nr;
  551.    (void) nstride;
  552.  
  553.    if (IDX & LIGHT_COLORMATERIAL) {
  554.       if (VB->ColorPtr[0]->Type != GL_FLOAT || 
  555.       VB->ColorPtr[0]->Size != 4)
  556.      import_color_material( ctx, stage );
  557.  
  558.       CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
  559.       CMstride = VB->ColorPtr[0]->StrideB;
  560.    }
  561.  
  562.    VB->ColorPtr[0] = &store->LitColor[0];
  563.    if (IDX & LIGHT_TWOSIDE)
  564.       VB->ColorPtr[1] = &store->LitColor[1];
  565.  
  566.    if (stage->changed_inputs == 0)
  567.       return;
  568.  
  569.    do {
  570.       
  571.       if ( CHECK_COLOR_MATERIAL(j) ) {
  572.      _mesa_update_color_material( ctx, CMcolor );
  573.       }
  574.  
  575.       if ( CHECK_MATERIAL(j) )
  576.      _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
  577.  
  578.       if ( CHECK_VALIDATE(j) )
  579.      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  580.  
  581.  
  582.       /* No attenuation, so incoporate _MatAmbient into base color.
  583.        */
  584.       COPY_3V(base[0], light->_MatAmbient[0]);
  585.       ACC_3V(base[0], ctx->Light._BaseColor[0] );
  586.       UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
  587.       UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3], 
  588.                   ctx->Light.Material[0].Diffuse[3]);
  589.  
  590.       if (IDX & LIGHT_TWOSIDE) {
  591.      COPY_3V(base[1], light->_MatAmbient[1]);
  592.      ACC_3V(base[1], ctx->Light._BaseColor[1]);
  593.      UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
  594.      UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3], 
  595.                  ctx->Light.Material[1].Diffuse[3]);
  596.       }
  597.  
  598.       do {
  599.      GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
  600.  
  601.      if (n_dot_VP < 0.0F) {
  602.         if (IDX & LIGHT_TWOSIDE) {
  603.            GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
  604.            GLfloat sum[3];
  605.            COPY_3V(sum, base[1]);
  606.            ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
  607.            if (n_dot_h > 0.0F) {
  608.           GLfloat spec;
  609.           GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
  610.           ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
  611.            }
  612.            UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
  613.            Bcolor[j][3] = basechan[1][3];
  614.         }
  615.         COPY_CHAN4(Fcolor[j], basechan[0]);
  616.      }
  617.          else {
  618.         GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
  619.         GLfloat sum[3];
  620.         COPY_3V(sum, base[0]);
  621.         ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
  622.         if (n_dot_h > 0.0F) {
  623.            GLfloat spec;
  624.            GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
  625.            ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
  626.  
  627.         }
  628.         UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
  629.         Fcolor[j][3] = basechan[0][3];
  630.         if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
  631.      }
  632.  
  633.      j++;
  634.      CMSTRIDE;
  635.      STRIDE_F(normal, NSTRIDE);
  636.       } while (DO_ANOTHER_NORMAL(j));
  637.  
  638.  
  639.       for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
  640.       {
  641.      COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
  642.      if (IDX & LIGHT_TWOSIDE)
  643.         COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
  644.       }
  645.  
  646.    } while (!CHECK_END_VB(j));
  647. }
  648.  
  649.  
  650. /* Light infinite lights
  651.  */
  652. static void TAG(light_fast_rgba)( GLcontext *ctx,
  653.                   struct vertex_buffer *VB,
  654.                   struct gl_pipeline_stage *stage,
  655.                   GLvector4f *input )
  656. {
  657.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  658.    GLchan sumA[2];
  659.    const GLuint nstride = VB->NormalPtr->stride;
  660.    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
  661.    GLfloat *CMcolor;
  662.    GLuint CMstride;
  663.    GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
  664.    GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
  665.    const GLuint *flags = VB->Flag;
  666.    GLuint j = 0;
  667.    struct gl_material (*new_material)[2] = VB->Material;
  668.    GLuint *new_material_mask = VB->MaterialMask;
  669.    const GLuint nr = VB->Count;
  670.    const struct gl_light *light;
  671.  
  672. #ifdef TRACE
  673.    fprintf(stderr, "%s\n", __FUNCTION__ );
  674. #endif
  675.  
  676.    (void) flags;
  677.    (void) input;
  678.    (void) nr;
  679.    (void) nstride;
  680.  
  681.    UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  682.    UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
  683.  
  684.    if (IDX & LIGHT_COLORMATERIAL) {
  685.       if (VB->ColorPtr[0]->Type != GL_FLOAT || 
  686.       VB->ColorPtr[0]->Size != 4)
  687.      import_color_material( ctx, stage );
  688.  
  689.       CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
  690.       CMstride = VB->ColorPtr[0]->StrideB;
  691.    }
  692.  
  693.    VB->ColorPtr[0] = &store->LitColor[0];
  694.    if (IDX & LIGHT_TWOSIDE)
  695.       VB->ColorPtr[1] = &store->LitColor[1];
  696.  
  697.    if (stage->changed_inputs == 0)
  698.       return;
  699.  
  700.    do {
  701.       do {
  702.      GLfloat sum[2][3];
  703.  
  704.      if ( CHECK_COLOR_MATERIAL(j) )
  705.         _mesa_update_color_material( ctx, CMcolor );
  706.  
  707.      if ( CHECK_MATERIAL(j) )
  708.         _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
  709.  
  710.      if ( CHECK_VALIDATE(j) ) {
  711.         TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  712.         UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
  713.         if (IDX & LIGHT_TWOSIDE)
  714.            UNCLAMPED_FLOAT_TO_CHAN(sumA[1], 
  715.                        ctx->Light.Material[1].Diffuse[3]);
  716.      }
  717.  
  718.  
  719.      COPY_3V(sum[0], ctx->Light._BaseColor[0]);
  720.      if (IDX & LIGHT_TWOSIDE)
  721.         COPY_3V(sum[1], ctx->Light._BaseColor[1]);
  722.  
  723.      foreach (light, &ctx->Light.EnabledList) {
  724.         GLfloat n_dot_h, n_dot_VP, spec;
  725.  
  726.         ACC_3V(sum[0], light->_MatAmbient[0]);
  727.         if (IDX & LIGHT_TWOSIDE)
  728.            ACC_3V(sum[1], light->_MatAmbient[1]);
  729.  
  730.         n_dot_VP = DOT3(normal, light->_VP_inf_norm);
  731.  
  732.         if (n_dot_VP > 0.0F) {
  733.            ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
  734.            n_dot_h = DOT3(normal, light->_h_inf_norm);
  735.            if (n_dot_h > 0.0F) {
  736.           struct gl_shine_tab *tab = ctx->_ShineTable[0];
  737.           GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
  738.           ACC_SCALE_SCALAR_3V( sum[0], spec,
  739.                        light->_MatSpecular[0]);
  740.            }
  741.         }
  742.         else if (IDX & LIGHT_TWOSIDE) {
  743.            ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
  744.            n_dot_h = -DOT3(normal, light->_h_inf_norm);
  745.            if (n_dot_h > 0.0F) {
  746.           struct gl_shine_tab *tab = ctx->_ShineTable[1];
  747.           GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
  748.           ACC_SCALE_SCALAR_3V( sum[1], spec,
  749.                        light->_MatSpecular[1]);
  750.            }
  751.         }
  752.      }
  753.  
  754.      UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
  755.      Fcolor[j][3] = sumA[0];
  756.  
  757.      if (IDX & LIGHT_TWOSIDE) {
  758.         UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
  759.         Bcolor[j][3] = sumA[1];
  760.      }
  761.  
  762.      j++;
  763.      CMSTRIDE;
  764.      STRIDE_F(normal, NSTRIDE);
  765.       } while (DO_ANOTHER_NORMAL(j));
  766.  
  767.       /* Reuse the shading results while there is no change to
  768.        * normal or material values.
  769.        */
  770.       for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
  771.       {
  772.      COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
  773.      if (IDX & LIGHT_TWOSIDE)
  774.         COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
  775.       }
  776.  
  777.    } while (!CHECK_END_VB(j));
  778. }
  779.  
  780.  
  781.  
  782.  
  783.  
  784. /*
  785.  * Use current lighting/material settings to compute the color indexes
  786.  * for an array of vertices.
  787.  * Input:  n - number of vertices to light
  788.  *         side - 0=use front material, 1=use back material
  789.  *         vertex - array of [n] vertex position in eye coordinates
  790.  *         normal - array of [n] surface normal vector
  791.  * Output:  indexResult - resulting array of [n] color indexes
  792.  */
  793. static void TAG(light_ci)( GLcontext *ctx,
  794.                struct vertex_buffer *VB,
  795.                struct gl_pipeline_stage *stage,
  796.                GLvector4f *input )
  797. {
  798.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  799.    GLuint j;
  800.    const GLuint vstride = input->stride;
  801.    const GLfloat *vertex = (GLfloat *) input->data;
  802.    const GLuint nstride = VB->NormalPtr->stride;
  803.    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
  804.    GLfloat *CMcolor;
  805.    GLuint CMstride;
  806.    const GLuint *flags = VB->Flag;
  807.    GLuint *indexResult[2];
  808.    struct gl_material (*new_material)[2] = VB->Material;
  809.    GLuint *new_material_mask = VB->MaterialMask;
  810.    const GLuint nr = VB->Count;
  811.  
  812. #ifdef TRACE
  813.    fprintf(stderr, "%s\n", __FUNCTION__ );
  814. #endif
  815.  
  816.    (void) flags;
  817.    (void) nstride;
  818.    (void) vstride;
  819.  
  820.    VB->IndexPtr[0] = &store->LitIndex[0];
  821.    if (IDX & LIGHT_TWOSIDE)
  822.       VB->IndexPtr[1] = &store->LitIndex[1];
  823.  
  824.    if (stage->changed_inputs == 0)
  825.       return;
  826.  
  827.    indexResult[0] = VB->IndexPtr[0]->data;
  828.    if (IDX & LIGHT_TWOSIDE)
  829.       indexResult[1] = VB->IndexPtr[1]->data;
  830.  
  831.    if (IDX & LIGHT_COLORMATERIAL) {
  832.       if (VB->ColorPtr[0]->Type != GL_FLOAT || 
  833.       VB->ColorPtr[0]->Size != 4)
  834.      import_color_material( ctx, stage );
  835.  
  836.       CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
  837.       CMstride = VB->ColorPtr[0]->StrideB;
  838.    }
  839.  
  840.    /* loop over vertices */
  841.    for ( j=0 ;
  842.      j<nr ;
  843.      j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
  844.    {
  845.       GLfloat diffuse[2], specular[2];
  846.       GLuint side = 0;
  847.       struct gl_light *light;
  848.  
  849.       if ( CHECK_COLOR_MATERIAL(j) )
  850.      _mesa_update_color_material( ctx, CMcolor );
  851.  
  852.       if ( CHECK_MATERIAL(j) )
  853.      _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
  854.  
  855.       if ( CHECK_VALIDATE(j) )
  856.      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  857.  
  858.       diffuse[0] = specular[0] = 0.0F;
  859.  
  860.       if ( IDX & LIGHT_TWOSIDE ) {
  861.      diffuse[1] = specular[1] = 0.0F;
  862.       }
  863.  
  864.       /* Accumulate diffuse and specular from each light source */
  865.       foreach (light, &ctx->Light.EnabledList) {
  866.  
  867.      GLfloat attenuation = 1.0F;
  868.      GLfloat VP[3];  /* unit vector from vertex to light */
  869.      GLfloat n_dot_VP;  /* dot product of l and n */
  870.      GLfloat *h, n_dot_h, correction = 1.0;
  871.  
  872.      /* compute l and attenuation */
  873.      if (!(light->_Flags & LIGHT_POSITIONAL)) {
  874.         /* directional light */
  875.         COPY_3V(VP, light->_VP_inf_norm);
  876.      }
  877.      else {
  878.         GLfloat d;     /* distance from vertex to light */
  879.  
  880.         SUB_3V(VP, light->_Position, vertex);
  881.  
  882.         d = (GLfloat) LEN_3FV( VP );
  883.         if ( d > 1e-6) {
  884.            GLfloat invd = 1.0F / d;
  885.            SELF_SCALE_SCALAR_3V(VP, invd);
  886.         }
  887.  
  888.         attenuation = 1.0F / (light->ConstantAttenuation + d *
  889.                   (light->LinearAttenuation + d *
  890.                    light->QuadraticAttenuation));
  891.  
  892.         /* spotlight attenuation */
  893.         if (light->_Flags & LIGHT_SPOT) {
  894.            GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
  895.            if (PV_dot_dir < light->_CosCutoff) {
  896.           continue; /* this light makes no contribution */
  897.            }
  898.            else {
  899.           GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  900.           GLint k = (GLint) x;
  901.           GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
  902.                   + (x-k)*light->_SpotExpTable[k][1]);
  903.           attenuation *= spot;
  904.            }
  905.         }
  906.      }
  907.  
  908.      if (attenuation < 1e-3)
  909.         continue;        /* this light makes no contribution */
  910.  
  911.      n_dot_VP = DOT3( normal, VP );
  912.  
  913.      /* which side are we lighting? */
  914.      if (n_dot_VP < 0.0F) {
  915.         if (!(IDX & LIGHT_TWOSIDE))
  916.            continue;
  917.         side = 1;
  918.         correction = -1;
  919.         n_dot_VP = -n_dot_VP;
  920.      }
  921.  
  922.      /* accumulate diffuse term */
  923.      diffuse[side] += n_dot_VP * light->_dli * attenuation;
  924.  
  925.      /* specular term */
  926.      if (ctx->Light.Model.LocalViewer) {
  927.         GLfloat v[3];
  928.         COPY_3V(v, vertex);
  929.         NORMALIZE_3FV(v);
  930.         SUB_3V(VP, VP, v);                /* h = VP + VPe */
  931.         h = VP;
  932.         NORMALIZE_3FV(h);
  933.      }
  934.      else if (light->_Flags & LIGHT_POSITIONAL) {
  935.         h = VP;
  936.             /* Strangely, disabling this addition fixes a conformance
  937.              * problem.  If this code is enabled, l_sed.c fails.
  938.              */
  939.         /*ACC_3V(h, ctx->_EyeZDir);*/
  940.         NORMALIZE_3FV(h);
  941.      }
  942.          else {
  943.         h = light->_h_inf_norm;
  944.      }
  945.  
  946.      n_dot_h = correction * DOT3(normal, h);
  947.      if (n_dot_h > 0.0F) {
  948.         GLfloat spec_coef;
  949.         struct gl_shine_tab *tab = ctx->_ShineTable[side];
  950.         GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
  951.         specular[side] += spec_coef * light->_sli * attenuation;
  952.      }
  953.       } /*loop over lights*/
  954.  
  955.       /* Now compute final color index */
  956.       for (side = 0 ; side < NR_SIDES ; side++) {
  957.      struct gl_material *mat = &ctx->Light.Material[side];
  958.      GLfloat index;
  959.  
  960.      if (specular[side] > 1.0F) {
  961.         index = mat->SpecularIndex;
  962.      }
  963.      else {
  964.         GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
  965.         GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
  966.  
  967.         index = mat->AmbientIndex
  968.            + diffuse[side] * (1.0F-specular[side]) * d_a
  969.            + specular[side] * s_a;
  970.  
  971.         if (index > mat->SpecularIndex) {
  972.            index = mat->SpecularIndex;
  973.         }
  974.      }
  975.      indexResult[side][j] = (GLuint) (GLint) index;
  976.       }
  977.    } /*for vertex*/
  978. }
  979.  
  980.  
  981.  
  982. static void TAG(init_light_tab)( void )
  983. {
  984.    _tnl_light_tab[IDX] = TAG(light_rgba);
  985.    _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
  986.    _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
  987.    _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
  988.    _tnl_light_ci_tab[IDX] = TAG(light_ci);
  989. }
  990.  
  991.  
  992. #undef TAG
  993. #undef IDX
  994. #undef NR_SIDES
  995. #undef NSTRIDE
  996. #undef VSTRIDE
  997. #undef CHECK_MATERIAL
  998. #undef CHECK_END_VB
  999. #undef DO_ANOTHER_NORMAL
  1000. #undef REUSE_LIGHT_RESULTS
  1001. #undef CMSTRIDE
  1002. #undef CHECK_COLOR_MATERIAL
  1003. #undef CHECK_VALIDATE
  1004.