Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  *
  25.  * Authors:
  26.  *    Brian Paul Keith Whitwell <keith@tungstengraphics.com>
  27.  */
  28.  
  29.  
  30. #if IDX & LIGHT_TWOSIDE
  31. #  define NR_SIDES 2
  32. #else
  33. #  define NR_SIDES 1
  34. #endif
  35.  
  36.  
  37. /* define TRACE to trace lighting code */
  38. /* #define TRACE 1 */
  39.  
  40. /*
  41.  * ctx is the current context
  42.  * VB is the vertex buffer
  43.  * stage is the lighting stage-private data
  44.  * input is the vector of eye or object-space vertex coordinates
  45.  */
  46. static void TAG(light_rgba_spec)( struct gl_context *ctx,
  47.                                   struct vertex_buffer *VB,
  48.                                   struct tnl_pipeline_stage *stage,
  49.                                   GLvector4f *input )
  50. {
  51.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  52.    GLfloat (*base)[3] = ctx->Light._BaseColor;
  53.    GLfloat sumA[2];
  54.    GLuint j;
  55.  
  56.    const GLuint vstride = input->stride;
  57.    const GLfloat *vertex = (GLfloat *)input->data;
  58.    const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
  59.    const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
  60.  
  61.    GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
  62.    GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data;
  63. #if IDX & LIGHT_TWOSIDE
  64.    GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
  65.    GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data;
  66. #endif
  67.  
  68.    const GLuint nr = VB->Count;
  69.  
  70. #ifdef TRACE
  71.    fprintf(stderr, "%s\n", __FUNCTION__ );
  72. #endif
  73.  
  74.    VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
  75.    VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &store->LitSecondary[0];
  76.    sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  77.  
  78. #if IDX & LIGHT_TWOSIDE
  79.    VB->BackfaceColorPtr = &store->LitColor[1];
  80.    VB->BackfaceSecondaryColorPtr = &store->LitSecondary[1];
  81.    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  82. #endif
  83.  
  84.  
  85.    store->LitColor[0].stride = 16;
  86.    store->LitColor[1].stride = 16;
  87.  
  88.    for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
  89.       GLfloat sum[2][3], spec[2][3];
  90.       struct gl_light *light;
  91.  
  92. #if IDX & LIGHT_MATERIAL
  93.       update_materials( ctx, store );
  94.       sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  95. #if IDX & LIGHT_TWOSIDE
  96.       sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  97. #endif
  98. #endif
  99.  
  100.       COPY_3V(sum[0], base[0]);
  101.       ZERO_3V(spec[0]);
  102.  
  103. #if IDX & LIGHT_TWOSIDE
  104.       COPY_3V(sum[1], base[1]);
  105.       ZERO_3V(spec[1]);
  106. #endif
  107.  
  108.       /* Add contribution from each enabled light source */
  109.       foreach (light, &ctx->Light.EnabledList) {
  110.          GLfloat n_dot_h;
  111.          GLfloat correction;
  112.          GLint side;
  113.          GLfloat contrib[3];
  114.          GLfloat attenuation;
  115.          GLfloat VP[3];  /* unit vector from vertex to light */
  116.          GLfloat n_dot_VP;       /* n dot VP */
  117.          GLfloat *h;
  118.  
  119.          /* compute VP and attenuation */
  120.          if (!(light->_Flags & LIGHT_POSITIONAL)) {
  121.             /* directional light */
  122.             COPY_3V(VP, light->_VP_inf_norm);
  123.             attenuation = light->_VP_inf_spot_attenuation;
  124.          }
  125.          else {
  126.             GLfloat d;     /* distance from vertex to light */
  127.  
  128.             SUB_3V(VP, light->_Position, vertex);
  129.  
  130.             d = (GLfloat) LEN_3FV( VP );
  131.  
  132.             if (d > 1e-6) {
  133.                GLfloat invd = 1.0F / d;
  134.                SELF_SCALE_SCALAR_3V(VP, invd);
  135.             }
  136.  
  137.             attenuation = 1.0F / (light->ConstantAttenuation + d *
  138.                                   (light->LinearAttenuation + d *
  139.                                    light->QuadraticAttenuation));
  140.  
  141.             /* spotlight attenuation */
  142.             if (light->_Flags & LIGHT_SPOT) {
  143.                GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
  144.  
  145.                if (PV_dot_dir<light->_CosCutoff) {
  146.                   continue; /* this light makes no contribution */
  147.                }
  148.                else {
  149.                   GLfloat spot = powf(PV_dot_dir, light->SpotExponent);
  150.                   attenuation *= spot;
  151.                }
  152.             }
  153.          }
  154.  
  155.          if (attenuation < 1e-3)
  156.             continue;           /* this light makes no contribution */
  157.  
  158.          /* Compute dot product or normal and vector from V to light pos */
  159.          n_dot_VP = DOT3( normal, VP );
  160.  
  161.          /* Which side gets the diffuse & specular terms? */
  162.          if (n_dot_VP < 0.0F) {
  163.             ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
  164. #if IDX & LIGHT_TWOSIDE
  165.             side = 1;
  166.             correction = -1;
  167.             n_dot_VP = -n_dot_VP;
  168. #else
  169.             continue;
  170. #endif
  171.          }
  172.          else {
  173. #if IDX & LIGHT_TWOSIDE
  174.             ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
  175. #endif
  176.             side = 0;
  177.             correction = 1;
  178.          }
  179.  
  180.          /* diffuse term */
  181.          COPY_3V(contrib, light->_MatAmbient[side]);
  182.          ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
  183.          ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
  184.  
  185.          /* specular term - cannibalize VP... */
  186.          if (ctx->Light.Model.LocalViewer) {
  187.             GLfloat v[3];
  188.             COPY_3V(v, vertex);
  189.             NORMALIZE_3FV(v);
  190.             SUB_3V(VP, VP, v);                /* h = VP + VPe */
  191.             h = VP;
  192.             NORMALIZE_3FV(h);
  193.          }
  194.          else if (light->_Flags & LIGHT_POSITIONAL) {
  195.             h = VP;
  196.             ACC_3V(h, ctx->_EyeZDir);
  197.             NORMALIZE_3FV(h);
  198.          }
  199.          else {
  200.             h = light->_h_inf_norm;
  201.          }
  202.  
  203.          n_dot_h = correction * DOT3(normal, h);
  204.  
  205.          if (n_dot_h > 0.0F) {
  206.             GLfloat spec_coef = lookup_shininess(ctx, side, n_dot_h);
  207.             if (spec_coef > 1.0e-10) {
  208.                spec_coef *= attenuation;
  209.                ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
  210.                                     light->_MatSpecular[side]);
  211.             }
  212.          }
  213.       } /*loop over lights*/
  214.  
  215.       COPY_3V( Fcolor[j], sum[0] );
  216.       COPY_3V( Fspec[j], spec[0] );
  217.       Fcolor[j][3] = sumA[0];
  218.  
  219. #if IDX & LIGHT_TWOSIDE
  220.       COPY_3V( Bcolor[j], sum[1] );
  221.       COPY_3V( Bspec[j], spec[1] );
  222.       Bcolor[j][3] = sumA[1];
  223. #endif
  224.    }
  225. }
  226.  
  227.  
  228. static void TAG(light_rgba)( struct gl_context *ctx,
  229.                              struct vertex_buffer *VB,
  230.                              struct tnl_pipeline_stage *stage,
  231.                              GLvector4f *input )
  232. {
  233.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  234.    GLuint j;
  235.  
  236.    GLfloat (*base)[3] = ctx->Light._BaseColor;
  237.    GLfloat sumA[2];
  238.  
  239.    const GLuint vstride = input->stride;
  240.    const GLfloat *vertex = (GLfloat *) input->data;
  241.    const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
  242.    const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
  243.  
  244.    GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
  245. #if IDX & LIGHT_TWOSIDE
  246.    GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
  247. #endif
  248.  
  249.    const GLuint nr = VB->Count;
  250.  
  251. #ifdef TRACE
  252.    fprintf(stderr, "%s\n", __FUNCTION__ );
  253. #endif
  254.  
  255.    VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
  256.    sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  257.  
  258. #if IDX & LIGHT_TWOSIDE
  259.    VB->BackfaceColorPtr = &store->LitColor[1];
  260.    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  261. #endif
  262.  
  263.    store->LitColor[0].stride = 16;
  264.    store->LitColor[1].stride = 16;
  265.  
  266.    for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
  267.       GLfloat sum[2][3];
  268.       struct gl_light *light;
  269.  
  270. #if IDX & LIGHT_MATERIAL
  271.       update_materials( ctx, store );
  272.       sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  273. #if IDX & LIGHT_TWOSIDE
  274.       sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  275. #endif
  276. #endif
  277.  
  278.       COPY_3V(sum[0], base[0]);
  279.  
  280. #if IDX & LIGHT_TWOSIDE
  281.       COPY_3V(sum[1], base[1]);
  282. #endif
  283.  
  284.       /* Add contribution from each enabled light source */
  285.       foreach (light, &ctx->Light.EnabledList) {
  286.  
  287.          GLfloat n_dot_h;
  288.          GLfloat correction;
  289.          GLint side;
  290.          GLfloat contrib[3];
  291.          GLfloat attenuation = 1.0;
  292.          GLfloat VP[3];          /* unit vector from vertex to light */
  293.          GLfloat n_dot_VP;       /* n dot VP */
  294.          GLfloat *h;
  295.  
  296.          /* compute VP and attenuation */
  297.          if (!(light->_Flags & LIGHT_POSITIONAL)) {
  298.             /* directional light */
  299.             COPY_3V(VP, light->_VP_inf_norm);
  300.             attenuation = light->_VP_inf_spot_attenuation;
  301.          }
  302.          else {
  303.             GLfloat d;     /* distance from vertex to light */
  304.  
  305.  
  306.             SUB_3V(VP, light->_Position, vertex);
  307.  
  308.             d = (GLfloat) LEN_3FV( VP );
  309.  
  310.             if ( d > 1e-6) {
  311.                GLfloat invd = 1.0F / d;
  312.                SELF_SCALE_SCALAR_3V(VP, invd);
  313.             }
  314.  
  315.             attenuation = 1.0F / (light->ConstantAttenuation + d *
  316.                                   (light->LinearAttenuation + d *
  317.                                    light->QuadraticAttenuation));
  318.  
  319.             /* spotlight attenuation */
  320.             if (light->_Flags & LIGHT_SPOT) {
  321.                GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
  322.  
  323.                if (PV_dot_dir<light->_CosCutoff) {
  324.                   continue; /* this light makes no contribution */
  325.                }
  326.                else {
  327.                   GLfloat spot = powf(PV_dot_dir, light->SpotExponent);
  328.                   attenuation *= spot;
  329.                }
  330.             }
  331.          }
  332.  
  333.          if (attenuation < 1e-3)
  334.             continue;           /* this light makes no contribution */
  335.  
  336.          /* Compute dot product or normal and vector from V to light pos */
  337.          n_dot_VP = DOT3( normal, VP );
  338.  
  339.          /* which side are we lighting? */
  340.          if (n_dot_VP < 0.0F) {
  341.             ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
  342. #if IDX & LIGHT_TWOSIDE
  343.             side = 1;
  344.             correction = -1;
  345.             n_dot_VP = -n_dot_VP;
  346. #else
  347.             continue;
  348. #endif
  349.          }
  350.          else {
  351. #if IDX & LIGHT_TWOSIDE
  352.             ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
  353. #endif
  354.             side = 0;
  355.             correction = 1;
  356.          }
  357.  
  358.          COPY_3V(contrib, light->_MatAmbient[side]);
  359.  
  360.          /* diffuse term */
  361.          ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
  362.  
  363.          /* specular term - cannibalize VP... */
  364.          {
  365.             if (ctx->Light.Model.LocalViewer) {
  366.                GLfloat v[3];
  367.                COPY_3V(v, vertex);
  368.                NORMALIZE_3FV(v);
  369.                SUB_3V(VP, VP, v);                /* h = VP + VPe */
  370.                h = VP;
  371.                NORMALIZE_3FV(h);
  372.             }
  373.             else if (light->_Flags & LIGHT_POSITIONAL) {
  374.                h = VP;
  375.                ACC_3V(h, ctx->_EyeZDir);
  376.                NORMALIZE_3FV(h);
  377.             }
  378.             else {
  379.                h = light->_h_inf_norm;
  380.             }
  381.  
  382.             n_dot_h = correction * DOT3(normal, h);
  383.  
  384.             if (n_dot_h > 0.0F) {
  385.                GLfloat spec_coef = lookup_shininess(ctx, side, n_dot_h);
  386.                ACC_SCALE_SCALAR_3V( contrib, spec_coef,
  387.                                     light->_MatSpecular[side]);
  388.             }
  389.          }
  390.  
  391.          ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
  392.       }
  393.  
  394.       COPY_3V( Fcolor[j], sum[0] );
  395.       Fcolor[j][3] = sumA[0];
  396.  
  397. #if IDX & LIGHT_TWOSIDE
  398.       COPY_3V( Bcolor[j], sum[1] );
  399.       Bcolor[j][3] = sumA[1];
  400. #endif
  401.    }
  402. }
  403.  
  404.  
  405.  
  406.  
  407. /* As below, but with just a single light.
  408.  */
  409. static void TAG(light_fast_rgba_single)( struct gl_context *ctx,
  410.                                          struct vertex_buffer *VB,
  411.                                          struct tnl_pipeline_stage *stage,
  412.                                          GLvector4f *input )
  413.  
  414. {
  415.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  416.    const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
  417.    const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
  418.    GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
  419. #if IDX & LIGHT_TWOSIDE
  420.    GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
  421. #endif
  422.    const struct gl_light *light = ctx->Light.EnabledList.next;
  423.    GLuint j = 0;
  424.    GLfloat base[2][4];
  425. #if IDX & LIGHT_MATERIAL
  426.    const GLuint nr = VB->Count;
  427. #else
  428.    const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
  429. #endif
  430.  
  431. #ifdef TRACE
  432.    fprintf(stderr, "%s\n", __FUNCTION__ );
  433. #endif
  434.  
  435.    (void) input;                /* doesn't refer to Eye or Obj */
  436.  
  437.    VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
  438. #if IDX & LIGHT_TWOSIDE
  439.    VB->BackfaceColorPtr = &store->LitColor[1];
  440. #endif
  441.  
  442.    if (nr > 1) {
  443.       store->LitColor[0].stride = 16;
  444.       store->LitColor[1].stride = 16;
  445.    }
  446.    else {
  447.       store->LitColor[0].stride = 0;
  448.       store->LitColor[1].stride = 0;
  449.    }
  450.  
  451.    for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
  452.  
  453.       GLfloat n_dot_VP;
  454.  
  455. #if IDX & LIGHT_MATERIAL
  456.       update_materials( ctx, store );
  457. #endif
  458.  
  459.       /* No attenuation, so incoporate _MatAmbient into base color.
  460.        */
  461. #if !(IDX & LIGHT_MATERIAL)
  462.       if ( j == 0 )
  463. #endif
  464.       {
  465.          COPY_3V(base[0], light->_MatAmbient[0]);
  466.          ACC_3V(base[0], ctx->Light._BaseColor[0] );
  467.          base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  468.  
  469. #if IDX & LIGHT_TWOSIDE
  470.          COPY_3V(base[1], light->_MatAmbient[1]);
  471.          ACC_3V(base[1], ctx->Light._BaseColor[1]);
  472.          base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  473. #endif
  474.       }
  475.  
  476.       n_dot_VP = DOT3(normal, light->_VP_inf_norm);
  477.  
  478.       if (n_dot_VP < 0.0F) {
  479. #if IDX & LIGHT_TWOSIDE
  480.          GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
  481.          GLfloat sum[3];
  482.          COPY_3V(sum, base[1]);
  483.          ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
  484.          if (n_dot_h > 0.0F) {
  485.             GLfloat spec = lookup_shininess(ctx, 1, n_dot_h);
  486.             ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
  487.          }
  488.          COPY_3V(Bcolor[j], sum );
  489.          Bcolor[j][3] = base[1][3];
  490. #endif
  491.          COPY_4FV(Fcolor[j], base[0]);
  492.       }
  493.       else {
  494.          GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
  495.          GLfloat sum[3];
  496.          COPY_3V(sum, base[0]);
  497.          ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
  498.          if (n_dot_h > 0.0F) {
  499.             GLfloat spec = lookup_shininess(ctx, 0, n_dot_h);
  500.             ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
  501.          }
  502.          COPY_3V(Fcolor[j], sum );
  503.          Fcolor[j][3] = base[0][3];
  504. #if IDX & LIGHT_TWOSIDE
  505.          COPY_4FV(Bcolor[j], base[1]);
  506. #endif
  507.       }
  508.    }
  509. }
  510.  
  511.  
  512. /* Light infinite lights
  513.  */
  514. static void TAG(light_fast_rgba)( struct gl_context *ctx,
  515.                                   struct vertex_buffer *VB,
  516.                                   struct tnl_pipeline_stage *stage,
  517.                                   GLvector4f *input )
  518. {
  519.    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
  520.    GLfloat sumA[2];
  521.    const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
  522.    const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
  523.    GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
  524. #if IDX & LIGHT_TWOSIDE
  525.    GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
  526. #endif
  527.    GLuint j = 0;
  528. #if IDX & LIGHT_MATERIAL
  529.    const GLuint nr = VB->Count;
  530. #else
  531.    const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
  532. #endif
  533.    const struct gl_light *light;
  534.  
  535. #ifdef TRACE
  536.    fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
  537. #endif
  538.  
  539.    (void) input;
  540.  
  541.    sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  542.    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  543.  
  544.    VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
  545. #if IDX & LIGHT_TWOSIDE
  546.    VB->BackfaceColorPtr = &store->LitColor[1];
  547. #endif
  548.  
  549.    if (nr > 1) {
  550.       store->LitColor[0].stride = 16;
  551.       store->LitColor[1].stride = 16;
  552.    }
  553.    else {
  554.       store->LitColor[0].stride = 0;
  555.       store->LitColor[1].stride = 0;
  556.    }
  557.  
  558.    for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
  559.  
  560.       GLfloat sum[2][3];
  561.  
  562. #if IDX & LIGHT_MATERIAL
  563.       update_materials( ctx, store );
  564.  
  565.       sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
  566. #if IDX & LIGHT_TWOSIDE
  567.       sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
  568. #endif
  569. #endif
  570.  
  571.  
  572.       COPY_3V(sum[0], ctx->Light._BaseColor[0]);
  573. #if IDX & LIGHT_TWOSIDE
  574.       COPY_3V(sum[1], ctx->Light._BaseColor[1]);
  575. #endif
  576.  
  577.       foreach (light, &ctx->Light.EnabledList) {
  578.          GLfloat n_dot_h, n_dot_VP, spec;
  579.  
  580.          ACC_3V(sum[0], light->_MatAmbient[0]);
  581. #if IDX & LIGHT_TWOSIDE
  582.          ACC_3V(sum[1], light->_MatAmbient[1]);
  583. #endif
  584.  
  585.          n_dot_VP = DOT3(normal, light->_VP_inf_norm);
  586.  
  587.          if (n_dot_VP > 0.0F) {
  588.             ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
  589.             n_dot_h = DOT3(normal, light->_h_inf_norm);
  590.             if (n_dot_h > 0.0F) {
  591.                spec = lookup_shininess(ctx, 0, n_dot_h);
  592.                ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]);
  593.             }
  594.          }
  595. #if IDX & LIGHT_TWOSIDE
  596.          else {
  597.             ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
  598.             n_dot_h = -DOT3(normal, light->_h_inf_norm);
  599.             if (n_dot_h > 0.0F) {
  600.                spec = lookup_shininess(ctx, 1, n_dot_h);
  601.                ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]);
  602.             }
  603.          }
  604. #endif
  605.       }
  606.  
  607.       COPY_3V( Fcolor[j], sum[0] );
  608.       Fcolor[j][3] = sumA[0];
  609.  
  610. #if IDX & LIGHT_TWOSIDE
  611.       COPY_3V( Bcolor[j], sum[1] );
  612.       Bcolor[j][3] = sumA[1];
  613. #endif
  614.    }
  615. }
  616.  
  617.  
  618.  
  619.  
  620. static void TAG(init_light_tab)( void )
  621. {
  622.    _tnl_light_tab[IDX] = TAG(light_rgba);
  623.    _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
  624.    _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
  625.    _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
  626. }
  627.  
  628.  
  629. #undef TAG
  630. #undef IDX
  631. #undef NR_SIDES
  632.