lots of gl_*() to _mesa_*() namespace clean-up
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /* $Id: t_vb_lighttmp.h,v 1.9 2001/03/03 20:33:31 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 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
118
119 if (IDX & LIGHT_COLORMATERIAL) {
120 CMcolor = (GLchan (*)[4]) VB->ColorPtr[0]->data;
121 CMstride = VB->ColorPtr[0]->stride;
122 }
123
124 VB->ColorPtr[0] = &store->LitColor[0];
125 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
126
127 if (IDX & LIGHT_TWOSIDE) {
128 VB->ColorPtr[1] = &store->LitColor[1];
129 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
130 }
131
132 /* Side-effects done, can we finish now?
133 */
134 if (stage->changed_inputs == 0)
135 return;
136
137 for ( j=0 ;
138 j<nr ;
139 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
140 {
141 GLfloat sum[2][3], spec[2][3];
142 struct gl_light *light;
143
144 if ( CHECK_COLOR_MATERIAL(j) )
145 _mesa_update_color_material( ctx, CMcolor[j] );
146
147 if ( CHECK_MATERIAL(j) )
148 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
149
150 if ( CHECK_VALIDATE(j) )
151 _mesa_validate_all_lighting_tables( ctx );
152
153 COPY_3V(sum[0], base[0]);
154 ZERO_3V(spec[0]);
155
156 if (IDX & LIGHT_TWOSIDE) {
157 COPY_3V(sum[1], base[1]);
158 ZERO_3V(spec[1]);
159 }
160
161 /* Add contribution from each enabled light source */
162 foreach (light, &ctx->Light.EnabledList) {
163 GLfloat n_dot_h;
164 GLfloat correction;
165 GLint side;
166 GLfloat contrib[3];
167 GLfloat attenuation;
168 GLfloat VP[3]; /* unit vector from vertex to light */
169 GLfloat n_dot_VP; /* n dot VP */
170 GLfloat *h;
171
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;
177 }
178 else {
179 GLfloat d; /* distance from vertex to light */
180
181 SUB_3V(VP, light->_Position, vertex);
182
183 d = (GLfloat) LEN_3FV( VP );
184
185 if (d > 1e-6) {
186 GLfloat invd = 1.0F / d;
187 SELF_SCALE_SCALAR_3V(VP, invd);
188 }
189
190 attenuation = 1.0F / (light->ConstantAttenuation + d *
191 (light->LinearAttenuation + d *
192 light->QuadraticAttenuation));
193
194 /* spotlight attenuation */
195 if (light->_Flags & LIGHT_SPOT) {
196 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
197
198 if (PV_dot_dir<light->_CosCutoff) {
199 continue; /* this light makes no contribution */
200 }
201 else {
202 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
203 int k = (int) x;
204 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
205 + (x-k)*light->_SpotExpTable[k][1]);
206 attenuation *= spot;
207 }
208 }
209 }
210
211
212 if (attenuation < 1e-3)
213 continue; /* this light makes no contribution */
214
215 /* Compute dot product or normal and vector from V to light pos */
216 n_dot_VP = DOT3( normal, VP );
217
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)) {
222 continue;
223 }
224 side = 1;
225 correction = -1;
226 n_dot_VP = -n_dot_VP;
227 }
228 else {
229 if (IDX & LIGHT_TWOSIDE) {
230 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
231 }
232 side = 0;
233 correction = 1;
234 }
235
236 /* diffuse term */
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 );
240
241 /* specular term - cannibalize VP... */
242 if (ctx->Light.Model.LocalViewer) {
243 GLfloat v[3];
244 COPY_3V(v, vertex);
245 NORMALIZE_3FV(v);
246 SUB_3V(VP, VP, v); /* h = VP + VPe */
247 h = VP;
248 NORMALIZE_3FV(h);
249 }
250 else if (light->_Flags & LIGHT_POSITIONAL) {
251 h = VP;
252 ACC_3V(h, ctx->_EyeZDir);
253 NORMALIZE_3FV(h);
254 }
255 else {
256 h = light->_h_inf_norm;
257 }
258
259 n_dot_h = correction * DOT3(normal, h);
260
261 if (n_dot_h > 0.0F) {
262 GLfloat spec_coef;
263 struct gl_shine_tab *tab = ctx->_ShineTable[side];
264 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
265
266 if (spec_coef > 1.0e-10) {
267 spec_coef *= attenuation;
268 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
269 light->_MatSpecular[side]);
270 }
271 }
272 } /*loop over lights*/
273
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];
277
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];
282 }
283 }
284 }
285
286
287 static void TAG(light_rgba)( GLcontext *ctx,
288 struct vertex_buffer *VB,
289 struct gl_pipeline_stage *stage,
290 GLvector4f *input )
291 {
292 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
293 GLuint j;
294
295 GLfloat (*base)[3] = ctx->Light._BaseColor;
296 const GLchan *sumA = ctx->Light._BaseAlpha;
297
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;
302
303 GLchan (*CMcolor)[4];
304 GLuint CMstride;
305
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;
309
310 struct gl_material (*new_material)[2] = VB->Material;
311 GLuint *new_material_mask = VB->MaterialMask;
312 GLuint nr = VB->Count;
313
314 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
315 (void) flags;
316 (void) nstride;
317 (void) vstride;
318
319 if (IDX & LIGHT_COLORMATERIAL) {
320 CMcolor = VB->ColorPtr[0]->data;
321 CMstride = VB->ColorPtr[0]->stride;
322 }
323
324 VB->ColorPtr[0] = &store->LitColor[0];
325 if (IDX & LIGHT_TWOSIDE)
326 VB->ColorPtr[1] = &store->LitColor[1];
327
328 if (stage->changed_inputs == 0)
329 return;
330
331 for ( j=0 ;
332 j<nr ;
333 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
334 {
335 GLfloat sum[2][3];
336 struct gl_light *light;
337
338 if ( CHECK_COLOR_MATERIAL(j) )
339 _mesa_update_color_material( ctx, (GLchan *)CMcolor[j] );
340
341 if ( CHECK_MATERIAL(j) )
342 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
343
344 if ( CHECK_VALIDATE(j) )
345 _mesa_validate_all_lighting_tables( ctx );
346
347 COPY_3V(sum[0], base[0]);
348
349 if ( IDX & LIGHT_TWOSIDE )
350 COPY_3V(sum[1], base[1]);
351
352 /* Add contribution from each enabled light source */
353 foreach (light, &ctx->Light.EnabledList) {
354
355 GLfloat n_dot_h;
356 GLfloat correction;
357 GLint side;
358 GLfloat contrib[3];
359 GLfloat attenuation = 1.0;
360 GLfloat VP[3]; /* unit vector from vertex to light */
361 GLfloat n_dot_VP; /* n dot VP */
362 GLfloat *h;
363
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;
369 }
370 else {
371 GLfloat d; /* distance from vertex to light */
372
373
374 SUB_3V(VP, light->_Position, vertex);
375
376 d = LEN_3FV( VP );
377
378 if ( d > 1e-6) {
379 GLfloat invd = 1.0F / d;
380 SELF_SCALE_SCALAR_3V(VP, invd);
381 }
382
383 attenuation = 1.0F / (light->ConstantAttenuation + d *
384 (light->LinearAttenuation + d *
385 light->QuadraticAttenuation));
386
387 /* spotlight attenuation */
388 if (light->_Flags & LIGHT_SPOT) {
389 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
390
391 if (PV_dot_dir<light->_CosCutoff) {
392 continue; /* this light makes no contribution */
393 }
394 else {
395 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
396 int k = (int) x;
397 GLfloat spot = (light->_SpotExpTable[k][0]
398 + (x-k)*light->_SpotExpTable[k][1]);
399 attenuation *= spot;
400 }
401 }
402 }
403
404
405 if (attenuation < 1e-3)
406 continue; /* this light makes no contribution */
407
408
409 /* Compute dot product or normal and vector from V to light pos */
410 n_dot_VP = DOT3( normal, VP );
411
412 /* which side are we lighting? */
413 if (n_dot_VP < 0.0F) {
414 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
415
416 if (!(IDX & LIGHT_TWOSIDE))
417 continue;
418
419 side = 1;
420 correction = -1;
421 n_dot_VP = -n_dot_VP;
422 }
423 else {
424 if (IDX & LIGHT_TWOSIDE) {
425 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
426 }
427 side = 0;
428 correction = 1;
429 }
430
431 COPY_3V(contrib, light->_MatAmbient[side]);
432
433 /* diffuse term */
434 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
435
436 /* specular term - cannibalize VP... */
437 {
438 if (ctx->Light.Model.LocalViewer) {
439 GLfloat v[3];
440 COPY_3V(v, vertex);
441 NORMALIZE_3FV(v);
442 SUB_3V(VP, VP, v); /* h = VP + VPe */
443 h = VP;
444 NORMALIZE_3FV(h);
445 }
446 else if (light->_Flags & LIGHT_POSITIONAL) {
447 h = VP;
448 ACC_3V(h, ctx->_EyeZDir);
449 NORMALIZE_3FV(h);
450 }
451 else {
452 h = light->_h_inf_norm;
453 }
454
455 n_dot_h = correction * DOT3(normal, h);
456
457 if (n_dot_h > 0.0F)
458 {
459 GLfloat spec_coef;
460 struct gl_shine_tab *tab = ctx->_ShineTable[side];
461
462 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
463
464 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
465 light->_MatSpecular[side]);
466 }
467 }
468
469 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
470 }
471
472 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
473 Fcolor[j][3] = sumA[0];
474
475 if (IDX & LIGHT_TWOSIDE) {
476 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
477 Bcolor[j][3] = sumA[1];
478 }
479 }
480 }
481
482
483
484
485 /* As below, but with just a single light.
486 */
487 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
488 struct vertex_buffer *VB,
489 struct gl_pipeline_stage *stage,
490 GLvector4f *input )
491
492 {
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];
497 GLuint CMstride;
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];
503 GLuint j = 0;
504 struct gl_material (*new_material)[2] = VB->Material;
505 GLuint *new_material_mask = VB->MaterialMask;
506 GLfloat base[2][3];
507 GLuint nr = VB->Count;
508
509 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
510 (void) input; /* doesn't refer to Eye or Obj */
511 (void) flags;
512 (void) nr;
513 (void) nstride;
514
515 if (IDX & LIGHT_COLORMATERIAL) {
516 CMcolor = VB->ColorPtr[0]->data;
517 CMstride = VB->ColorPtr[0]->stride;
518 }
519
520 VB->ColorPtr[0] = &store->LitColor[0];
521 if (IDX & LIGHT_TWOSIDE)
522 VB->ColorPtr[1] = &store->LitColor[1];
523
524 if (stage->changed_inputs == 0)
525 return;
526
527 do {
528
529 if ( CHECK_COLOR_MATERIAL(j) )
530 _mesa_update_color_material( ctx, (GLchan *)CMcolor[j] );
531
532 if ( CHECK_MATERIAL(j) )
533 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
534
535 if ( CHECK_VALIDATE(j) )
536 _mesa_validate_all_lighting_tables( ctx );
537
538 baseubyte[0][3] = ctx->Light._BaseAlpha[0];
539 baseubyte[1][3] = ctx->Light._BaseAlpha[1];
540
541 /* No attenuation, so incoporate _MatAmbient into base color.
542 */
543 {
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] );
547
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]);
552 }
553 }
554
555 do {
556 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
557
558 COPY_CHAN4(Fcolor[j], baseubyte[0]);
559 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], baseubyte[1]);
560
561 if (n_dot_VP < 0.0F) {
562 if (IDX & LIGHT_TWOSIDE) {
563 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
564 GLfloat sum[3];
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) {
568 GLfloat spec;
569 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
570 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
571 }
572 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
573 }
574 } else {
575 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
576 GLfloat sum[3];
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) {
580 GLfloat spec;
581 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
582 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
583
584 }
585 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
586 }
587
588 j++;
589 STRIDE_F(normal, NSTRIDE);
590 } while (DO_ANOTHER_NORMAL(j));
591
592
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);
598 }
599
600 } while (!CHECK_END_VB(j));
601 }
602
603
604 /* Light infinite lights
605 */
606 static void TAG(light_fast_rgba)( GLcontext *ctx,
607 struct vertex_buffer *VB,
608 struct gl_pipeline_stage *stage,
609 GLvector4f *input )
610 {
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];
616 GLuint CMstride;
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;
620 GLuint j = 0;
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;
625
626 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
627 (void) flags;
628 (void) input;
629 (void) nr;
630 (void) nstride;
631
632 if (IDX & LIGHT_COLORMATERIAL) {
633 CMcolor = VB->ColorPtr[0]->data;
634 CMstride = VB->ColorPtr[0]->stride;
635 }
636
637 VB->ColorPtr[0] = &store->LitColor[0];
638 if (IDX & LIGHT_TWOSIDE)
639 VB->ColorPtr[1] = &store->LitColor[1];
640
641 if (stage->changed_inputs == 0)
642 return;
643
644 do {
645 do {
646 GLfloat sum[2][3];
647
648 if ( CHECK_COLOR_MATERIAL(j) )
649 _mesa_update_color_material( ctx, CMcolor[j] );
650
651 if ( CHECK_MATERIAL(j) )
652 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
653
654 if ( CHECK_VALIDATE(j) )
655 _mesa_validate_all_lighting_tables( ctx );
656
657
658 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
659 if (IDX & LIGHT_TWOSIDE)
660 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
661
662 foreach (light, &ctx->Light.EnabledList) {
663 GLfloat n_dot_h, n_dot_VP, spec;
664
665 ACC_3V(sum[0], light->_MatAmbient[0]);
666 if (IDX & LIGHT_TWOSIDE)
667 ACC_3V(sum[1], light->_MatAmbient[1]);
668
669 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
670
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]);
679 }
680 }
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]);
689 }
690 }
691 }
692
693 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
694 Fcolor[j][3] = sumA[0];
695
696 if (IDX & LIGHT_TWOSIDE) {
697 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
698 Bcolor[j][3] = sumA[1];
699 }
700
701 j++;
702 STRIDE_F(normal, NSTRIDE);
703 } while (DO_ANOTHER_NORMAL(j));
704
705 /* Reuse the shading results while there is no change to
706 * normal or material values.
707 */
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);
713 }
714
715 } while (!CHECK_END_VB(j));
716 }
717
718
719
720
721
722 /*
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
730 */
731 static void TAG(light_ci)( GLcontext *ctx,
732 struct vertex_buffer *VB,
733 struct gl_pipeline_stage *stage,
734 GLvector4f *input )
735 {
736 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
737 GLuint j;
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];
743 GLuint CMstride;
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;
749
750 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
751 (void) flags;
752 (void) nstride;
753 (void) vstride;
754
755 VB->IndexPtr[0] = &store->LitIndex[0];
756 if (IDX & LIGHT_TWOSIDE)
757 VB->IndexPtr[1] = &store->LitIndex[1];
758
759 if (stage->changed_inputs == 0)
760 return;
761
762 indexResult[0] = VB->IndexPtr[0]->data;
763 if (IDX & LIGHT_TWOSIDE)
764 indexResult[1] = VB->IndexPtr[1]->data;
765
766 if (IDX & LIGHT_COLORMATERIAL) {
767 CMcolor = VB->ColorPtr[0]->data;
768 CMstride = VB->ColorPtr[0]->stride;
769 }
770
771 /* loop over vertices */
772 for ( j=0 ;
773 j<nr ;
774 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
775 {
776 GLfloat diffuse[2], specular[2];
777 GLuint side = 0;
778 struct gl_light *light;
779
780 if ( CHECK_COLOR_MATERIAL(j) )
781 _mesa_update_color_material( ctx, (GLchan *)CMcolor[j] );
782
783 if ( CHECK_MATERIAL(j) )
784 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
785
786 if ( CHECK_VALIDATE(j) )
787 _mesa_validate_all_lighting_tables( ctx );
788
789 diffuse[0] = specular[0] = 0.0F;
790
791 if ( IDX & LIGHT_TWOSIDE ) {
792 diffuse[1] = specular[1] = 0.0F;
793 }
794
795 /* Accumulate diffuse and specular from each light source */
796 foreach (light, &ctx->Light.EnabledList) {
797
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;
802
803 /* compute l and attenuation */
804 if (!(light->_Flags & LIGHT_POSITIONAL)) {
805 /* directional light */
806 COPY_3V(VP, light->_VP_inf_norm);
807 }
808 else {
809 GLfloat d; /* distance from vertex to light */
810
811 SUB_3V(VP, light->_Position, vertex);
812
813 d = LEN_3FV( VP );
814 if ( d > 1e-6) {
815 GLfloat invd = 1.0F / d;
816 SELF_SCALE_SCALAR_3V(VP, invd);
817 }
818
819 attenuation = 1.0F / (light->ConstantAttenuation + d *
820 (light->LinearAttenuation + d *
821 light->QuadraticAttenuation));
822
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 */
828 }
829 else {
830 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
831 int k = (int) x;
832 GLfloat spot = (light->_SpotExpTable[k][0]
833 + (x-k)*light->_SpotExpTable[k][1]);
834 attenuation *= spot;
835 }
836 }
837 }
838
839 if (attenuation < 1e-3)
840 continue; /* this light makes no contribution */
841
842 n_dot_VP = DOT3( normal, VP );
843
844 /* which side are we lighting? */
845 if (n_dot_VP < 0.0F) {
846 if (!(IDX & LIGHT_TWOSIDE))
847 continue;
848 side = 1;
849 correction = -1;
850 n_dot_VP = -n_dot_VP;
851 }
852
853 /* accumulate diffuse term */
854 diffuse[side] += n_dot_VP * light->_dli * attenuation;
855
856 /* specular term */
857 if (ctx->Light.Model.LocalViewer) {
858 GLfloat v[3];
859 COPY_3V(v, vertex);
860 NORMALIZE_3FV(v);
861 SUB_3V(VP, VP, v); /* h = VP + VPe */
862 h = VP;
863 NORMALIZE_3FV(h);
864 }
865 else if (light->_Flags & LIGHT_POSITIONAL) {
866 h = VP;
867 /* Strangely, disabling this addition fixes a conformance
868 * problem. If this code is enabled, l_sed.c fails.
869 */
870 /*ACC_3V(h, ctx->_EyeZDir);*/
871 NORMALIZE_3FV(h);
872 }
873 else {
874 h = light->_h_inf_norm;
875 }
876
877 n_dot_h = correction * DOT3(normal, h);
878 if (n_dot_h > 0.0F) {
879 GLfloat spec_coef;
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;
883 }
884 } /*loop over lights*/
885
886 /* Now compute final color index */
887 for (side = 0 ; side < NR_SIDES ; side++) {
888 struct gl_material *mat = &ctx->Light.Material[side];
889 GLfloat index;
890
891 if (specular[side] > 1.0F) {
892 index = mat->SpecularIndex;
893 }
894 else {
895 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
896 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
897
898 index = mat->AmbientIndex
899 + diffuse[side] * (1.0F-specular[side]) * d_a
900 + specular[side] * s_a;
901
902 if (index > mat->SpecularIndex) {
903 index = mat->SpecularIndex;
904 }
905 }
906 indexResult[side][j] = (GLuint) (GLint) index;
907 }
908 } /*for vertex*/
909 }
910
911
912
913 static void TAG(init_light_tab)( void )
914 {
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);
920 }
921
922
923 #undef TAG
924 #undef IDX
925 #undef NR_SIDES
926 #undef NSTRIDE
927 #undef VSTRIDE
928 #undef CHECK_MATERIAL
929 #undef CHECK_END_VB
930 #undef DO_ANOTHER_NORMAL
931 #undef REUSE_LIGHT_RESULTS
932 #undef CMSTRIDE
933 #undef CHECK_COLOR_MATERIAL
934 #undef CHECK_VALIDATE