1 /* $Id: t_vb_lighttmp.h,v 1.10 2001/03/12 00:48:44 gareth Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
28 * Brian Paul <brianp@valinux.com>
29 * Keith Whitwell <keithw@valinux.com>
33 #if (IDX & LIGHT_FLAGS)
34 # define VSTRIDE (4 * sizeof(GLfloat))
35 # define NSTRIDE (3 * sizeof(GLfloat))
36 # define CHECK_MATERIAL(x) (flags[x] & VERT_MATERIAL)
37 # define CHECK_END_VB(x) (flags[x] & VERT_END_VB)
38 # if (IDX & LIGHT_COLORMATERIAL)
39 # define CMSTRIDE STRIDE_4CHAN(CMcolor, (4 * sizeof(GLchan)))
40 # define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_RGBA)
41 # define CHECK_VALIDATE(x) (flags[x] & (VERT_RGBA|VERT_MATERIAL))
42 # define DO_ANOTHER_NORMAL(x) \
43 ((flags[x] & (VERT_RGBA|VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == VERT_NORM)
44 # define REUSE_LIGHT_RESULTS(x) \
45 ((flags[x] & (VERT_RGBA|VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == 0)
48 # define CHECK_COLOR_MATERIAL(x) 0
49 # define CHECK_VALIDATE(x) (flags[x] & (VERT_MATERIAL))
50 # define DO_ANOTHER_NORMAL(x) \
51 ((flags[x] & (VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == VERT_NORM)
52 # define REUSE_LIGHT_RESULTS(x) \
53 ((flags[x] & (VERT_NORM|VERT_END_VB|VERT_MATERIAL)) == 0)
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_4CHAN(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 */
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 */
71 # define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */
76 #if (IDX & LIGHT_TWOSIDE)
84 static void TAG(light_rgba_spec
)( GLcontext
*ctx
,
85 struct vertex_buffer
*VB
,
86 struct gl_pipeline_stage
*stage
,
89 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
90 GLfloat (*base
)[3] = ctx
->Light
._BaseColor
;
91 const GLchan
*sumA
= ctx
->Light
._BaseAlpha
;
95 GLuint vstride
= input
->stride
;
96 const GLfloat
*vertex
= (GLfloat
*)input
->data
;
97 GLuint nstride
= VB
->NormalPtr
->stride
;
98 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
100 GLchan (*CMcolor
)[4];
103 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
104 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
105 GLchan (*Fspec
)[4] = (GLchan (*)[4]) store
->LitSecondary
[0].data
;
106 GLchan (*Bspec
)[4] = (GLchan (*)[4]) store
->LitSecondary
[1].data
;
107 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
;
117 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
119 if (IDX
& LIGHT_COLORMATERIAL
) {
120 CMcolor
= (GLchan (*)[4]) VB
->ColorPtr
[0]->data
;
121 CMstride
= VB
->ColorPtr
[0]->stride
;
124 VB
->ColorPtr
[0] = &store
->LitColor
[0];
125 VB
->SecondaryColorPtr
[0] = &store
->LitSecondary
[0];
127 if (IDX
& LIGHT_TWOSIDE
) {
128 VB
->ColorPtr
[1] = &store
->LitColor
[1];
129 VB
->SecondaryColorPtr
[1] = &store
->LitSecondary
[1];
132 /* Side-effects done, can we finish now?
134 if (stage
->changed_inputs
== 0)
139 j
++,STRIDE_F(vertex
,VSTRIDE
),STRIDE_F(normal
,NSTRIDE
),CMSTRIDE
)
141 GLfloat sum
[2][3], spec
[2][3];
142 struct gl_light
*light
;
144 if ( CHECK_COLOR_MATERIAL(j
) )
145 _mesa_update_color_material( ctx
, CMcolor
[j
] );
147 if ( CHECK_MATERIAL(j
) )
148 _mesa_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
150 if ( CHECK_VALIDATE(j
) )
151 _mesa_validate_all_lighting_tables( ctx
);
153 COPY_3V(sum
[0], base
[0]);
156 if (IDX
& LIGHT_TWOSIDE
) {
157 COPY_3V(sum
[1], base
[1]);
161 /* Add contribution from each enabled light source */
162 foreach (light
, &ctx
->Light
.EnabledList
) {
168 GLfloat VP
[3]; /* unit vector from vertex to light */
169 GLfloat n_dot_VP
; /* n dot VP */
172 /* compute VP and attenuation */
173 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
174 /* directional light */
175 COPY_3V(VP
, light
->_VP_inf_norm
);
176 attenuation
= light
->_VP_inf_spot_attenuation
;
179 GLfloat d
; /* distance from vertex to light */
181 SUB_3V(VP
, light
->_Position
, vertex
);
183 d
= (GLfloat
) LEN_3FV( VP
);
186 GLfloat invd
= 1.0F
/ d
;
187 SELF_SCALE_SCALAR_3V(VP
, invd
);
190 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
191 (light
->LinearAttenuation
+ d
*
192 light
->QuadraticAttenuation
));
194 /* spotlight attenuation */
195 if (light
->_Flags
& LIGHT_SPOT
) {
196 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
198 if (PV_dot_dir
<light
->_CosCutoff
) {
199 continue; /* this light makes no contribution */
202 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
204 GLfloat spot
= (GLfloat
) (light
->_SpotExpTable
[k
][0]
205 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
212 if (attenuation
< 1e-3)
213 continue; /* this light makes no contribution */
215 /* Compute dot product or normal and vector from V to light pos */
216 n_dot_VP
= DOT3( normal
, VP
);
218 /* Which side gets the diffuse & specular terms? */
219 if (n_dot_VP
< 0.0F
) {
220 ACC_SCALE_SCALAR_3V(sum
[0], attenuation
, light
->_MatAmbient
[0]);
221 if (!(IDX
& LIGHT_TWOSIDE
)) {
226 n_dot_VP
= -n_dot_VP
;
229 if (IDX
& LIGHT_TWOSIDE
) {
230 ACC_SCALE_SCALAR_3V( sum
[1], attenuation
, light
->_MatAmbient
[1]);
237 COPY_3V(contrib
, light
->_MatAmbient
[side
]);
238 ACC_SCALE_SCALAR_3V(contrib
, n_dot_VP
, light
->_MatDiffuse
[side
]);
239 ACC_SCALE_SCALAR_3V(sum
[side
], attenuation
, contrib
);
241 /* specular term - cannibalize VP... */
242 if (ctx
->Light
.Model
.LocalViewer
) {
246 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
250 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
252 ACC_3V(h
, ctx
->_EyeZDir
);
256 h
= light
->_h_inf_norm
;
259 n_dot_h
= correction
* DOT3(normal
, h
);
261 if (n_dot_h
> 0.0F
) {
263 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
264 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
266 if (spec_coef
> 1.0e-10) {
267 spec_coef
*= attenuation
;
268 ACC_SCALE_SCALAR_3V( spec
[side
], spec_coef
,
269 light
->_MatSpecular
[side
]);
272 } /*loop over lights*/
274 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
275 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec
[j
], spec
[0] );
276 Fcolor
[j
][3] = sumA
[0];
278 if (IDX
& LIGHT_TWOSIDE
) {
279 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
280 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec
[j
], spec
[1] );
281 Bcolor
[j
][3] = sumA
[1];
287 static void TAG(light_rgba
)( GLcontext
*ctx
,
288 struct vertex_buffer
*VB
,
289 struct gl_pipeline_stage
*stage
,
292 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
295 GLfloat (*base
)[3] = ctx
->Light
._BaseColor
;
296 const GLchan
*sumA
= ctx
->Light
._BaseAlpha
;
298 GLuint vstride
= input
->stride
;
299 const GLfloat
*vertex
= (GLfloat
*) input
->data
;
300 GLuint nstride
= VB
->NormalPtr
->stride
;
301 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
303 GLchan (*CMcolor
)[4];
306 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
307 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
308 GLuint
*flags
= VB
->Flag
;
310 struct gl_material (*new_material
)[2] = VB
->Material
;
311 GLuint
*new_material_mask
= VB
->MaterialMask
;
312 GLuint nr
= VB
->Count
;
314 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
319 if (IDX
& LIGHT_COLORMATERIAL
) {
320 CMcolor
= VB
->ColorPtr
[0]->data
;
321 CMstride
= VB
->ColorPtr
[0]->stride
;
324 VB
->ColorPtr
[0] = &store
->LitColor
[0];
325 if (IDX
& LIGHT_TWOSIDE
)
326 VB
->ColorPtr
[1] = &store
->LitColor
[1];
328 if (stage
->changed_inputs
== 0)
333 j
++,STRIDE_F(vertex
,VSTRIDE
), STRIDE_F(normal
,NSTRIDE
),CMSTRIDE
)
336 struct gl_light
*light
;
338 if ( CHECK_COLOR_MATERIAL(j
) )
339 _mesa_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
341 if ( CHECK_MATERIAL(j
) )
342 _mesa_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
344 if ( CHECK_VALIDATE(j
) )
345 _mesa_validate_all_lighting_tables( ctx
);
347 COPY_3V(sum
[0], base
[0]);
349 if ( IDX
& LIGHT_TWOSIDE
)
350 COPY_3V(sum
[1], base
[1]);
352 /* Add contribution from each enabled light source */
353 foreach (light
, &ctx
->Light
.EnabledList
) {
359 GLfloat attenuation
= 1.0;
360 GLfloat VP
[3]; /* unit vector from vertex to light */
361 GLfloat n_dot_VP
; /* n dot VP */
364 /* compute VP and attenuation */
365 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
366 /* directional light */
367 COPY_3V(VP
, light
->_VP_inf_norm
);
368 attenuation
= light
->_VP_inf_spot_attenuation
;
371 GLfloat d
; /* distance from vertex to light */
374 SUB_3V(VP
, light
->_Position
, vertex
);
379 GLfloat invd
= 1.0F
/ d
;
380 SELF_SCALE_SCALAR_3V(VP
, invd
);
383 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
384 (light
->LinearAttenuation
+ d
*
385 light
->QuadraticAttenuation
));
387 /* spotlight attenuation */
388 if (light
->_Flags
& LIGHT_SPOT
) {
389 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
391 if (PV_dot_dir
<light
->_CosCutoff
) {
392 continue; /* this light makes no contribution */
395 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
397 GLfloat spot
= (light
->_SpotExpTable
[k
][0]
398 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
405 if (attenuation
< 1e-3)
406 continue; /* this light makes no contribution */
409 /* Compute dot product or normal and vector from V to light pos */
410 n_dot_VP
= DOT3( normal
, VP
);
412 /* which side are we lighting? */
413 if (n_dot_VP
< 0.0F
) {
414 ACC_SCALE_SCALAR_3V(sum
[0], attenuation
, light
->_MatAmbient
[0]);
416 if (!(IDX
& LIGHT_TWOSIDE
))
421 n_dot_VP
= -n_dot_VP
;
424 if (IDX
& LIGHT_TWOSIDE
) {
425 ACC_SCALE_SCALAR_3V( sum
[1], attenuation
, light
->_MatAmbient
[1]);
431 COPY_3V(contrib
, light
->_MatAmbient
[side
]);
434 ACC_SCALE_SCALAR_3V(contrib
, n_dot_VP
, light
->_MatDiffuse
[side
]);
436 /* specular term - cannibalize VP... */
438 if (ctx
->Light
.Model
.LocalViewer
) {
442 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
446 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
448 ACC_3V(h
, ctx
->_EyeZDir
);
452 h
= light
->_h_inf_norm
;
455 n_dot_h
= correction
* DOT3(normal
, h
);
460 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
462 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
464 ACC_SCALE_SCALAR_3V( contrib
, spec_coef
,
465 light
->_MatSpecular
[side
]);
469 ACC_SCALE_SCALAR_3V( sum
[side
], attenuation
, contrib
);
472 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
473 Fcolor
[j
][3] = sumA
[0];
475 if (IDX
& LIGHT_TWOSIDE
) {
476 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
477 Bcolor
[j
][3] = sumA
[1];
485 /* As below, but with just a single light.
487 static void TAG(light_fast_rgba_single
)( GLcontext
*ctx
,
488 struct vertex_buffer
*VB
,
489 struct gl_pipeline_stage
*stage
,
493 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
494 GLuint nstride
= VB
->NormalPtr
->stride
;
495 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
496 GLchan (*CMcolor
)[4];
498 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
499 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
500 struct gl_light
*light
= ctx
->Light
.EnabledList
.next
;
501 GLuint
*flags
= VB
->Flag
;
502 GLchan baseubyte
[2][4];
504 struct gl_material (*new_material
)[2] = VB
->Material
;
505 GLuint
*new_material_mask
= VB
->MaterialMask
;
507 GLuint nr
= VB
->Count
;
509 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
510 (void) input
; /* doesn't refer to Eye or Obj */
515 if (IDX
& LIGHT_COLORMATERIAL
) {
516 CMcolor
= VB
->ColorPtr
[0]->data
;
517 CMstride
= VB
->ColorPtr
[0]->stride
;
520 VB
->ColorPtr
[0] = &store
->LitColor
[0];
521 if (IDX
& LIGHT_TWOSIDE
)
522 VB
->ColorPtr
[1] = &store
->LitColor
[1];
524 if (stage
->changed_inputs
== 0)
529 if ( CHECK_COLOR_MATERIAL(j
) )
530 _mesa_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
532 if ( CHECK_MATERIAL(j
) )
533 _mesa_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
535 if ( CHECK_VALIDATE(j
) )
536 _mesa_validate_all_lighting_tables( ctx
);
538 baseubyte
[0][3] = ctx
->Light
._BaseAlpha
[0];
539 baseubyte
[1][3] = ctx
->Light
._BaseAlpha
[1];
541 /* No attenuation, so incoporate _MatAmbient into base color.
544 COPY_3V(base
[0], light
->_MatAmbient
[0]);
545 ACC_3V(base
[0], ctx
->Light
._BaseColor
[0] );
546 UNCLAMPED_FLOAT_TO_RGB_CHAN( baseubyte
[0], base
[0] );
548 if (IDX
& LIGHT_TWOSIDE
) {
549 COPY_3V(base
[1], light
->_MatAmbient
[1]);
550 ACC_3V(base
[1], ctx
->Light
._BaseColor
[1]);
551 UNCLAMPED_FLOAT_TO_RGB_CHAN( baseubyte
[1], base
[1]);
556 GLfloat n_dot_VP
= DOT3(normal
, light
->_VP_inf_norm
);
558 COPY_CHAN4(Fcolor
[j
], baseubyte
[0]);
559 if (IDX
& LIGHT_TWOSIDE
) COPY_CHAN4(Bcolor
[j
], baseubyte
[1]);
561 if (n_dot_VP
< 0.0F
) {
562 if (IDX
& LIGHT_TWOSIDE
) {
563 GLfloat n_dot_h
= -DOT3(normal
, light
->_h_inf_norm
);
565 COPY_3V(sum
, base
[1]);
566 ACC_SCALE_SCALAR_3V(sum
, -n_dot_VP
, light
->_MatDiffuse
[1]);
567 if (n_dot_h
> 0.0F
) {
569 GET_SHINE_TAB_ENTRY( ctx
->_ShineTable
[1], n_dot_h
, spec
);
570 ACC_SCALE_SCALAR_3V(sum
, spec
, light
->_MatSpecular
[1]);
572 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor
[j
], sum
);
575 GLfloat n_dot_h
= DOT3(normal
, light
->_h_inf_norm
);
577 COPY_3V(sum
, base
[0]);
578 ACC_SCALE_SCALAR_3V(sum
, n_dot_VP
, light
->_MatDiffuse
[0]);
579 if (n_dot_h
> 0.0F
) {
581 GET_SHINE_TAB_ENTRY( ctx
->_ShineTable
[0], n_dot_h
, spec
);
582 ACC_SCALE_SCALAR_3V(sum
, spec
, light
->_MatSpecular
[0]);
585 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor
[j
], sum
);
589 STRIDE_F(normal
, NSTRIDE
);
590 } while (DO_ANOTHER_NORMAL(j
));
593 for ( ; REUSE_LIGHT_RESULTS(j
) ; j
++ ) {
594 COPY_CHAN4(Fcolor
[j
], Fcolor
[j
-1]);
595 if (IDX
& LIGHT_TWOSIDE
)
596 COPY_CHAN4(Bcolor
[j
], Bcolor
[j
-1]);
597 STRIDE_F(normal
, NSTRIDE
);
600 } while (!CHECK_END_VB(j
));
604 /* Light infinite lights
606 static void TAG(light_fast_rgba
)( GLcontext
*ctx
,
607 struct vertex_buffer
*VB
,
608 struct gl_pipeline_stage
*stage
,
611 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
612 const GLchan
*sumA
= ctx
->Light
._BaseAlpha
;
613 GLuint nstride
= VB
->NormalPtr
->stride
;
614 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
615 GLchan (*CMcolor
)[4];
617 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
618 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
619 GLuint
*flags
= VB
->Flag
;
621 struct gl_material (*new_material
)[2] = VB
->Material
;
622 GLuint
*new_material_mask
= VB
->MaterialMask
;
623 GLuint nr
= VB
->Count
;
624 struct gl_light
*light
;
626 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
632 if (IDX
& LIGHT_COLORMATERIAL
) {
633 CMcolor
= VB
->ColorPtr
[0]->data
;
634 CMstride
= VB
->ColorPtr
[0]->stride
;
637 VB
->ColorPtr
[0] = &store
->LitColor
[0];
638 if (IDX
& LIGHT_TWOSIDE
)
639 VB
->ColorPtr
[1] = &store
->LitColor
[1];
641 if (stage
->changed_inputs
== 0)
648 if ( CHECK_COLOR_MATERIAL(j
) )
649 _mesa_update_color_material( ctx
, CMcolor
[j
] );
651 if ( CHECK_MATERIAL(j
) )
652 _mesa_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
654 if ( CHECK_VALIDATE(j
) )
655 _mesa_validate_all_lighting_tables( ctx
);
658 COPY_3V(sum
[0], ctx
->Light
._BaseColor
[0]);
659 if (IDX
& LIGHT_TWOSIDE
)
660 COPY_3V(sum
[1], ctx
->Light
._BaseColor
[1]);
662 foreach (light
, &ctx
->Light
.EnabledList
) {
663 GLfloat n_dot_h
, n_dot_VP
, spec
;
665 ACC_3V(sum
[0], light
->_MatAmbient
[0]);
666 if (IDX
& LIGHT_TWOSIDE
)
667 ACC_3V(sum
[1], light
->_MatAmbient
[1]);
669 n_dot_VP
= DOT3(normal
, light
->_VP_inf_norm
);
671 if (n_dot_VP
> 0.0F
) {
672 ACC_SCALE_SCALAR_3V(sum
[0], n_dot_VP
, light
->_MatDiffuse
[0]);
673 n_dot_h
= DOT3(normal
, light
->_h_inf_norm
);
674 if (n_dot_h
> 0.0F
) {
675 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[0];
676 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
677 ACC_SCALE_SCALAR_3V( sum
[0], spec
,
678 light
->_MatSpecular
[0]);
681 else if (IDX
& LIGHT_TWOSIDE
) {
682 ACC_SCALE_SCALAR_3V(sum
[1], -n_dot_VP
, light
->_MatDiffuse
[1]);
683 n_dot_h
= -DOT3(normal
, light
->_h_inf_norm
);
684 if (n_dot_h
> 0.0F
) {
685 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[1];
686 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
687 ACC_SCALE_SCALAR_3V( sum
[1], spec
,
688 light
->_MatSpecular
[1]);
693 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
694 Fcolor
[j
][3] = sumA
[0];
696 if (IDX
& LIGHT_TWOSIDE
) {
697 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
698 Bcolor
[j
][3] = sumA
[1];
702 STRIDE_F(normal
, NSTRIDE
);
703 } while (DO_ANOTHER_NORMAL(j
));
705 /* Reuse the shading results while there is no change to
706 * normal or material values.
708 for ( ; REUSE_LIGHT_RESULTS(j
) ; j
++ ) {
709 COPY_CHAN4(Fcolor
[j
], Fcolor
[j
-1]);
710 if (IDX
& LIGHT_TWOSIDE
)
711 COPY_CHAN4(Bcolor
[j
], Bcolor
[j
-1]);
712 STRIDE_F(normal
, NSTRIDE
);
715 } while (!CHECK_END_VB(j
));
723 * Use current lighting/material settings to compute the color indexes
724 * for an array of vertices.
725 * Input: n - number of vertices to light
726 * side - 0=use front material, 1=use back material
727 * vertex - array of [n] vertex position in eye coordinates
728 * normal - array of [n] surface normal vector
729 * Output: indexResult - resulting array of [n] color indexes
731 static void TAG(light_ci
)( GLcontext
*ctx
,
732 struct vertex_buffer
*VB
,
733 struct gl_pipeline_stage
*stage
,
736 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
738 GLuint vstride
= input
->stride
;
739 const GLfloat
*vertex
= (GLfloat
*) input
->data
;
740 GLuint nstride
= VB
->NormalPtr
->stride
;
741 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
742 GLchan (*CMcolor
)[4];
744 GLuint
*flags
= VB
->Flag
;
745 GLuint
*indexResult
[2];
746 struct gl_material (*new_material
)[2] = VB
->Material
;
747 GLuint
*new_material_mask
= VB
->MaterialMask
;
748 GLuint nr
= VB
->Count
;
750 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
755 VB
->IndexPtr
[0] = &store
->LitIndex
[0];
756 if (IDX
& LIGHT_TWOSIDE
)
757 VB
->IndexPtr
[1] = &store
->LitIndex
[1];
759 if (stage
->changed_inputs
== 0)
762 indexResult
[0] = VB
->IndexPtr
[0]->data
;
763 if (IDX
& LIGHT_TWOSIDE
)
764 indexResult
[1] = VB
->IndexPtr
[1]->data
;
766 if (IDX
& LIGHT_COLORMATERIAL
) {
767 CMcolor
= VB
->ColorPtr
[0]->data
;
768 CMstride
= VB
->ColorPtr
[0]->stride
;
771 /* loop over vertices */
774 j
++,STRIDE_F(vertex
,VSTRIDE
),STRIDE_F(normal
, NSTRIDE
), CMSTRIDE
)
776 GLfloat diffuse
[2], specular
[2];
778 struct gl_light
*light
;
780 if ( CHECK_COLOR_MATERIAL(j
) )
781 _mesa_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
783 if ( CHECK_MATERIAL(j
) )
784 _mesa_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
786 if ( CHECK_VALIDATE(j
) )
787 _mesa_validate_all_lighting_tables( ctx
);
789 diffuse
[0] = specular
[0] = 0.0F
;
791 if ( IDX
& LIGHT_TWOSIDE
) {
792 diffuse
[1] = specular
[1] = 0.0F
;
795 /* Accumulate diffuse and specular from each light source */
796 foreach (light
, &ctx
->Light
.EnabledList
) {
798 GLfloat attenuation
= 1.0F
;
799 GLfloat VP
[3]; /* unit vector from vertex to light */
800 GLfloat n_dot_VP
; /* dot product of l and n */
801 GLfloat
*h
, n_dot_h
, correction
= 1.0;
803 /* compute l and attenuation */
804 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
805 /* directional light */
806 COPY_3V(VP
, light
->_VP_inf_norm
);
809 GLfloat d
; /* distance from vertex to light */
811 SUB_3V(VP
, light
->_Position
, vertex
);
815 GLfloat invd
= 1.0F
/ d
;
816 SELF_SCALE_SCALAR_3V(VP
, invd
);
819 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
820 (light
->LinearAttenuation
+ d
*
821 light
->QuadraticAttenuation
));
823 /* spotlight attenuation */
824 if (light
->_Flags
& LIGHT_SPOT
) {
825 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
826 if (PV_dot_dir
< light
->_CosCutoff
) {
827 continue; /* this light makes no contribution */
830 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
832 GLfloat spot
= (light
->_SpotExpTable
[k
][0]
833 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
839 if (attenuation
< 1e-3)
840 continue; /* this light makes no contribution */
842 n_dot_VP
= DOT3( normal
, VP
);
844 /* which side are we lighting? */
845 if (n_dot_VP
< 0.0F
) {
846 if (!(IDX
& LIGHT_TWOSIDE
))
850 n_dot_VP
= -n_dot_VP
;
853 /* accumulate diffuse term */
854 diffuse
[side
] += n_dot_VP
* light
->_dli
* attenuation
;
857 if (ctx
->Light
.Model
.LocalViewer
) {
861 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
865 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
867 /* Strangely, disabling this addition fixes a conformance
868 * problem. If this code is enabled, l_sed.c fails.
870 /*ACC_3V(h, ctx->_EyeZDir);*/
874 h
= light
->_h_inf_norm
;
877 n_dot_h
= correction
* DOT3(normal
, h
);
878 if (n_dot_h
> 0.0F
) {
880 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
881 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
882 specular
[side
] += spec_coef
* light
->_sli
* attenuation
;
884 } /*loop over lights*/
886 /* Now compute final color index */
887 for (side
= 0 ; side
< NR_SIDES
; side
++) {
888 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
891 if (specular
[side
] > 1.0F
) {
892 index
= mat
->SpecularIndex
;
895 GLfloat d_a
= mat
->DiffuseIndex
- mat
->AmbientIndex
;
896 GLfloat s_a
= mat
->SpecularIndex
- mat
->AmbientIndex
;
898 index
= mat
->AmbientIndex
899 + diffuse
[side
] * (1.0F
-specular
[side
]) * d_a
900 + specular
[side
] * s_a
;
902 if (index
> mat
->SpecularIndex
) {
903 index
= mat
->SpecularIndex
;
906 indexResult
[side
][j
] = (GLuint
) (GLint
) index
;
913 static void TAG(init_light_tab
)( void )
915 _tnl_light_tab
[IDX
] = TAG(light_rgba
);
916 _tnl_light_fast_tab
[IDX
] = TAG(light_fast_rgba
);
917 _tnl_light_fast_single_tab
[IDX
] = TAG(light_fast_rgba_single
);
918 _tnl_light_spec_tab
[IDX
] = TAG(light_rgba_spec
);
919 _tnl_light_ci_tab
[IDX
] = TAG(light_ci
);
928 #undef CHECK_MATERIAL
930 #undef DO_ANOTHER_NORMAL
931 #undef REUSE_LIGHT_RESULTS
933 #undef CHECK_COLOR_MATERIAL
934 #undef CHECK_VALIDATE