1 /* $Id: t_vb_lighttmp.h,v 1.6 2001/02/14 23:00:42 brianp 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 if (IDX
& LIGHT_COLORMATERIAL
) {
118 CMcolor
= (GLchan (*)[4]) VB
->ColorPtr
[0]->data
;
119 CMstride
= VB
->ColorPtr
[0]->stride
;
122 VB
->ColorPtr
[0] = &store
->LitColor
[0];
123 VB
->SecondaryColorPtr
[0] = &store
->LitSecondary
[0];
125 if (IDX
& LIGHT_TWOSIDE
) {
126 VB
->ColorPtr
[1] = &store
->LitColor
[1];
127 VB
->SecondaryColorPtr
[1] = &store
->LitSecondary
[1];
130 /* Side-effects done, can we finish now?
132 if (stage
->changed_inputs
== 0)
137 j
++,STRIDE_F(vertex
,VSTRIDE
),STRIDE_F(normal
,NSTRIDE
),CMSTRIDE
)
139 GLfloat sum
[2][3], spec
[2][3];
140 struct gl_light
*light
;
142 if ( CHECK_COLOR_MATERIAL(j
) )
143 gl_update_color_material( ctx
, CMcolor
[j
] );
145 if ( CHECK_MATERIAL(j
) )
146 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
148 if ( CHECK_VALIDATE(j
) )
149 gl_validate_all_lighting_tables( ctx
);
151 COPY_3V(sum
[0], base
[0]);
154 if (IDX
& LIGHT_TWOSIDE
) {
155 COPY_3V(sum
[1], base
[1]);
159 /* Add contribution from each enabled light source */
160 foreach (light
, &ctx
->Light
.EnabledList
) {
166 GLfloat VP
[3]; /* unit vector from vertex to light */
167 GLfloat n_dot_VP
; /* n dot VP */
170 /* compute VP and attenuation */
171 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
172 /* directional light */
173 COPY_3V(VP
, light
->_VP_inf_norm
);
174 attenuation
= light
->_VP_inf_spot_attenuation
;
177 GLfloat d
; /* distance from vertex to light */
179 SUB_3V(VP
, light
->_Position
, vertex
);
181 d
= (GLfloat
) LEN_3FV( VP
);
184 GLfloat invd
= 1.0F
/ d
;
185 SELF_SCALE_SCALAR_3V(VP
, invd
);
188 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
189 (light
->LinearAttenuation
+ d
*
190 light
->QuadraticAttenuation
));
192 /* spotlight attenuation */
193 if (light
->_Flags
& LIGHT_SPOT
) {
194 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
196 if (PV_dot_dir
<light
->_CosCutoff
) {
197 continue; /* this light makes no contribution */
200 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
202 GLfloat spot
= (GLfloat
) (light
->_SpotExpTable
[k
][0]
203 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
210 if (attenuation
< 1e-3)
211 continue; /* this light makes no contribution */
213 /* Compute dot product or normal and vector from V to light pos */
214 n_dot_VP
= DOT3( normal
, VP
);
216 /* Which side gets the diffuse & specular terms? */
217 if (n_dot_VP
< 0.0F
) {
218 ACC_SCALE_SCALAR_3V(sum
[0], attenuation
, light
->_MatAmbient
[0]);
219 if (!(IDX
& LIGHT_TWOSIDE
)) {
224 n_dot_VP
= -n_dot_VP
;
227 if (IDX
& LIGHT_TWOSIDE
) {
228 ACC_SCALE_SCALAR_3V( sum
[1], attenuation
, light
->_MatAmbient
[1]);
235 COPY_3V(contrib
, light
->_MatAmbient
[side
]);
236 ACC_SCALE_SCALAR_3V(contrib
, n_dot_VP
, light
->_MatDiffuse
[side
]);
237 ACC_SCALE_SCALAR_3V(sum
[side
], attenuation
, contrib
);
239 /* specular term - cannibalize VP... */
240 if (ctx
->Light
.Model
.LocalViewer
) {
244 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
248 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
250 ACC_3V(h
, ctx
->_EyeZDir
);
254 h
= light
->_h_inf_norm
;
257 n_dot_h
= correction
* DOT3(normal
, h
);
259 if (n_dot_h
> 0.0F
) {
261 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
262 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
264 if (spec_coef
> 1.0e-10) {
265 spec_coef
*= attenuation
;
266 ACC_SCALE_SCALAR_3V( spec
[side
], spec_coef
,
267 light
->_MatSpecular
[side
]);
270 } /*loop over lights*/
272 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
273 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec
[j
], spec
[0] );
274 Fcolor
[j
][3] = sumA
[0];
276 if (IDX
& LIGHT_TWOSIDE
) {
277 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
278 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec
[j
], spec
[1] );
279 Bcolor
[j
][3] = sumA
[1];
283 if ( CHECK_COLOR_MATERIAL(j
) )
284 gl_update_color_material( ctx
, CMcolor
[j
] );
286 if ( CHECK_MATERIAL(j
) )
287 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
289 if ( CHECK_VALIDATE(j
) )
290 gl_validate_all_lighting_tables( ctx
);
294 static void TAG(light_rgba
)( GLcontext
*ctx
,
295 struct vertex_buffer
*VB
,
296 struct gl_pipeline_stage
*stage
,
299 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
302 GLfloat (*base
)[3] = ctx
->Light
._BaseColor
;
303 const GLchan
*sumA
= ctx
->Light
._BaseAlpha
;
305 GLuint vstride
= input
->stride
;
306 const GLfloat
*vertex
= (GLfloat
*) input
->data
;
307 GLuint nstride
= VB
->NormalPtr
->stride
;
308 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
310 GLchan (*CMcolor
)[4];
313 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
314 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
315 GLuint
*flags
= VB
->Flag
;
317 struct gl_material (*new_material
)[2] = VB
->Material
;
318 GLuint
*new_material_mask
= VB
->MaterialMask
;
319 GLuint nr
= VB
->Count
;
325 if (IDX
& LIGHT_COLORMATERIAL
) {
326 CMcolor
= VB
->ColorPtr
[0]->data
;
327 CMstride
= VB
->ColorPtr
[0]->stride
;
330 VB
->ColorPtr
[0] = &store
->LitColor
[0];
331 if (IDX
& LIGHT_TWOSIDE
)
332 VB
->ColorPtr
[1] = &store
->LitColor
[1];
334 if (stage
->changed_inputs
== 0)
339 j
++,STRIDE_F(vertex
,VSTRIDE
), STRIDE_F(normal
,NSTRIDE
),CMSTRIDE
)
342 struct gl_light
*light
;
344 if ( CHECK_COLOR_MATERIAL(j
) )
345 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
347 if ( CHECK_MATERIAL(j
) )
348 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
350 if ( CHECK_VALIDATE(j
) )
351 gl_validate_all_lighting_tables( ctx
);
353 COPY_3V(sum
[0], base
[0]);
355 if ( IDX
& LIGHT_TWOSIDE
)
356 COPY_3V(sum
[1], base
[1]);
358 /* Add contribution from each enabled light source */
359 foreach (light
, &ctx
->Light
.EnabledList
) {
365 GLfloat attenuation
= 1.0;
366 GLfloat VP
[3]; /* unit vector from vertex to light */
367 GLfloat n_dot_VP
; /* n dot VP */
370 /* compute VP and attenuation */
371 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
372 /* directional light */
373 COPY_3V(VP
, light
->_VP_inf_norm
);
374 attenuation
= light
->_VP_inf_spot_attenuation
;
377 GLfloat d
; /* distance from vertex to light */
380 SUB_3V(VP
, light
->_Position
, vertex
);
385 GLfloat invd
= 1.0F
/ d
;
386 SELF_SCALE_SCALAR_3V(VP
, invd
);
389 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
390 (light
->LinearAttenuation
+ d
*
391 light
->QuadraticAttenuation
));
393 /* spotlight attenuation */
394 if (light
->_Flags
& LIGHT_SPOT
) {
395 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
397 if (PV_dot_dir
<light
->_CosCutoff
) {
398 continue; /* this light makes no contribution */
401 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
403 GLfloat spot
= (light
->_SpotExpTable
[k
][0]
404 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
411 if (attenuation
< 1e-3)
412 continue; /* this light makes no contribution */
415 /* Compute dot product or normal and vector from V to light pos */
416 n_dot_VP
= DOT3( normal
, VP
);
418 /* which side are we lighting? */
419 if (n_dot_VP
< 0.0F
) {
420 ACC_SCALE_SCALAR_3V(sum
[0], attenuation
, light
->_MatAmbient
[0]);
422 if (!(IDX
& LIGHT_TWOSIDE
))
427 n_dot_VP
= -n_dot_VP
;
430 if (IDX
& LIGHT_TWOSIDE
) {
431 ACC_SCALE_SCALAR_3V( sum
[1], attenuation
, light
->_MatAmbient
[1]);
437 COPY_3V(contrib
, light
->_MatAmbient
[side
]);
440 ACC_SCALE_SCALAR_3V(contrib
, n_dot_VP
, light
->_MatDiffuse
[side
]);
442 /* specular term - cannibalize VP... */
444 if (ctx
->Light
.Model
.LocalViewer
) {
448 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
452 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
454 ACC_3V(h
, ctx
->_EyeZDir
);
458 h
= light
->_h_inf_norm
;
461 n_dot_h
= correction
* DOT3(normal
, h
);
466 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
468 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
470 ACC_SCALE_SCALAR_3V( contrib
, spec_coef
,
471 light
->_MatSpecular
[side
]);
475 ACC_SCALE_SCALAR_3V( sum
[side
], attenuation
, contrib
);
478 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
479 Fcolor
[j
][3] = sumA
[0];
481 if (IDX
& LIGHT_TWOSIDE
) {
482 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
483 Bcolor
[j
][3] = sumA
[1];
487 if ( CHECK_COLOR_MATERIAL(j
) )
488 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
490 if ( CHECK_MATERIAL(j
) )
491 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
493 if ( CHECK_VALIDATE(j
) )
494 gl_validate_all_lighting_tables( ctx
);
500 /* As below, but with just a single light.
502 static void TAG(light_fast_rgba_single
)( GLcontext
*ctx
,
503 struct vertex_buffer
*VB
,
504 struct gl_pipeline_stage
*stage
,
508 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
509 GLuint nstride
= VB
->NormalPtr
->stride
;
510 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
511 GLchan (*CMcolor
)[4];
513 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
514 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
515 struct gl_light
*light
= ctx
->Light
.EnabledList
.next
;
516 GLuint
*flags
= VB
->Flag
;
517 GLchan baseubyte
[2][4];
519 struct gl_material (*new_material
)[2] = VB
->Material
;
520 GLuint
*new_material_mask
= VB
->MaterialMask
;
522 GLuint nr
= VB
->Count
;
524 (void) input
; /* doesn't refer to Eye or Obj */
529 if (IDX
& LIGHT_COLORMATERIAL
) {
530 CMcolor
= VB
->ColorPtr
[0]->data
;
531 CMstride
= VB
->ColorPtr
[0]->stride
;
534 VB
->ColorPtr
[0] = &store
->LitColor
[0];
535 if (IDX
& LIGHT_TWOSIDE
)
536 VB
->ColorPtr
[1] = &store
->LitColor
[1];
538 if (stage
->changed_inputs
== 0)
541 if ( CHECK_COLOR_MATERIAL(j
) )
542 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
544 if ( CHECK_MATERIAL(j
) )
545 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
547 if ( CHECK_VALIDATE(j
) )
548 gl_validate_all_lighting_tables( ctx
);
550 baseubyte
[0][3] = ctx
->Light
._BaseAlpha
[0];
551 baseubyte
[1][3] = ctx
->Light
._BaseAlpha
[1];
554 /* No attenuation, so incoporate _MatAmbient into base color.
557 COPY_3V(base
[0], light
->_MatAmbient
[0]);
558 ACC_3V(base
[0], ctx
->Light
._BaseColor
[0] );
559 UNCLAMPED_FLOAT_TO_RGB_CHAN( baseubyte
[0], base
[0] );
561 if (IDX
& LIGHT_TWOSIDE
) {
562 COPY_3V(base
[1], light
->_MatAmbient
[1]);
563 ACC_3V(base
[1], ctx
->Light
._BaseColor
[1]);
564 UNCLAMPED_FLOAT_TO_RGB_CHAN( baseubyte
[1], base
[1]);
569 GLfloat n_dot_VP
= DOT3(normal
, light
->_VP_inf_norm
);
571 COPY_CHAN4(Fcolor
[j
], baseubyte
[0]);
572 if (IDX
& LIGHT_TWOSIDE
) COPY_CHAN4(Bcolor
[j
], baseubyte
[1]);
574 if (n_dot_VP
< 0.0F
) {
575 if (IDX
& LIGHT_TWOSIDE
) {
576 GLfloat n_dot_h
= -DOT3(normal
, light
->_h_inf_norm
);
578 COPY_3V(sum
, base
[1]);
579 ACC_SCALE_SCALAR_3V(sum
, -n_dot_VP
, light
->_MatDiffuse
[1]);
580 if (n_dot_h
> 0.0F
) {
582 GET_SHINE_TAB_ENTRY( ctx
->_ShineTable
[1], n_dot_h
, spec
);
583 ACC_SCALE_SCALAR_3V(sum
, spec
, light
->_MatSpecular
[1]);
585 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor
[j
], sum
);
588 GLfloat n_dot_h
= DOT3(normal
, light
->_h_inf_norm
);
590 COPY_3V(sum
, base
[0]);
591 ACC_SCALE_SCALAR_3V(sum
, n_dot_VP
, light
->_MatDiffuse
[0]);
592 if (n_dot_h
> 0.0F
) {
594 GET_SHINE_TAB_ENTRY( ctx
->_ShineTable
[0], n_dot_h
, spec
);
595 ACC_SCALE_SCALAR_3V(sum
, spec
, light
->_MatSpecular
[0]);
598 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor
[j
], sum
);
602 STRIDE_F(normal
, NSTRIDE
);
603 } while (DO_ANOTHER_NORMAL(j
));
606 for ( ; REUSE_LIGHT_RESULTS(j
) ; j
++ ) {
607 COPY_CHAN4(Fcolor
[j
], Fcolor
[j
-1]);
608 if (IDX
& LIGHT_TWOSIDE
)
609 COPY_CHAN4(Bcolor
[j
], Bcolor
[j
-1]);
610 STRIDE_F(normal
, NSTRIDE
);
613 /* Have to recompute our base colors on material change.
615 if ( CHECK_MATERIAL(j
) )
616 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
618 if ( CHECK_COLOR_MATERIAL(j
) )
619 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
621 if ( CHECK_VALIDATE(j
) )
622 gl_validate_all_lighting_tables( ctx
);
624 } while (!CHECK_END_VB(j
));
628 /* Light infinite lights
630 static void TAG(light_fast_rgba
)( GLcontext
*ctx
,
631 struct vertex_buffer
*VB
,
632 struct gl_pipeline_stage
*stage
,
635 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
636 const GLchan
*sumA
= ctx
->Light
._BaseAlpha
;
637 GLuint nstride
= VB
->NormalPtr
->stride
;
638 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
639 GLchan (*CMcolor
)[4];
641 GLchan (*Fcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[0].data
;
642 GLchan (*Bcolor
)[4] = (GLchan (*)[4]) store
->LitColor
[1].data
;
643 GLuint
*flags
= VB
->Flag
;
645 struct gl_material (*new_material
)[2] = VB
->Material
;
646 GLuint
*new_material_mask
= VB
->MaterialMask
;
647 GLuint nr
= VB
->Count
;
648 struct gl_light
*light
;
655 if (IDX
& LIGHT_COLORMATERIAL
) {
656 CMcolor
= VB
->ColorPtr
[0]->data
;
657 CMstride
= VB
->ColorPtr
[0]->stride
;
660 VB
->ColorPtr
[0] = &store
->LitColor
[0];
661 if (IDX
& LIGHT_TWOSIDE
)
662 VB
->ColorPtr
[1] = &store
->LitColor
[1];
664 if (stage
->changed_inputs
== 0)
667 if ( CHECK_COLOR_MATERIAL(j
) )
668 gl_update_color_material( ctx
, *CMcolor
);
670 if ( CHECK_MATERIAL(j
) )
671 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
673 if ( CHECK_VALIDATE(j
) )
674 gl_validate_all_lighting_tables( ctx
);
680 COPY_3V(sum
[0], ctx
->Light
._BaseColor
[0]);
681 if (IDX
& LIGHT_TWOSIDE
)
682 COPY_3V(sum
[1], ctx
->Light
._BaseColor
[1]);
684 foreach (light
, &ctx
->Light
.EnabledList
) {
685 GLfloat n_dot_h
, n_dot_VP
, spec
;
687 ACC_3V(sum
[0], light
->_MatAmbient
[0]);
688 if (IDX
& LIGHT_TWOSIDE
)
689 ACC_3V(sum
[1], light
->_MatAmbient
[1]);
691 n_dot_VP
= DOT3(normal
, light
->_VP_inf_norm
);
693 if (n_dot_VP
> 0.0F
) {
694 ACC_SCALE_SCALAR_3V(sum
[0], n_dot_VP
, light
->_MatDiffuse
[0]);
695 n_dot_h
= DOT3(normal
, light
->_h_inf_norm
);
696 if (n_dot_h
> 0.0F
) {
697 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[0];
698 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
699 ACC_SCALE_SCALAR_3V( sum
[0], spec
,
700 light
->_MatSpecular
[0]);
703 else if (IDX
& LIGHT_TWOSIDE
) {
704 ACC_SCALE_SCALAR_3V(sum
[1], -n_dot_VP
, light
->_MatDiffuse
[1]);
705 n_dot_h
= -DOT3(normal
, light
->_h_inf_norm
);
706 if (n_dot_h
> 0.0F
) {
707 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[1];
708 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
709 ACC_SCALE_SCALAR_3V( sum
[1], spec
,
710 light
->_MatSpecular
[1]);
715 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor
[j
], sum
[0] );
716 Fcolor
[j
][3] = sumA
[0];
718 if (IDX
& LIGHT_TWOSIDE
) {
719 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor
[j
], sum
[1] );
720 Bcolor
[j
][3] = sumA
[1];
724 STRIDE_F(normal
, NSTRIDE
);
725 } while (DO_ANOTHER_NORMAL(j
));
727 /* Reuse the shading results while there is no change to
728 * normal or material values.
730 for ( ; REUSE_LIGHT_RESULTS(j
) ; j
++ ) {
731 COPY_CHAN4(Fcolor
[j
], Fcolor
[j
-1]);
732 if (IDX
& LIGHT_TWOSIDE
)
733 COPY_CHAN4(Bcolor
[j
], Bcolor
[j
-1]);
734 STRIDE_F(normal
, NSTRIDE
);
737 if ( CHECK_COLOR_MATERIAL(j
) )
738 gl_update_color_material( ctx
, CMcolor
[j
] );
740 if ( CHECK_MATERIAL(j
) )
741 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
743 if ( CHECK_VALIDATE(j
) )
744 gl_validate_all_lighting_tables( ctx
);
746 } while (!CHECK_END_VB(j
));
754 * Use current lighting/material settings to compute the color indexes
755 * for an array of vertices.
756 * Input: n - number of vertices to light
757 * side - 0=use front material, 1=use back material
758 * vertex - array of [n] vertex position in eye coordinates
759 * normal - array of [n] surface normal vector
760 * Output: indexResult - resulting array of [n] color indexes
762 static void TAG(light_ci
)( GLcontext
*ctx
,
763 struct vertex_buffer
*VB
,
764 struct gl_pipeline_stage
*stage
,
767 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
769 GLuint vstride
= input
->stride
;
770 const GLfloat
*vertex
= (GLfloat
*) input
->data
;
771 GLuint nstride
= VB
->NormalPtr
->stride
;
772 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
773 GLchan (*CMcolor
)[4];
775 GLuint
*flags
= VB
->Flag
;
776 GLuint
*indexResult
[2];
777 struct gl_material (*new_material
)[2] = VB
->Material
;
778 GLuint
*new_material_mask
= VB
->MaterialMask
;
779 GLuint nr
= VB
->Count
;
785 VB
->IndexPtr
[0] = &store
->LitIndex
[0];
786 if (IDX
& LIGHT_TWOSIDE
)
787 VB
->IndexPtr
[1] = &store
->LitIndex
[1];
789 if (stage
->changed_inputs
== 0)
792 indexResult
[0] = VB
->IndexPtr
[0]->data
;
793 if (IDX
& LIGHT_TWOSIDE
)
794 indexResult
[1] = VB
->IndexPtr
[1]->data
;
796 if (IDX
& LIGHT_COLORMATERIAL
) {
797 CMcolor
= VB
->ColorPtr
[0]->data
;
798 CMstride
= VB
->ColorPtr
[0]->stride
;
801 /* loop over vertices */
804 j
++,STRIDE_F(vertex
,VSTRIDE
),STRIDE_F(normal
, NSTRIDE
), CMSTRIDE
)
806 GLfloat diffuse
[2], specular
[2];
808 struct gl_light
*light
;
810 if ( CHECK_COLOR_MATERIAL(j
) )
811 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
813 if ( CHECK_MATERIAL(j
) )
814 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
816 if ( CHECK_VALIDATE(j
) )
817 gl_validate_all_lighting_tables( ctx
);
819 diffuse
[0] = specular
[0] = 0.0F
;
821 if ( IDX
& LIGHT_TWOSIDE
) {
822 diffuse
[1] = specular
[1] = 0.0F
;
825 /* Accumulate diffuse and specular from each light source */
826 foreach (light
, &ctx
->Light
.EnabledList
) {
828 GLfloat attenuation
= 1.0F
;
829 GLfloat VP
[3]; /* unit vector from vertex to light */
830 GLfloat n_dot_VP
; /* dot product of l and n */
831 GLfloat
*h
, n_dot_h
, correction
= 1.0;
833 /* compute l and attenuation */
834 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
835 /* directional light */
836 COPY_3V(VP
, light
->_VP_inf_norm
);
839 GLfloat d
; /* distance from vertex to light */
841 SUB_3V(VP
, light
->_Position
, vertex
);
845 GLfloat invd
= 1.0F
/ d
;
846 SELF_SCALE_SCALAR_3V(VP
, invd
);
849 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
850 (light
->LinearAttenuation
+ d
*
851 light
->QuadraticAttenuation
));
853 /* spotlight attenuation */
854 if (light
->_Flags
& LIGHT_SPOT
) {
855 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
856 if (PV_dot_dir
< light
->_CosCutoff
) {
857 continue; /* this light makes no contribution */
860 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
862 GLfloat spot
= (light
->_SpotExpTable
[k
][0]
863 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
869 if (attenuation
< 1e-3)
870 continue; /* this light makes no contribution */
872 n_dot_VP
= DOT3( normal
, VP
);
874 /* which side are we lighting? */
875 if (n_dot_VP
< 0.0F
) {
876 if (!(IDX
& LIGHT_TWOSIDE
))
880 n_dot_VP
= -n_dot_VP
;
883 /* accumulate diffuse term */
884 diffuse
[side
] += n_dot_VP
* light
->_dli
* attenuation
;
887 if (ctx
->Light
.Model
.LocalViewer
) {
891 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
895 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
897 /* Strangely, disabling this addition fixes a conformance
898 * problem. If this code is enabled, l_sed.c fails.
900 /*ACC_3V(h, ctx->_EyeZDir);*/
904 h
= light
->_h_inf_norm
;
907 n_dot_h
= correction
* DOT3(normal
, h
);
908 if (n_dot_h
> 0.0F
) {
910 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
911 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
912 specular
[side
] += spec_coef
* light
->_sli
* attenuation
;
914 } /*loop over lights*/
916 /* Now compute final color index */
917 for (side
= 0 ; side
< NR_SIDES
; side
++) {
918 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
921 if (specular
[side
] > 1.0F
) {
922 index
= mat
->SpecularIndex
;
925 GLfloat d_a
= mat
->DiffuseIndex
- mat
->AmbientIndex
;
926 GLfloat s_a
= mat
->SpecularIndex
- mat
->AmbientIndex
;
928 index
= mat
->AmbientIndex
929 + diffuse
[side
] * (1.0F
-specular
[side
]) * d_a
930 + specular
[side
] * s_a
;
932 if (index
> mat
->SpecularIndex
) {
933 index
= mat
->SpecularIndex
;
936 indexResult
[side
][j
] = (GLuint
) (GLint
) index
;
940 if ( CHECK_COLOR_MATERIAL(j
) )
941 gl_update_color_material( ctx
, CMcolor
[j
] );
943 if ( CHECK_MATERIAL(j
) )
944 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
946 if ( CHECK_VALIDATE(j
) )
947 gl_validate_all_lighting_tables( ctx
);
952 static void TAG(init_light_tab
)( void )
954 _tnl_light_tab
[IDX
] = TAG(light_rgba
);
955 _tnl_light_fast_tab
[IDX
] = TAG(light_fast_rgba
);
956 _tnl_light_fast_single_tab
[IDX
] = TAG(light_fast_rgba_single
);
957 _tnl_light_spec_tab
[IDX
] = TAG(light_rgba_spec
);
958 _tnl_light_ci_tab
[IDX
] = TAG(light_ci
);
967 #undef CHECK_MATERIAL
969 #undef DO_ANOTHER_NORMAL
970 #undef REUSE_LIGHT_RESULTS
972 #undef CHECK_COLOR_MATERIAL
973 #undef CHECK_VALIDATE