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