fixed a CI-mode spot light conformance failure, but still not clear why
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /* $Id: t_vb_lighttmp.h,v 1.6 2001/02/14 23:00:42 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 * Authors:
28 * Brian Paul <brianp@valinux.com>
29 * Keith Whitwell <keithw@valinux.com>
30 */
31
32
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)
46 # else
47 # define CMSTRIDE 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)
54 # endif
55 #else
56 # define VSTRIDE vstride
57 # define NSTRIDE nstride
58 # define CHECK_MATERIAL(x) 0 /* no materials on array paths */
59 # define CHECK_END_VB(XX) (XX >= nr)
60 # if (IDX & LIGHT_COLORMATERIAL)
61 # define CMSTRIDE STRIDE_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 */
65 # else
66 # define CMSTRIDE 0
67 # define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */
68 # define CHECK_VALIDATE(x) (0)
69 # define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */
70 # endif
71 # define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */
72 #endif
73
74
75
76 #if (IDX & LIGHT_TWOSIDE)
77 # define NR_SIDES 2
78 #else
79 # define NR_SIDES 1
80 #endif
81
82
83
84 static void TAG(light_rgba_spec)( GLcontext *ctx,
85 struct vertex_buffer *VB,
86 struct gl_pipeline_stage *stage,
87 GLvector4f *input )
88 {
89 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
90 GLfloat (*base)[3] = ctx->Light._BaseColor;
91 const GLchan *sumA = ctx->Light._BaseAlpha;
92
93 GLuint j;
94
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;
99
100 GLchan (*CMcolor)[4];
101 GLuint CMstride;
102
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;
108
109 GLuint *flags = VB->Flag;
110 struct gl_material (*new_material)[2] = VB->Material;
111 GLuint *new_material_mask = VB->MaterialMask;
112
113 (void) flags;
114 (void) nstride;
115 (void) vstride;
116
117 if (IDX & LIGHT_COLORMATERIAL) {
118 CMcolor = (GLchan (*)[4]) VB->ColorPtr[0]->data;
119 CMstride = VB->ColorPtr[0]->stride;
120 }
121
122 VB->ColorPtr[0] = &store->LitColor[0];
123 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
124
125 if (IDX & LIGHT_TWOSIDE) {
126 VB->ColorPtr[1] = &store->LitColor[1];
127 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
128 }
129
130 /* Side-effects done, can we finish now?
131 */
132 if (stage->changed_inputs == 0)
133 return;
134
135 for ( j=0 ;
136 j<nr ;
137 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
138 {
139 GLfloat sum[2][3], spec[2][3];
140 struct gl_light *light;
141
142 if ( CHECK_COLOR_MATERIAL(j) )
143 gl_update_color_material( ctx, CMcolor[j] );
144
145 if ( CHECK_MATERIAL(j) )
146 gl_update_material( ctx, new_material[j], new_material_mask[j] );
147
148 if ( CHECK_VALIDATE(j) )
149 gl_validate_all_lighting_tables( ctx );
150
151 COPY_3V(sum[0], base[0]);
152 ZERO_3V(spec[0]);
153
154 if (IDX & LIGHT_TWOSIDE) {
155 COPY_3V(sum[1], base[1]);
156 ZERO_3V(spec[1]);
157 }
158
159 /* Add contribution from each enabled light source */
160 foreach (light, &ctx->Light.EnabledList) {
161 GLfloat n_dot_h;
162 GLfloat correction;
163 GLint side;
164 GLfloat contrib[3];
165 GLfloat attenuation;
166 GLfloat VP[3]; /* unit vector from vertex to light */
167 GLfloat n_dot_VP; /* n dot VP */
168 GLfloat *h;
169
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;
175 }
176 else {
177 GLfloat d; /* distance from vertex to light */
178
179 SUB_3V(VP, light->_Position, vertex);
180
181 d = (GLfloat) LEN_3FV( VP );
182
183 if (d > 1e-6) {
184 GLfloat invd = 1.0F / d;
185 SELF_SCALE_SCALAR_3V(VP, invd);
186 }
187
188 attenuation = 1.0F / (light->ConstantAttenuation + d *
189 (light->LinearAttenuation + d *
190 light->QuadraticAttenuation));
191
192 /* spotlight attenuation */
193 if (light->_Flags & LIGHT_SPOT) {
194 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
195
196 if (PV_dot_dir<light->_CosCutoff) {
197 continue; /* this light makes no contribution */
198 }
199 else {
200 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
201 int k = (int) x;
202 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
203 + (x-k)*light->_SpotExpTable[k][1]);
204 attenuation *= spot;
205 }
206 }
207 }
208
209
210 if (attenuation < 1e-3)
211 continue; /* this light makes no contribution */
212
213 /* Compute dot product or normal and vector from V to light pos */
214 n_dot_VP = DOT3( normal, VP );
215
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)) {
220 continue;
221 }
222 side = 1;
223 correction = -1;
224 n_dot_VP = -n_dot_VP;
225 }
226 else {
227 if (IDX & LIGHT_TWOSIDE) {
228 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
229 }
230 side = 0;
231 correction = 1;
232 }
233
234 /* diffuse term */
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 );
238
239 /* specular term - cannibalize VP... */
240 if (ctx->Light.Model.LocalViewer) {
241 GLfloat v[3];
242 COPY_3V(v, vertex);
243 NORMALIZE_3FV(v);
244 SUB_3V(VP, VP, v); /* h = VP + VPe */
245 h = VP;
246 NORMALIZE_3FV(h);
247 }
248 else if (light->_Flags & LIGHT_POSITIONAL) {
249 h = VP;
250 ACC_3V(h, ctx->_EyeZDir);
251 NORMALIZE_3FV(h);
252 }
253 else {
254 h = light->_h_inf_norm;
255 }
256
257 n_dot_h = correction * DOT3(normal, h);
258
259 if (n_dot_h > 0.0F) {
260 GLfloat spec_coef;
261 struct gl_shine_tab *tab = ctx->_ShineTable[side];
262 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
263
264 if (spec_coef > 1.0e-10) {
265 spec_coef *= attenuation;
266 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
267 light->_MatSpecular[side]);
268 }
269 }
270 } /*loop over lights*/
271
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];
275
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];
280 }
281 }
282
283 if ( CHECK_COLOR_MATERIAL(j) )
284 gl_update_color_material( ctx, CMcolor[j] );
285
286 if ( CHECK_MATERIAL(j) )
287 gl_update_material( ctx, new_material[j], new_material_mask[j] );
288
289 if ( CHECK_VALIDATE(j) )
290 gl_validate_all_lighting_tables( ctx );
291 }
292
293
294 static void TAG(light_rgba)( GLcontext *ctx,
295 struct vertex_buffer *VB,
296 struct gl_pipeline_stage *stage,
297 GLvector4f *input )
298 {
299 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
300 GLuint j;
301
302 GLfloat (*base)[3] = ctx->Light._BaseColor;
303 const GLchan *sumA = ctx->Light._BaseAlpha;
304
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;
309
310 GLchan (*CMcolor)[4];
311 GLuint CMstride;
312
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;
316
317 struct gl_material (*new_material)[2] = VB->Material;
318 GLuint *new_material_mask = VB->MaterialMask;
319 GLuint nr = VB->Count;
320
321 (void) flags;
322 (void) nstride;
323 (void) vstride;
324
325 if (IDX & LIGHT_COLORMATERIAL) {
326 CMcolor = VB->ColorPtr[0]->data;
327 CMstride = VB->ColorPtr[0]->stride;
328 }
329
330 VB->ColorPtr[0] = &store->LitColor[0];
331 if (IDX & LIGHT_TWOSIDE)
332 VB->ColorPtr[1] = &store->LitColor[1];
333
334 if (stage->changed_inputs == 0)
335 return;
336
337 for ( j=0 ;
338 j<nr ;
339 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
340 {
341 GLfloat sum[2][3];
342 struct gl_light *light;
343
344 if ( CHECK_COLOR_MATERIAL(j) )
345 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
346
347 if ( CHECK_MATERIAL(j) )
348 gl_update_material( ctx, new_material[j], new_material_mask[j] );
349
350 if ( CHECK_VALIDATE(j) )
351 gl_validate_all_lighting_tables( ctx );
352
353 COPY_3V(sum[0], base[0]);
354
355 if ( IDX & LIGHT_TWOSIDE )
356 COPY_3V(sum[1], base[1]);
357
358 /* Add contribution from each enabled light source */
359 foreach (light, &ctx->Light.EnabledList) {
360
361 GLfloat n_dot_h;
362 GLfloat correction;
363 GLint side;
364 GLfloat contrib[3];
365 GLfloat attenuation = 1.0;
366 GLfloat VP[3]; /* unit vector from vertex to light */
367 GLfloat n_dot_VP; /* n dot VP */
368 GLfloat *h;
369
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;
375 }
376 else {
377 GLfloat d; /* distance from vertex to light */
378
379
380 SUB_3V(VP, light->_Position, vertex);
381
382 d = LEN_3FV( VP );
383
384 if ( d > 1e-6) {
385 GLfloat invd = 1.0F / d;
386 SELF_SCALE_SCALAR_3V(VP, invd);
387 }
388
389 attenuation = 1.0F / (light->ConstantAttenuation + d *
390 (light->LinearAttenuation + d *
391 light->QuadraticAttenuation));
392
393 /* spotlight attenuation */
394 if (light->_Flags & LIGHT_SPOT) {
395 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
396
397 if (PV_dot_dir<light->_CosCutoff) {
398 continue; /* this light makes no contribution */
399 }
400 else {
401 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
402 int k = (int) x;
403 GLfloat spot = (light->_SpotExpTable[k][0]
404 + (x-k)*light->_SpotExpTable[k][1]);
405 attenuation *= spot;
406 }
407 }
408 }
409
410
411 if (attenuation < 1e-3)
412 continue; /* this light makes no contribution */
413
414
415 /* Compute dot product or normal and vector from V to light pos */
416 n_dot_VP = DOT3( normal, VP );
417
418 /* which side are we lighting? */
419 if (n_dot_VP < 0.0F) {
420 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
421
422 if (!(IDX & LIGHT_TWOSIDE))
423 continue;
424
425 side = 1;
426 correction = -1;
427 n_dot_VP = -n_dot_VP;
428 }
429 else {
430 if (IDX & LIGHT_TWOSIDE) {
431 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
432 }
433 side = 0;
434 correction = 1;
435 }
436
437 COPY_3V(contrib, light->_MatAmbient[side]);
438
439 /* diffuse term */
440 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
441
442 /* specular term - cannibalize VP... */
443 {
444 if (ctx->Light.Model.LocalViewer) {
445 GLfloat v[3];
446 COPY_3V(v, vertex);
447 NORMALIZE_3FV(v);
448 SUB_3V(VP, VP, v); /* h = VP + VPe */
449 h = VP;
450 NORMALIZE_3FV(h);
451 }
452 else if (light->_Flags & LIGHT_POSITIONAL) {
453 h = VP;
454 ACC_3V(h, ctx->_EyeZDir);
455 NORMALIZE_3FV(h);
456 }
457 else {
458 h = light->_h_inf_norm;
459 }
460
461 n_dot_h = correction * DOT3(normal, h);
462
463 if (n_dot_h > 0.0F)
464 {
465 GLfloat spec_coef;
466 struct gl_shine_tab *tab = ctx->_ShineTable[side];
467
468 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
469
470 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
471 light->_MatSpecular[side]);
472 }
473 }
474
475 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
476 }
477
478 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
479 Fcolor[j][3] = sumA[0];
480
481 if (IDX & LIGHT_TWOSIDE) {
482 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
483 Bcolor[j][3] = sumA[1];
484 }
485 }
486
487 if ( CHECK_COLOR_MATERIAL(j) )
488 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
489
490 if ( CHECK_MATERIAL(j) )
491 gl_update_material( ctx, new_material[j], new_material_mask[j] );
492
493 if ( CHECK_VALIDATE(j) )
494 gl_validate_all_lighting_tables( ctx );
495 }
496
497
498
499
500 /* As below, but with just a single light.
501 */
502 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
503 struct vertex_buffer *VB,
504 struct gl_pipeline_stage *stage,
505 GLvector4f *input )
506
507 {
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];
512 GLuint CMstride;
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];
518 GLuint j = 0;
519 struct gl_material (*new_material)[2] = VB->Material;
520 GLuint *new_material_mask = VB->MaterialMask;
521 GLfloat base[2][3];
522 GLuint nr = VB->Count;
523
524 (void) input; /* doesn't refer to Eye or Obj */
525 (void) flags;
526 (void) nr;
527 (void) nstride;
528
529 if (IDX & LIGHT_COLORMATERIAL) {
530 CMcolor = VB->ColorPtr[0]->data;
531 CMstride = VB->ColorPtr[0]->stride;
532 }
533
534 VB->ColorPtr[0] = &store->LitColor[0];
535 if (IDX & LIGHT_TWOSIDE)
536 VB->ColorPtr[1] = &store->LitColor[1];
537
538 if (stage->changed_inputs == 0)
539 return;
540
541 if ( CHECK_COLOR_MATERIAL(j) )
542 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
543
544 if ( CHECK_MATERIAL(j) )
545 gl_update_material( ctx, new_material[j], new_material_mask[j] );
546
547 if ( CHECK_VALIDATE(j) )
548 gl_validate_all_lighting_tables( ctx );
549
550 baseubyte[0][3] = ctx->Light._BaseAlpha[0];
551 baseubyte[1][3] = ctx->Light._BaseAlpha[1];
552
553 do {
554 /* No attenuation, so incoporate _MatAmbient into base color.
555 */
556 {
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] );
560
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]);
565 }
566 }
567
568 do {
569 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
570
571 COPY_CHAN4(Fcolor[j], baseubyte[0]);
572 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], baseubyte[1]);
573
574 if (n_dot_VP < 0.0F) {
575 if (IDX & LIGHT_TWOSIDE) {
576 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
577 GLfloat sum[3];
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) {
581 GLfloat spec;
582 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
583 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
584 }
585 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
586 }
587 } else {
588 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
589 GLfloat sum[3];
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) {
593 GLfloat spec;
594 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
595 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
596
597 }
598 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
599 }
600
601 j++;
602 STRIDE_F(normal, NSTRIDE);
603 } while (DO_ANOTHER_NORMAL(j));
604
605
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);
611 }
612
613 /* Have to recompute our base colors on material change.
614 */
615 if ( CHECK_MATERIAL(j) )
616 gl_update_material( ctx, new_material[j], new_material_mask[j] );
617
618 if ( CHECK_COLOR_MATERIAL(j) )
619 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
620
621 if ( CHECK_VALIDATE(j) )
622 gl_validate_all_lighting_tables( ctx );
623
624 } while (!CHECK_END_VB(j));
625 }
626
627
628 /* Light infinite lights
629 */
630 static void TAG(light_fast_rgba)( GLcontext *ctx,
631 struct vertex_buffer *VB,
632 struct gl_pipeline_stage *stage,
633 GLvector4f *input )
634 {
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];
640 GLuint CMstride;
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;
644 GLuint j = 0;
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;
649
650 (void) flags;
651 (void) input;
652 (void) nr;
653 (void) nstride;
654
655 if (IDX & LIGHT_COLORMATERIAL) {
656 CMcolor = VB->ColorPtr[0]->data;
657 CMstride = VB->ColorPtr[0]->stride;
658 }
659
660 VB->ColorPtr[0] = &store->LitColor[0];
661 if (IDX & LIGHT_TWOSIDE)
662 VB->ColorPtr[1] = &store->LitColor[1];
663
664 if (stage->changed_inputs == 0)
665 return;
666
667 if ( CHECK_COLOR_MATERIAL(j) )
668 gl_update_color_material( ctx, *CMcolor );
669
670 if ( CHECK_MATERIAL(j) )
671 gl_update_material( ctx, new_material[j], new_material_mask[j] );
672
673 if ( CHECK_VALIDATE(j) )
674 gl_validate_all_lighting_tables( ctx );
675
676 do {
677 do {
678 GLfloat sum[2][3];
679
680 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
681 if (IDX & LIGHT_TWOSIDE)
682 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
683
684 foreach (light, &ctx->Light.EnabledList) {
685 GLfloat n_dot_h, n_dot_VP, spec;
686
687 ACC_3V(sum[0], light->_MatAmbient[0]);
688 if (IDX & LIGHT_TWOSIDE)
689 ACC_3V(sum[1], light->_MatAmbient[1]);
690
691 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
692
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]);
701 }
702 }
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]);
711 }
712 }
713 }
714
715 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
716 Fcolor[j][3] = sumA[0];
717
718 if (IDX & LIGHT_TWOSIDE) {
719 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
720 Bcolor[j][3] = sumA[1];
721 }
722
723 j++;
724 STRIDE_F(normal, NSTRIDE);
725 } while (DO_ANOTHER_NORMAL(j));
726
727 /* Reuse the shading results while there is no change to
728 * normal or material values.
729 */
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);
735 }
736
737 if ( CHECK_COLOR_MATERIAL(j) )
738 gl_update_color_material( ctx, CMcolor[j] );
739
740 if ( CHECK_MATERIAL(j) )
741 gl_update_material( ctx, new_material[j], new_material_mask[j] );
742
743 if ( CHECK_VALIDATE(j) )
744 gl_validate_all_lighting_tables( ctx );
745
746 } while (!CHECK_END_VB(j));
747 }
748
749
750
751
752
753 /*
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
761 */
762 static void TAG(light_ci)( GLcontext *ctx,
763 struct vertex_buffer *VB,
764 struct gl_pipeline_stage *stage,
765 GLvector4f *input )
766 {
767 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
768 GLuint j;
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];
774 GLuint CMstride;
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;
780
781 (void) flags;
782 (void) nstride;
783 (void) vstride;
784
785 VB->IndexPtr[0] = &store->LitIndex[0];
786 if (IDX & LIGHT_TWOSIDE)
787 VB->IndexPtr[1] = &store->LitIndex[1];
788
789 if (stage->changed_inputs == 0)
790 return;
791
792 indexResult[0] = VB->IndexPtr[0]->data;
793 if (IDX & LIGHT_TWOSIDE)
794 indexResult[1] = VB->IndexPtr[1]->data;
795
796 if (IDX & LIGHT_COLORMATERIAL) {
797 CMcolor = VB->ColorPtr[0]->data;
798 CMstride = VB->ColorPtr[0]->stride;
799 }
800
801 /* loop over vertices */
802 for ( j=0 ;
803 j<nr ;
804 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
805 {
806 GLfloat diffuse[2], specular[2];
807 GLuint side = 0;
808 struct gl_light *light;
809
810 if ( CHECK_COLOR_MATERIAL(j) )
811 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
812
813 if ( CHECK_MATERIAL(j) )
814 gl_update_material( ctx, new_material[j], new_material_mask[j] );
815
816 if ( CHECK_VALIDATE(j) )
817 gl_validate_all_lighting_tables( ctx );
818
819 diffuse[0] = specular[0] = 0.0F;
820
821 if ( IDX & LIGHT_TWOSIDE ) {
822 diffuse[1] = specular[1] = 0.0F;
823 }
824
825 /* Accumulate diffuse and specular from each light source */
826 foreach (light, &ctx->Light.EnabledList) {
827
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;
832
833 /* compute l and attenuation */
834 if (!(light->_Flags & LIGHT_POSITIONAL)) {
835 /* directional light */
836 COPY_3V(VP, light->_VP_inf_norm);
837 }
838 else {
839 GLfloat d; /* distance from vertex to light */
840
841 SUB_3V(VP, light->_Position, vertex);
842
843 d = LEN_3FV( VP );
844 if ( d > 1e-6) {
845 GLfloat invd = 1.0F / d;
846 SELF_SCALE_SCALAR_3V(VP, invd);
847 }
848
849 attenuation = 1.0F / (light->ConstantAttenuation + d *
850 (light->LinearAttenuation + d *
851 light->QuadraticAttenuation));
852
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 */
858 }
859 else {
860 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
861 int k = (int) x;
862 GLfloat spot = (light->_SpotExpTable[k][0]
863 + (x-k)*light->_SpotExpTable[k][1]);
864 attenuation *= spot;
865 }
866 }
867 }
868
869 if (attenuation < 1e-3)
870 continue; /* this light makes no contribution */
871
872 n_dot_VP = DOT3( normal, VP );
873
874 /* which side are we lighting? */
875 if (n_dot_VP < 0.0F) {
876 if (!(IDX & LIGHT_TWOSIDE))
877 continue;
878 side = 1;
879 correction = -1;
880 n_dot_VP = -n_dot_VP;
881 }
882
883 /* accumulate diffuse term */
884 diffuse[side] += n_dot_VP * light->_dli * attenuation;
885
886 /* specular term */
887 if (ctx->Light.Model.LocalViewer) {
888 GLfloat v[3];
889 COPY_3V(v, vertex);
890 NORMALIZE_3FV(v);
891 SUB_3V(VP, VP, v); /* h = VP + VPe */
892 h = VP;
893 NORMALIZE_3FV(h);
894 }
895 else if (light->_Flags & LIGHT_POSITIONAL) {
896 h = VP;
897 /* Strangely, disabling this addition fixes a conformance
898 * problem. If this code is enabled, l_sed.c fails.
899 */
900 /*ACC_3V(h, ctx->_EyeZDir);*/
901 NORMALIZE_3FV(h);
902 }
903 else {
904 h = light->_h_inf_norm;
905 }
906
907 n_dot_h = correction * DOT3(normal, h);
908 if (n_dot_h > 0.0F) {
909 GLfloat spec_coef;
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;
913 }
914 } /*loop over lights*/
915
916 /* Now compute final color index */
917 for (side = 0 ; side < NR_SIDES ; side++) {
918 struct gl_material *mat = &ctx->Light.Material[side];
919 GLfloat index;
920
921 if (specular[side] > 1.0F) {
922 index = mat->SpecularIndex;
923 }
924 else {
925 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
926 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
927
928 index = mat->AmbientIndex
929 + diffuse[side] * (1.0F-specular[side]) * d_a
930 + specular[side] * s_a;
931
932 if (index > mat->SpecularIndex) {
933 index = mat->SpecularIndex;
934 }
935 }
936 indexResult[side][j] = (GLuint) (GLint) index;
937 }
938 } /*for vertex*/
939
940 if ( CHECK_COLOR_MATERIAL(j) )
941 gl_update_color_material( ctx, CMcolor[j] );
942
943 if ( CHECK_MATERIAL(j) )
944 gl_update_material( ctx, new_material[j], new_material_mask[j] );
945
946 if ( CHECK_VALIDATE(j) )
947 gl_validate_all_lighting_tables( ctx );
948 }
949
950
951
952 static void TAG(init_light_tab)( void )
953 {
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);
959 }
960
961
962 #undef TAG
963 #undef IDX
964 #undef NR_SIDES
965 #undef NSTRIDE
966 #undef VSTRIDE
967 #undef CHECK_MATERIAL
968 #undef CHECK_END_VB
969 #undef DO_ANOTHER_NORMAL
970 #undef REUSE_LIGHT_RESULTS
971 #undef CMSTRIDE
972 #undef CHECK_COLOR_MATERIAL
973 #undef CHECK_VALIDATE