Subversion Repositories shark

Rev

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

Rev Author Line No. Line
56 pj 1
/* $Id: t_vb_lighttmp.h,v 1.1 2003-02-28 11:48:07 pj 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