1 /* $Id: t_vb_lighttmp.h,v 1.1 2000/12/26 05:09:33 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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_4UB(CMcolor, (4 * sizeof(GLubyte)))
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_4UB(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 FLOAT_RGB_TO_CHAN_RGB( Fcolor
[j
], sum
[0] );
273 FLOAT_RGB_TO_CHAN_RGB( Fspec
[j
], spec
[0] );
274 Fcolor
[j
][3] = sumA
[0];
276 if (IDX
& LIGHT_TWOSIDE
) {
277 FLOAT_RGB_TO_CHAN_RGB( Bcolor
[j
], sum
[1] );
278 FLOAT_RGB_TO_CHAN_RGB( 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 GLubyte (*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 FLOAT_RGB_TO_CHAN_RGB( Fcolor
[j
], sum
[0] );
479 Fcolor
[j
][3] = sumA
[0];
481 if (IDX
& LIGHT_TWOSIDE
) {
482 FLOAT_RGB_TO_CHAN_RGB( 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 GLubyte (*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 FLOAT_RGB_TO_CHAN_RGB( 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 FLOAT_RGB_TO_CHAN_RGB( 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 FLOAT_RGB_TO_CHAN_RGB(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 FLOAT_RGB_TO_CHAN_RGB(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 GLubyte (*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 ( CHECK_COLOR_MATERIAL(j
) )
665 gl_update_color_material( ctx
, *CMcolor
);
667 if ( CHECK_MATERIAL(j
) )
668 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
670 if ( CHECK_VALIDATE(j
) )
671 gl_validate_all_lighting_tables( ctx
);
677 COPY_3V(sum
[0], ctx
->Light
._BaseColor
[0]);
678 if (IDX
& LIGHT_TWOSIDE
)
679 COPY_3V(sum
[1], ctx
->Light
._BaseColor
[1]);
681 foreach (light
, &ctx
->Light
.EnabledList
) {
682 GLfloat n_dot_h
, n_dot_VP
, spec
;
684 ACC_3V(sum
[0], light
->_MatAmbient
[0]);
685 if (IDX
& LIGHT_TWOSIDE
)
686 ACC_3V(sum
[1], light
->_MatAmbient
[1]);
688 n_dot_VP
= DOT3(normal
, light
->_VP_inf_norm
);
690 if (n_dot_VP
> 0.0F
) {
691 ACC_SCALE_SCALAR_3V(sum
[0], n_dot_VP
, light
->_MatDiffuse
[0]);
692 n_dot_h
= DOT3(normal
, light
->_h_inf_norm
);
693 if (n_dot_h
> 0.0F
) {
694 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[0];
695 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
696 ACC_SCALE_SCALAR_3V( sum
[0], spec
,
697 light
->_MatSpecular
[0]);
700 else if (IDX
& LIGHT_TWOSIDE
) {
701 ACC_SCALE_SCALAR_3V(sum
[1], -n_dot_VP
, light
->_MatDiffuse
[1]);
702 n_dot_h
= -DOT3(normal
, light
->_h_inf_norm
);
703 if (n_dot_h
> 0.0F
) {
704 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[1];
705 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec
);
706 ACC_SCALE_SCALAR_3V( sum
[1], spec
,
707 light
->_MatSpecular
[1]);
712 FLOAT_RGB_TO_CHAN_RGB( Fcolor
[j
], sum
[0] );
713 Fcolor
[j
][3] = sumA
[0];
715 if (IDX
& LIGHT_TWOSIDE
) {
716 FLOAT_RGB_TO_CHAN_RGB( Bcolor
[j
], sum
[1] );
717 Bcolor
[j
][3] = sumA
[1];
721 STRIDE_F(normal
, NSTRIDE
);
722 } while (DO_ANOTHER_NORMAL(j
));
724 /* Reuse the shading results while there is no change to
725 * normal or material values.
727 for ( ; REUSE_LIGHT_RESULTS(j
) ; j
++ ) {
728 COPY_CHAN4(Fcolor
[j
], Fcolor
[j
-1]);
729 if (IDX
& LIGHT_TWOSIDE
)
730 COPY_CHAN4(Bcolor
[j
], Bcolor
[j
-1]);
731 STRIDE_F(normal
, NSTRIDE
);
734 if ( CHECK_COLOR_MATERIAL(j
) )
735 gl_update_color_material( ctx
, CMcolor
[j
] );
737 if ( CHECK_MATERIAL(j
) )
738 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
740 if ( CHECK_VALIDATE(j
) )
741 gl_validate_all_lighting_tables( ctx
);
743 } while (!CHECK_END_VB(j
));
751 * Use current lighting/material settings to compute the color indexes
752 * for an array of vertices.
753 * Input: n - number of vertices to light
754 * side - 0=use front material, 1=use back material
755 * vertex - array of [n] vertex position in eye coordinates
756 * normal - array of [n] surface normal vector
757 * Output: indexResult - resulting array of [n] color indexes
759 static void TAG(light_ci
)( GLcontext
*ctx
,
760 struct vertex_buffer
*VB
,
761 struct gl_pipeline_stage
*stage
,
764 struct light_stage_data
*store
= LIGHT_STAGE_DATA(stage
);
766 GLuint vstride
= input
->stride
;
767 const GLfloat
*vertex
= (GLfloat
*) input
->data
;
768 GLuint nstride
= VB
->NormalPtr
->stride
;
769 const GLfloat
*normal
= (GLfloat
*)VB
->NormalPtr
->data
;
770 GLubyte (*CMcolor
)[4];
772 GLuint
*flags
= VB
->Flag
;
773 GLuint
*indexResult
[2];
774 struct gl_material (*new_material
)[2] = VB
->Material
;
775 GLuint
*new_material_mask
= VB
->MaterialMask
;
776 GLuint nr
= VB
->Count
;
782 VB
->IndexPtr
[0] = &store
->LitIndex
[0];
783 if (IDX
& LIGHT_TWOSIDE
)
784 VB
->IndexPtr
[1] = &store
->LitIndex
[1];
786 indexResult
[0] = VB
->IndexPtr
[0]->data
;
787 indexResult
[1] = VB
->IndexPtr
[1]->data
;
789 if (IDX
& LIGHT_COLORMATERIAL
) {
790 CMcolor
= VB
->ColorPtr
[0]->data
;
791 CMstride
= VB
->ColorPtr
[0]->stride
;
794 /* loop over vertices */
797 j
++,STRIDE_F(vertex
,VSTRIDE
),STRIDE_F(normal
, NSTRIDE
), CMSTRIDE
)
799 GLfloat diffuse
[2], specular
[2];
801 struct gl_light
*light
;
803 if ( CHECK_COLOR_MATERIAL(j
) )
804 gl_update_color_material( ctx
, (GLchan
*)CMcolor
[j
] );
806 if ( CHECK_MATERIAL(j
) )
807 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
809 if ( CHECK_VALIDATE(j
) )
810 gl_validate_all_lighting_tables( ctx
);
812 diffuse
[0] = specular
[0] = 0.0F
;
814 if ( IDX
& LIGHT_TWOSIDE
) {
815 diffuse
[1] = specular
[1] = 0.0F
;
818 /* Accumulate diffuse and specular from each light source */
819 foreach (light
, &ctx
->Light
.EnabledList
) {
821 GLfloat attenuation
= 1.0F
;
822 GLfloat VP
[3]; /* unit vector from vertex to light */
823 GLfloat n_dot_VP
; /* dot product of l and n */
824 GLfloat
*h
, n_dot_h
, correction
= 1.0;
826 /* compute l and attenuation */
827 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
828 /* directional light */
829 COPY_3V(VP
, light
->_VP_inf_norm
);
832 GLfloat d
; /* distance from vertex to light */
834 SUB_3V(VP
, light
->_Position
, vertex
);
838 GLfloat invd
= 1.0F
/ d
;
839 SELF_SCALE_SCALAR_3V(VP
, invd
);
842 attenuation
= 1.0F
/ (light
->ConstantAttenuation
+ d
*
843 (light
->LinearAttenuation
+ d
*
844 light
->QuadraticAttenuation
));
846 /* spotlight attenuation */
847 if (light
->_Flags
& LIGHT_SPOT
) {
848 GLfloat PV_dot_dir
= - DOT3(VP
, light
->_NormDirection
);
849 if (PV_dot_dir
<light
->_CosCutoff
) {
850 continue; /* this light makes no contribution */
853 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
855 GLfloat spot
= (light
->_SpotExpTable
[k
][0]
856 + (x
-k
)*light
->_SpotExpTable
[k
][1]);
862 if (attenuation
< 1e-3)
863 continue; /* this light makes no contribution */
865 n_dot_VP
= DOT3( normal
, VP
);
867 /* which side are we lighting? */
868 if (n_dot_VP
< 0.0F
) {
869 if (!(IDX
& LIGHT_TWOSIDE
))
873 n_dot_VP
= -n_dot_VP
;
876 /* accumulate diffuse term */
877 diffuse
[side
] += n_dot_VP
* light
->_dli
* attenuation
;
880 if (ctx
->Light
.Model
.LocalViewer
) {
884 SUB_3V(VP
, VP
, v
); /* h = VP + VPe */
888 else if (light
->_Flags
& LIGHT_POSITIONAL
) {
890 ACC_3V(h
, ctx
->_EyeZDir
);
894 h
= light
->_h_inf_norm
;
897 n_dot_h
= correction
* DOT3(normal
, h
);
902 struct gl_shine_tab
*tab
= ctx
->_ShineTable
[side
];
903 GET_SHINE_TAB_ENTRY( tab
, n_dot_h
, spec_coef
);
904 specular
[side
] += spec_coef
* light
->_sli
* attenuation
;
906 } /*loop over lights*/
908 /* Now compute final color index */
909 for (side
= 0 ; side
< NR_SIDES
; side
++) {
910 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
913 if (specular
[side
] > 1.0F
) {
914 index
= mat
->SpecularIndex
;
917 GLfloat d_a
= mat
->DiffuseIndex
- mat
->AmbientIndex
;
918 GLfloat s_a
= mat
->SpecularIndex
- mat
->AmbientIndex
;
920 index
= mat
->AmbientIndex
921 + diffuse
[side
] * (1.0F
-specular
[side
]) * d_a
922 + specular
[side
] * s_a
;
924 if (index
> mat
->SpecularIndex
) {
925 index
= mat
->SpecularIndex
;
928 indexResult
[side
][j
] = (GLuint
) (GLint
) index
;
932 if ( CHECK_COLOR_MATERIAL(j
) )
933 gl_update_color_material( ctx
, CMcolor
[j
] );
935 if ( CHECK_MATERIAL(j
) )
936 gl_update_material( ctx
, new_material
[j
], new_material_mask
[j
] );
938 if ( CHECK_VALIDATE(j
) )
939 gl_validate_all_lighting_tables( ctx
);
944 static void TAG(init_light_tab
)( void )
946 _tnl_light_tab
[IDX
] = TAG(light_rgba
);
947 _tnl_light_fast_tab
[IDX
] = TAG(light_fast_rgba
);
948 _tnl_light_fast_single_tab
[IDX
] = TAG(light_fast_rgba_single
);
949 _tnl_light_spec_tab
[IDX
] = TAG(light_rgba_spec
);
950 _tnl_light_ci_tab
[IDX
] = TAG(light_ci
);
959 #undef CHECK_MATERIAL
961 #undef DO_ANOTHER_NORMAL
962 #undef REUSE_LIGHT_RESULTS
964 #undef CHECK_COLOR_MATERIAL
965 #undef CHECK_VALIDATE