3
* Mesa 3-D graphics library
6
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8
* Permission is hereby granted, free of charge, to any person obtaining a
9
* copy of this software and associated documentation files (the "Software"),
10
* to deal in the Software without restriction, including without limitation
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
* and/or sell copies of the Software, and to permit persons to whom the
13
* Software is furnished to do so, subject to the following conditions:
15
* The above copyright notice and this permission notice shall be included
16
* in all copies or substantial portions of the Software.
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
* Brian Paul <brianp@valinux.com>
28
* Keith Whitwell <keithw@valinux.com>
32
#if (IDX & LIGHT_FLAGS)
33
# define VSTRIDE (4 * sizeof(GLfloat))
34
# define NSTRIDE (3 * sizeof(GLfloat))
35
# define CHECK_MATERIAL(x) (flags[x] & VERT_MATERIAL)
36
# define CHECK_END_VB(x) (flags[x] & VERT_END_VB)
37
# if (IDX & LIGHT_COLORMATERIAL)
38
# define CMSTRIDE STRIDE_F(CMcolor, CMstride)
39
# define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_RGBA)
40
# define CHECK_VALIDATE(x) (flags[x] & (VERT_RGBA|VERT_MATERIAL))
41
# define DO_ANOTHER_NORMAL(x) \
42
((flags[x] & (VERT_RGBA|VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == VERT_NORM)
43
# define REUSE_LIGHT_RESULTS(x) \
44
((flags[x] & (VERT_RGBA|VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == 0)
46
# define CMSTRIDE (void)0
47
# define CHECK_COLOR_MATERIAL(x) 0
48
# define CHECK_VALIDATE(x) (flags[x] & (VERT_MATERIAL))
49
# define DO_ANOTHER_NORMAL(x) \
50
((flags[x] & (VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == VERT_NORM)
51
# define REUSE_LIGHT_RESULTS(x) \
52
((flags[x] & (VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == 0)
55
# define VSTRIDE vstride
56
# define NSTRIDE nstride
57
# define CHECK_MATERIAL(x) 0 /* no materials on array paths */
58
# define CHECK_END_VB(XX) (XX >= nr)
59
# if (IDX & LIGHT_COLORMATERIAL)
60
# define CMSTRIDE STRIDE_F(CMcolor, CMstride)
61
# define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */
62
# define CHECK_VALIDATE(x) (x < nr)
63
# define DO_ANOTHER_NORMAL(x) 0 /* always stop to recalc colormat */
65
# define CMSTRIDE (void)0
66
# define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */
67
# define CHECK_VALIDATE(x) (0)
68
# define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */
70
# define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */
75
#if (IDX & LIGHT_TWOSIDE)
83
static void TAG(light_rgba_spec)( GLcontext *ctx,
84
struct vertex_buffer *VB,
85
struct gl_pipeline_stage *stage,
88
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
89
GLfloat (*base)[3] = ctx->Light._BaseColor;
94
GLuint vstride = input->stride;
95
const GLfloat *vertex = (GLfloat *)input->data;
96
GLuint nstride = VB->NormalPtr->stride;
97
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
102
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
103
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
104
GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
105
GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
106
GLchan (*spec[2])[4];
108
GLuint nr = VB->Count;
109
GLuint *flags = VB->Flag;
110
struct gl_material (*new_material)[2] = VB->Material;
111
GLuint *new_material_mask = VB->MaterialMask;
118
if (MESA_VERBOSE & VERBOSE_LIGHTING)
119
fprintf(stderr, "%s\n", __FUNCTION__ );
124
if (IDX & LIGHT_COLORMATERIAL) {
125
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
126
VB->ColorPtr[0]->Size != 4)
127
import_color_material( ctx, stage );
129
CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
130
CMstride = VB->ColorPtr[0]->StrideB;
133
VB->ColorPtr[0] = &store->LitColor[0];
134
VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
135
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
137
if (IDX & LIGHT_TWOSIDE) {
138
VB->ColorPtr[1] = &store->LitColor[1];
139
VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
140
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
143
/* Side-effects done, can we finish now?
145
if (stage->changed_inputs == 0)
150
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
152
GLfloat sum[2][3], spec[2][3];
153
struct gl_light *light;
155
if ( CHECK_COLOR_MATERIAL(j) )
156
_mesa_update_color_material( ctx, CMcolor );
158
if ( CHECK_MATERIAL(j) )
159
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
161
if ( CHECK_VALIDATE(j) ) {
162
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
163
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
164
if (IDX & LIGHT_TWOSIDE)
165
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
168
COPY_3V(sum[0], base[0]);
171
if (IDX & LIGHT_TWOSIDE) {
172
COPY_3V(sum[1], base[1]);
176
/* Add contribution from each enabled light source */
177
foreach (light, &ctx->Light.EnabledList) {
183
GLfloat VP[3]; /* unit vector from vertex to light */
184
GLfloat n_dot_VP; /* n dot VP */
187
/* compute VP and attenuation */
188
if (!(light->_Flags & LIGHT_POSITIONAL)) {
189
/* directional light */
190
COPY_3V(VP, light->_VP_inf_norm);
191
attenuation = light->_VP_inf_spot_attenuation;
194
GLfloat d; /* distance from vertex to light */
196
SUB_3V(VP, light->_Position, vertex);
198
d = (GLfloat) LEN_3FV( VP );
201
GLfloat invd = 1.0F / d;
202
SELF_SCALE_SCALAR_3V(VP, invd);
205
attenuation = 1.0F / (light->ConstantAttenuation + d *
206
(light->LinearAttenuation + d *
207
light->QuadraticAttenuation));
209
/* spotlight attenuation */
210
if (light->_Flags & LIGHT_SPOT) {
211
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
213
if (PV_dot_dir<light->_CosCutoff) {
214
continue; /* this light makes no contribution */
217
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
219
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
220
+ (x-k)*light->_SpotExpTable[k][1]);
226
if (attenuation < 1e-3)
227
continue; /* this light makes no contribution */
229
/* Compute dot product or normal and vector from V to light pos */
230
n_dot_VP = DOT3( normal, VP );
232
/* Which side gets the diffuse & specular terms? */
233
if (n_dot_VP < 0.0F) {
234
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
235
if (!(IDX & LIGHT_TWOSIDE)) {
240
n_dot_VP = -n_dot_VP;
243
if (IDX & LIGHT_TWOSIDE) {
244
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
251
COPY_3V(contrib, light->_MatAmbient[side]);
252
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
253
ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
255
/* specular term - cannibalize VP... */
256
if (ctx->Light.Model.LocalViewer) {
260
SUB_3V(VP, VP, v); /* h = VP + VPe */
264
else if (light->_Flags & LIGHT_POSITIONAL) {
266
ACC_3V(h, ctx->_EyeZDir);
270
h = light->_h_inf_norm;
273
n_dot_h = correction * DOT3(normal, h);
275
if (n_dot_h > 0.0F) {
277
struct gl_shine_tab *tab = ctx->_ShineTable[side];
278
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
280
if (spec_coef > 1.0e-10) {
281
spec_coef *= attenuation;
282
ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
283
light->_MatSpecular[side]);
286
} /*loop over lights*/
288
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
289
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
290
Fcolor[j][3] = sumA[0];
292
if (IDX & LIGHT_TWOSIDE) {
293
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
294
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
295
Bcolor[j][3] = sumA[1];
301
static void TAG(light_rgba)( GLcontext *ctx,
302
struct vertex_buffer *VB,
303
struct gl_pipeline_stage *stage,
306
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
309
GLfloat (*base)[3] = ctx->Light._BaseColor;
312
GLuint vstride = input->stride;
313
const GLfloat *vertex = (GLfloat *) input->data;
314
GLuint nstride = VB->NormalPtr->stride;
315
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
320
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
321
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
322
GLchan (*color[2])[4];
323
GLuint *flags = VB->Flag;
325
struct gl_material (*new_material)[2] = VB->Material;
326
GLuint *new_material_mask = VB->MaterialMask;
327
GLuint nr = VB->Count;
329
if (MESA_VERBOSE & VERBOSE_LIGHTING)
330
fprintf(stderr, "%s\n", __FUNCTION__ );
339
if (IDX & LIGHT_COLORMATERIAL) {
340
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
341
VB->ColorPtr[0]->Size != 4)
342
import_color_material( ctx, stage );
344
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
345
CMstride = VB->ColorPtr[0]->StrideB;
348
VB->ColorPtr[0] = &store->LitColor[0];
349
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
351
if (IDX & LIGHT_TWOSIDE) {
352
VB->ColorPtr[1] = &store->LitColor[1];
353
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
356
if (stage->changed_inputs == 0)
361
j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
364
struct gl_light *light;
366
if ( CHECK_COLOR_MATERIAL(j) )
367
_mesa_update_color_material( ctx, CMcolor );
369
if ( CHECK_MATERIAL(j) )
370
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
372
if ( CHECK_VALIDATE(j) ) {
373
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
374
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
375
if (IDX & LIGHT_TWOSIDE)
376
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
379
COPY_3V(sum[0], base[0]);
381
if ( IDX & LIGHT_TWOSIDE )
382
COPY_3V(sum[1], base[1]);
384
/* Add contribution from each enabled light source */
385
foreach (light, &ctx->Light.EnabledList) {
391
GLfloat attenuation = 1.0;
392
GLfloat VP[3]; /* unit vector from vertex to light */
393
GLfloat n_dot_VP; /* n dot VP */
396
/* compute VP and attenuation */
397
if (!(light->_Flags & LIGHT_POSITIONAL)) {
398
/* directional light */
399
COPY_3V(VP, light->_VP_inf_norm);
400
attenuation = light->_VP_inf_spot_attenuation;
403
GLfloat d; /* distance from vertex to light */
406
SUB_3V(VP, light->_Position, vertex);
408
d = (GLfloat) LEN_3FV( VP );
411
GLfloat invd = 1.0F / d;
412
SELF_SCALE_SCALAR_3V(VP, invd);
415
attenuation = 1.0F / (light->ConstantAttenuation + d *
416
(light->LinearAttenuation + d *
417
light->QuadraticAttenuation));
419
/* spotlight attenuation */
420
if (light->_Flags & LIGHT_SPOT) {
421
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
423
if (PV_dot_dir<light->_CosCutoff) {
424
continue; /* this light makes no contribution */
427
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
429
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
430
+ (x-k)*light->_SpotExpTable[k][1]);
436
if (attenuation < 1e-3)
437
continue; /* this light makes no contribution */
439
/* Compute dot product or normal and vector from V to light pos */
440
n_dot_VP = DOT3( normal, VP );
442
/* which side are we lighting? */
443
if (n_dot_VP < 0.0F) {
444
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
446
if (!(IDX & LIGHT_TWOSIDE))
451
n_dot_VP = -n_dot_VP;
454
if (IDX & LIGHT_TWOSIDE) {
455
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
461
COPY_3V(contrib, light->_MatAmbient[side]);
464
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
466
/* specular term - cannibalize VP... */
468
if (ctx->Light.Model.LocalViewer) {
472
SUB_3V(VP, VP, v); /* h = VP + VPe */
476
else if (light->_Flags & LIGHT_POSITIONAL) {
478
ACC_3V(h, ctx->_EyeZDir);
482
h = light->_h_inf_norm;
485
n_dot_h = correction * DOT3(normal, h);
490
struct gl_shine_tab *tab = ctx->_ShineTable[side];
492
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
494
ACC_SCALE_SCALAR_3V( contrib, spec_coef,
495
light->_MatSpecular[side]);
499
ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
502
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
503
Fcolor[j][3] = sumA[0];
505
if (IDX & LIGHT_TWOSIDE) {
506
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
507
Bcolor[j][3] = sumA[1];
515
/* As below, but with just a single light.
517
static void TAG(light_fast_rgba_single)( GLcontext *ctx,
518
struct vertex_buffer *VB,
519
struct gl_pipeline_stage *stage,
523
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
524
GLuint nstride = VB->NormalPtr->stride;
525
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
528
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
529
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
530
struct gl_light *light = ctx->Light.EnabledList.next;
531
GLuint *flags = VB->Flag;
532
GLchan basechan[2][4];
534
struct gl_material (*new_material)[2] = VB->Material;
535
GLuint *new_material_mask = VB->MaterialMask;
537
GLuint nr = VB->Count;
539
if (MESA_VERBOSE & VERBOSE_LIGHTING)
540
fprintf(stderr, "%s\n", __FUNCTION__ );
542
(void) input; /* doesn't refer to Eye or Obj */
547
if (IDX & LIGHT_COLORMATERIAL) {
548
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
549
VB->ColorPtr[0]->Size != 4)
550
import_color_material( ctx, stage );
552
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
553
CMstride = VB->ColorPtr[0]->StrideB;
556
VB->ColorPtr[0] = &store->LitColor[0];
557
if (IDX & LIGHT_TWOSIDE)
558
VB->ColorPtr[1] = &store->LitColor[1];
560
if (stage->changed_inputs == 0)
565
if ( CHECK_COLOR_MATERIAL(j) ) {
566
_mesa_update_color_material( ctx, CMcolor );
569
if ( CHECK_MATERIAL(j) )
570
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
572
if ( CHECK_VALIDATE(j) )
573
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
576
/* No attenuation, so incoporate _MatAmbient into base color.
578
COPY_3V(base[0], light->_MatAmbient[0]);
579
ACC_3V(base[0], ctx->Light._BaseColor[0] );
580
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
581
UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3],
582
ctx->Light.Material[0].Diffuse[3]);
584
if (IDX & LIGHT_TWOSIDE) {
585
COPY_3V(base[1], light->_MatAmbient[1]);
586
ACC_3V(base[1], ctx->Light._BaseColor[1]);
587
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
588
UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3],
589
ctx->Light.Material[1].Diffuse[3]);
593
GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
595
if (n_dot_VP < 0.0F) {
596
if (IDX & LIGHT_TWOSIDE) {
597
GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
599
COPY_3V(sum, base[1]);
600
ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
601
if (n_dot_h > 0.0F) {
603
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
604
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
606
UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
607
Bcolor[j][3] = basechan[1][3];
609
COPY_CHAN4(Fcolor[j], basechan[0]);
611
GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
613
COPY_3V(sum, base[0]);
614
ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
615
if (n_dot_h > 0.0F) {
617
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
618
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
621
UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
622
Fcolor[j][3] = basechan[0][3];
623
if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
628
STRIDE_F(normal, NSTRIDE);
629
} while (DO_ANOTHER_NORMAL(j));
632
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
634
COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
635
if (IDX & LIGHT_TWOSIDE)
636
COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
639
} while (!CHECK_END_VB(j));
643
/* Light infinite lights
645
static void TAG(light_fast_rgba)( GLcontext *ctx,
646
struct vertex_buffer *VB,
647
struct gl_pipeline_stage *stage,
650
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
652
GLuint nstride = VB->NormalPtr->stride;
653
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
656
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
657
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
658
GLuint *flags = VB->Flag;
660
struct gl_material (*new_material)[2] = VB->Material;
661
GLuint *new_material_mask = VB->MaterialMask;
662
GLuint nr = VB->Count;
663
struct gl_light *light;
665
if (MESA_VERBOSE & VERBOSE_LIGHTING)
666
fprintf(stderr, "%s\n", __FUNCTION__ );
674
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
675
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
677
if (IDX & LIGHT_COLORMATERIAL) {
678
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
679
VB->ColorPtr[0]->Size != 4)
680
import_color_material( ctx, stage );
682
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
683
CMstride = VB->ColorPtr[0]->StrideB;
686
VB->ColorPtr[0] = &store->LitColor[0];
687
if (IDX & LIGHT_TWOSIDE)
688
VB->ColorPtr[1] = &store->LitColor[1];
690
if (stage->changed_inputs == 0)
697
if ( CHECK_COLOR_MATERIAL(j) )
698
_mesa_update_color_material( ctx, CMcolor );
700
if ( CHECK_MATERIAL(j) )
701
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
703
if ( CHECK_VALIDATE(j) ) {
704
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
705
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
706
if (IDX & LIGHT_TWOSIDE)
707
UNCLAMPED_FLOAT_TO_CHAN(sumA[1],
708
ctx->Light.Material[1].Diffuse[3]);
712
COPY_3V(sum[0], ctx->Light._BaseColor[0]);
713
if (IDX & LIGHT_TWOSIDE)
714
COPY_3V(sum[1], ctx->Light._BaseColor[1]);
716
foreach (light, &ctx->Light.EnabledList) {
717
GLfloat n_dot_h, n_dot_VP, spec;
719
ACC_3V(sum[0], light->_MatAmbient[0]);
720
if (IDX & LIGHT_TWOSIDE)
721
ACC_3V(sum[1], light->_MatAmbient[1]);
723
n_dot_VP = DOT3(normal, light->_VP_inf_norm);
725
if (n_dot_VP > 0.0F) {
726
ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
727
n_dot_h = DOT3(normal, light->_h_inf_norm);
728
if (n_dot_h > 0.0F) {
729
struct gl_shine_tab *tab = ctx->_ShineTable[0];
730
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
731
ACC_SCALE_SCALAR_3V( sum[0], spec,
732
light->_MatSpecular[0]);
735
else if (IDX & LIGHT_TWOSIDE) {
736
ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
737
n_dot_h = -DOT3(normal, light->_h_inf_norm);
738
if (n_dot_h > 0.0F) {
739
struct gl_shine_tab *tab = ctx->_ShineTable[1];
740
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
741
ACC_SCALE_SCALAR_3V( sum[1], spec,
742
light->_MatSpecular[1]);
747
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
748
Fcolor[j][3] = sumA[0];
750
if (IDX & LIGHT_TWOSIDE) {
751
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
752
Bcolor[j][3] = sumA[1];
757
STRIDE_F(normal, NSTRIDE);
758
} while (DO_ANOTHER_NORMAL(j));
760
/* Reuse the shading results while there is no change to
761
* normal or material values.
763
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
765
COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
766
if (IDX & LIGHT_TWOSIDE)
767
COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
770
} while (!CHECK_END_VB(j));
778
* Use current lighting/material settings to compute the color indexes
779
* for an array of vertices.
780
* Input: n - number of vertices to light
781
* side - 0=use front material, 1=use back material
782
* vertex - array of [n] vertex position in eye coordinates
783
* normal - array of [n] surface normal vector
784
* Output: indexResult - resulting array of [n] color indexes
786
static void TAG(light_ci)( GLcontext *ctx,
787
struct vertex_buffer *VB,
788
struct gl_pipeline_stage *stage,
791
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
793
GLuint vstride = input->stride;
794
const GLfloat *vertex = (GLfloat *) input->data;
795
GLuint nstride = VB->NormalPtr->stride;
796
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
799
GLuint *flags = VB->Flag;
800
GLuint *indexResult[2];
801
struct gl_material (*new_material)[2] = VB->Material;
802
GLuint *new_material_mask = VB->MaterialMask;
803
GLuint nr = VB->Count;
805
if (MESA_VERBOSE & VERBOSE_LIGHTING)
806
fprintf(stderr, "%s\n", __FUNCTION__ );
812
VB->IndexPtr[0] = &store->LitIndex[0];
813
if (IDX & LIGHT_TWOSIDE)
814
VB->IndexPtr[1] = &store->LitIndex[1];
816
if (stage->changed_inputs == 0)
819
indexResult[0] = VB->IndexPtr[0]->data;
820
if (IDX & LIGHT_TWOSIDE)
821
indexResult[1] = VB->IndexPtr[1]->data;
823
if (IDX & LIGHT_COLORMATERIAL) {
824
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
825
VB->ColorPtr[0]->Size != 4)
826
import_color_material( ctx, stage );
828
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
829
CMstride = VB->ColorPtr[0]->StrideB;
832
/* loop over vertices */
835
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
837
GLfloat diffuse[2], specular[2];
839
struct gl_light *light;
841
if ( CHECK_COLOR_MATERIAL(j) )
842
_mesa_update_color_material( ctx, CMcolor );
844
if ( CHECK_MATERIAL(j) )
845
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
847
if ( CHECK_VALIDATE(j) )
848
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
850
diffuse[0] = specular[0] = 0.0F;
852
if ( IDX & LIGHT_TWOSIDE ) {
853
diffuse[1] = specular[1] = 0.0F;
856
/* Accumulate diffuse and specular from each light source */
857
foreach (light, &ctx->Light.EnabledList) {
859
GLfloat attenuation = 1.0F;
860
GLfloat VP[3]; /* unit vector from vertex to light */
861
GLfloat n_dot_VP; /* dot product of l and n */
862
GLfloat *h, n_dot_h, correction = 1.0;
864
/* compute l and attenuation */
865
if (!(light->_Flags & LIGHT_POSITIONAL)) {
866
/* directional light */
867
COPY_3V(VP, light->_VP_inf_norm);
870
GLfloat d; /* distance from vertex to light */
872
SUB_3V(VP, light->_Position, vertex);
874
d = (GLfloat) LEN_3FV( VP );
876
GLfloat invd = 1.0F / d;
877
SELF_SCALE_SCALAR_3V(VP, invd);
880
attenuation = 1.0F / (light->ConstantAttenuation + d *
881
(light->LinearAttenuation + d *
882
light->QuadraticAttenuation));
884
/* spotlight attenuation */
885
if (light->_Flags & LIGHT_SPOT) {
886
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
887
if (PV_dot_dir < light->_CosCutoff) {
888
continue; /* this light makes no contribution */
891
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
893
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
894
+ (x-k)*light->_SpotExpTable[k][1]);
900
if (attenuation < 1e-3)
901
continue; /* this light makes no contribution */
903
n_dot_VP = DOT3( normal, VP );
905
/* which side are we lighting? */
906
if (n_dot_VP < 0.0F) {
907
if (!(IDX & LIGHT_TWOSIDE))
911
n_dot_VP = -n_dot_VP;
914
/* accumulate diffuse term */
915
diffuse[side] += n_dot_VP * light->_dli * attenuation;
918
if (ctx->Light.Model.LocalViewer) {
922
SUB_3V(VP, VP, v); /* h = VP + VPe */
926
else if (light->_Flags & LIGHT_POSITIONAL) {
928
/* Strangely, disabling this addition fixes a conformance
929
* problem. If this code is enabled, l_sed.c fails.
931
/*ACC_3V(h, ctx->_EyeZDir);*/
935
h = light->_h_inf_norm;
938
n_dot_h = correction * DOT3(normal, h);
939
if (n_dot_h > 0.0F) {
941
struct gl_shine_tab *tab = ctx->_ShineTable[side];
942
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
943
specular[side] += spec_coef * light->_sli * attenuation;
945
} /*loop over lights*/
947
/* Now compute final color index */
948
for (side = 0 ; side < NR_SIDES ; side++) {
949
struct gl_material *mat = &ctx->Light.Material[side];
952
if (specular[side] > 1.0F) {
953
index = mat->SpecularIndex;
956
GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
957
GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
959
index = mat->AmbientIndex
960
+ diffuse[side] * (1.0F-specular[side]) * d_a
961
+ specular[side] * s_a;
963
if (index > mat->SpecularIndex) {
964
index = mat->SpecularIndex;
967
indexResult[side][j] = (GLuint) (GLint) index;
974
static void TAG(init_light_tab)( void )
976
_tnl_light_tab[IDX] = TAG(light_rgba);
977
_tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
978
_tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
979
_tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
980
_tnl_light_ci_tab[IDX] = TAG(light_ci);
989
#undef CHECK_MATERIAL
991
#undef DO_ANOTHER_NORMAL
992
#undef REUSE_LIGHT_RESULTS
994
#undef CHECK_COLOR_MATERIAL
995
#undef CHECK_VALIDATE