more warning fixes (Karl Schultz)
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /* $Id: t_vb_lighttmp.h,v 1.18 2001/09/14 21:30: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_F(CMcolor, CMstride)
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 (void)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_F(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 (void)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 GLchan sumA[2];
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 GLfloat *CMcolor;
101 GLuint CMstride;
102
103 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
104 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
105 GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
106 GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
107 GLchan (*spec[2])[4];
108
109 GLuint nr = VB->Count;
110 GLuint *flags = VB->Flag;
111 struct gl_material (*new_material)[2] = VB->Material;
112 GLuint *new_material_mask = VB->MaterialMask;
113
114 (void) flags;
115 (void) nstride;
116 (void) vstride;
117
118
119
120 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
121
122 spec[0] = Fspec;
123 spec[1] = Bspec;
124
125 if (IDX & LIGHT_COLORMATERIAL) {
126 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
127 VB->ColorPtr[0]->Size != 4)
128 import_color_material( ctx, stage );
129
130 CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
131 CMstride = VB->ColorPtr[0]->StrideB;
132 }
133
134 VB->ColorPtr[0] = &store->LitColor[0];
135 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
136 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
137
138 if (IDX & LIGHT_TWOSIDE) {
139 VB->ColorPtr[1] = &store->LitColor[1];
140 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
141 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
142 }
143
144 /* Side-effects done, can we finish now?
145 */
146 if (stage->changed_inputs == 0)
147 return;
148
149 for ( j=0 ;
150 j<nr ;
151 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
152 {
153 GLfloat sum[2][3], spec[2][3];
154 struct gl_light *light;
155
156 if ( CHECK_COLOR_MATERIAL(j) )
157 _mesa_update_color_material( ctx, CMcolor );
158
159 if ( CHECK_MATERIAL(j) )
160 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
161
162 if ( CHECK_VALIDATE(j) ) {
163 _mesa_validate_all_lighting_tables( ctx );
164 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
165 if (IDX & LIGHT_TWOSIDE)
166 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
167 }
168
169 COPY_3V(sum[0], base[0]);
170 ZERO_3V(spec[0]);
171
172 if (IDX & LIGHT_TWOSIDE) {
173 COPY_3V(sum[1], base[1]);
174 ZERO_3V(spec[1]);
175 }
176
177 /* Add contribution from each enabled light source */
178 foreach (light, &ctx->Light.EnabledList) {
179 GLfloat n_dot_h;
180 GLfloat correction;
181 GLint side;
182 GLfloat contrib[3];
183 GLfloat attenuation;
184 GLfloat VP[3]; /* unit vector from vertex to light */
185 GLfloat n_dot_VP; /* n dot VP */
186 GLfloat *h;
187
188 /* compute VP and attenuation */
189 if (!(light->_Flags & LIGHT_POSITIONAL)) {
190 /* directional light */
191 COPY_3V(VP, light->_VP_inf_norm);
192 attenuation = light->_VP_inf_spot_attenuation;
193 }
194 else {
195 GLfloat d; /* distance from vertex to light */
196
197 SUB_3V(VP, light->_Position, vertex);
198
199 d = (GLfloat) LEN_3FV( VP );
200
201 if (d > 1e-6) {
202 GLfloat invd = 1.0F / d;
203 SELF_SCALE_SCALAR_3V(VP, invd);
204 }
205
206 attenuation = 1.0F / (light->ConstantAttenuation + d *
207 (light->LinearAttenuation + d *
208 light->QuadraticAttenuation));
209
210 /* spotlight attenuation */
211 if (light->_Flags & LIGHT_SPOT) {
212 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
213
214 if (PV_dot_dir<light->_CosCutoff) {
215 continue; /* this light makes no contribution */
216 }
217 else {
218 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
219 GLint k = (GLint) x;
220 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
221 + (x-k)*light->_SpotExpTable[k][1]);
222 attenuation *= spot;
223 }
224 }
225 }
226
227 if (attenuation < 1e-3)
228 continue; /* this light makes no contribution */
229
230 /* Compute dot product or normal and vector from V to light pos */
231 n_dot_VP = DOT3( normal, VP );
232
233 /* Which side gets the diffuse & specular terms? */
234 if (n_dot_VP < 0.0F) {
235 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
236 if (!(IDX & LIGHT_TWOSIDE)) {
237 continue;
238 }
239 side = 1;
240 correction = -1;
241 n_dot_VP = -n_dot_VP;
242 }
243 else {
244 if (IDX & LIGHT_TWOSIDE) {
245 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
246 }
247 side = 0;
248 correction = 1;
249 }
250
251 /* diffuse term */
252 COPY_3V(contrib, light->_MatAmbient[side]);
253 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
254 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
255
256 /* specular term - cannibalize VP... */
257 if (ctx->Light.Model.LocalViewer) {
258 GLfloat v[3];
259 COPY_3V(v, vertex);
260 NORMALIZE_3FV(v);
261 SUB_3V(VP, VP, v); /* h = VP + VPe */
262 h = VP;
263 NORMALIZE_3FV(h);
264 }
265 else if (light->_Flags & LIGHT_POSITIONAL) {
266 h = VP;
267 ACC_3V(h, ctx->_EyeZDir);
268 NORMALIZE_3FV(h);
269 }
270 else {
271 h = light->_h_inf_norm;
272 }
273
274 n_dot_h = correction * DOT3(normal, h);
275
276 if (n_dot_h > 0.0F) {
277 GLfloat spec_coef;
278 struct gl_shine_tab *tab = ctx->_ShineTable[side];
279 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
280
281 if (spec_coef > 1.0e-10) {
282 spec_coef *= attenuation;
283 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
284 light->_MatSpecular[side]);
285 }
286 }
287 } /*loop over lights*/
288
289 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
290 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
291 Fcolor[j][3] = sumA[0];
292
293 if (IDX & LIGHT_TWOSIDE) {
294 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
295 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
296 Bcolor[j][3] = sumA[1];
297 }
298 }
299 }
300
301
302 static void TAG(light_rgba)( GLcontext *ctx,
303 struct vertex_buffer *VB,
304 struct gl_pipeline_stage *stage,
305 GLvector4f *input )
306 {
307 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
308 GLuint j;
309
310 GLfloat (*base)[3] = ctx->Light._BaseColor;
311 GLchan sumA[2];
312
313 GLuint vstride = input->stride;
314 const GLfloat *vertex = (GLfloat *) input->data;
315 GLuint nstride = VB->NormalPtr->stride;
316 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
317
318 GLfloat *CMcolor;
319 GLuint CMstride;
320
321 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
322 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
323 GLchan (*color[2])[4];
324 GLuint *flags = VB->Flag;
325
326 struct gl_material (*new_material)[2] = VB->Material;
327 GLuint *new_material_mask = VB->MaterialMask;
328 GLuint nr = VB->Count;
329
330 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
331 (void) flags;
332 (void) nstride;
333 (void) vstride;
334
335 color[0] = Fcolor;
336 color[1] = Bcolor;
337
338 if (IDX & LIGHT_COLORMATERIAL) {
339 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
340 VB->ColorPtr[0]->Size != 4)
341 import_color_material( ctx, stage );
342
343 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
344 CMstride = VB->ColorPtr[0]->StrideB;
345 }
346
347 VB->ColorPtr[0] = &store->LitColor[0];
348 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
349
350 if (IDX & LIGHT_TWOSIDE) {
351 VB->ColorPtr[1] = &store->LitColor[1];
352 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
353 }
354
355 if (stage->changed_inputs == 0)
356 return;
357
358 for ( j=0 ;
359 j<nr ;
360 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
361 {
362 GLfloat sum[2][3];
363 struct gl_light *light;
364
365 if ( CHECK_COLOR_MATERIAL(j) )
366 _mesa_update_color_material( ctx, CMcolor );
367
368 if ( CHECK_MATERIAL(j) )
369 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
370
371 if ( CHECK_VALIDATE(j) ) {
372 _mesa_validate_all_lighting_tables( ctx );
373 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
374 if (IDX & LIGHT_TWOSIDE)
375 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
376 }
377
378 COPY_3V(sum[0], base[0]);
379
380 if ( IDX & LIGHT_TWOSIDE )
381 COPY_3V(sum[1], base[1]);
382
383 /* Add contribution from each enabled light source */
384 foreach (light, &ctx->Light.EnabledList) {
385
386 GLfloat n_dot_h;
387 GLfloat correction;
388 GLint side;
389 GLfloat contrib[3];
390 GLfloat attenuation = 1.0;
391 GLfloat VP[3]; /* unit vector from vertex to light */
392 GLfloat n_dot_VP; /* n dot VP */
393 GLfloat *h;
394
395 /* compute VP and attenuation */
396 if (!(light->_Flags & LIGHT_POSITIONAL)) {
397 /* directional light */
398 COPY_3V(VP, light->_VP_inf_norm);
399 attenuation = light->_VP_inf_spot_attenuation;
400 }
401 else {
402 GLfloat d; /* distance from vertex to light */
403
404
405 SUB_3V(VP, light->_Position, vertex);
406
407 d = (GLfloat) LEN_3FV( VP );
408
409 if ( d > 1e-6) {
410 GLfloat invd = 1.0F / d;
411 SELF_SCALE_SCALAR_3V(VP, invd);
412 }
413
414 attenuation = 1.0F / (light->ConstantAttenuation + d *
415 (light->LinearAttenuation + d *
416 light->QuadraticAttenuation));
417
418 /* spotlight attenuation */
419 if (light->_Flags & LIGHT_SPOT) {
420 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
421
422 if (PV_dot_dir<light->_CosCutoff) {
423 continue; /* this light makes no contribution */
424 }
425 else {
426 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
427 GLint k = (GLint) x;
428 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
429 + (x-k)*light->_SpotExpTable[k][1]);
430 attenuation *= spot;
431 }
432 }
433 }
434
435 if (attenuation < 1e-3)
436 continue; /* this light makes no contribution */
437
438 /* Compute dot product or normal and vector from V to light pos */
439 n_dot_VP = DOT3( normal, VP );
440
441 /* which side are we lighting? */
442 if (n_dot_VP < 0.0F) {
443 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
444
445 if (!(IDX & LIGHT_TWOSIDE))
446 continue;
447
448 side = 1;
449 correction = -1;
450 n_dot_VP = -n_dot_VP;
451 }
452 else {
453 if (IDX & LIGHT_TWOSIDE) {
454 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
455 }
456 side = 0;
457 correction = 1;
458 }
459
460 COPY_3V(contrib, light->_MatAmbient[side]);
461
462 /* diffuse term */
463 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
464
465 /* specular term - cannibalize VP... */
466 {
467 if (ctx->Light.Model.LocalViewer) {
468 GLfloat v[3];
469 COPY_3V(v, vertex);
470 NORMALIZE_3FV(v);
471 SUB_3V(VP, VP, v); /* h = VP + VPe */
472 h = VP;
473 NORMALIZE_3FV(h);
474 }
475 else if (light->_Flags & LIGHT_POSITIONAL) {
476 h = VP;
477 ACC_3V(h, ctx->_EyeZDir);
478 NORMALIZE_3FV(h);
479 }
480 else {
481 h = light->_h_inf_norm;
482 }
483
484 n_dot_h = correction * DOT3(normal, h);
485
486 if (n_dot_h > 0.0F)
487 {
488 GLfloat spec_coef;
489 struct gl_shine_tab *tab = ctx->_ShineTable[side];
490
491 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
492
493 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
494 light->_MatSpecular[side]);
495 }
496 }
497
498 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
499 }
500
501 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
502 Fcolor[j][3] = sumA[0];
503
504 if (IDX & LIGHT_TWOSIDE) {
505 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
506 Bcolor[j][3] = sumA[1];
507 }
508 }
509 }
510
511
512
513
514 /* As below, but with just a single light.
515 */
516 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
517 struct vertex_buffer *VB,
518 struct gl_pipeline_stage *stage,
519 GLvector4f *input )
520
521 {
522 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
523 GLuint nstride = VB->NormalPtr->stride;
524 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
525 GLfloat *CMcolor;
526 GLuint CMstride;
527 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
528 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
529 struct gl_light *light = ctx->Light.EnabledList.next;
530 GLuint *flags = VB->Flag;
531 GLchan basechan[2][4];
532 GLuint j = 0;
533 struct gl_material (*new_material)[2] = VB->Material;
534 GLuint *new_material_mask = VB->MaterialMask;
535 GLfloat base[2][3];
536 GLuint nr = VB->Count;
537
538 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
539 (void) input; /* doesn't refer to Eye or Obj */
540 (void) flags;
541 (void) nr;
542 (void) nstride;
543
544 if (IDX & LIGHT_COLORMATERIAL) {
545 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
546 VB->ColorPtr[0]->Size != 4)
547 import_color_material( ctx, stage );
548
549 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
550 CMstride = VB->ColorPtr[0]->StrideB;
551 }
552
553 VB->ColorPtr[0] = &store->LitColor[0];
554 if (IDX & LIGHT_TWOSIDE)
555 VB->ColorPtr[1] = &store->LitColor[1];
556
557 if (stage->changed_inputs == 0)
558 return;
559
560 do {
561
562 if ( CHECK_COLOR_MATERIAL(j) ) {
563 /* fprintf(stderr, "colormaterial at %d (%p)\n", j, CMcolor); */
564 _mesa_update_color_material( ctx, CMcolor );
565 }
566
567 if ( CHECK_MATERIAL(j) )
568 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
569
570 if ( CHECK_VALIDATE(j) )
571 _mesa_validate_all_lighting_tables( ctx );
572
573
574 /* No attenuation, so incoporate _MatAmbient into base color.
575 */
576 COPY_3V(base[0], light->_MatAmbient[0]);
577 ACC_3V(base[0], ctx->Light._BaseColor[0] );
578 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
579 UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3],
580 ctx->Light.Material[0].Diffuse[3]);
581
582 if (IDX & LIGHT_TWOSIDE) {
583 COPY_3V(base[1], light->_MatAmbient[1]);
584 ACC_3V(base[1], ctx->Light._BaseColor[1]);
585 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
586 UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3],
587 ctx->Light.Material[1].Diffuse[3]);
588 }
589
590 do {
591 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
592
593 /* if (j < 5) */
594 /* fprintf(stderr, "light normal %d: %f %f %f\n", */
595 /* j, */
596 /* normal[0], */
597 /* normal[1], */
598 /* normal[2]); */
599
600 if (n_dot_VP < 0.0F) {
601 if (IDX & LIGHT_TWOSIDE) {
602 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
603 GLfloat sum[3];
604 COPY_3V(sum, base[1]);
605 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
606 if (n_dot_h > 0.0F) {
607 GLfloat spec;
608 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
609 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
610 }
611 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
612 }
613 COPY_CHAN4(Fcolor[j], basechan[0]);
614 } else {
615 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
616 GLfloat sum[3];
617 COPY_3V(sum, base[0]);
618 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
619 if (n_dot_h > 0.0F) {
620 GLfloat spec;
621 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
622 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
623
624 }
625 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
626 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
627 }
628
629 j++;
630 CMSTRIDE;
631 STRIDE_F(normal, NSTRIDE);
632 } while (DO_ANOTHER_NORMAL(j));
633
634
635 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
636 {
637 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
638 if (IDX & LIGHT_TWOSIDE)
639 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
640
641 /* if (j < 5) */
642 /* fprintf(stderr, "skip normal %d: %f %f %f\n", */
643 /* j, */
644 /* normal[0], */
645 /* normal[1], */
646 /* normal[2]); */
647
648 }
649
650 } while (!CHECK_END_VB(j));
651 }
652
653
654 /* Light infinite lights
655 */
656 static void TAG(light_fast_rgba)( GLcontext *ctx,
657 struct vertex_buffer *VB,
658 struct gl_pipeline_stage *stage,
659 GLvector4f *input )
660 {
661 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
662 GLchan sumA[2];
663 GLuint nstride = VB->NormalPtr->stride;
664 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
665 GLfloat *CMcolor;
666 GLuint CMstride;
667 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
668 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
669 GLuint *flags = VB->Flag;
670 GLuint j = 0;
671 struct gl_material (*new_material)[2] = VB->Material;
672 GLuint *new_material_mask = VB->MaterialMask;
673 GLuint nr = VB->Count;
674 struct gl_light *light;
675
676 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
677 (void) flags;
678 (void) input;
679 (void) nr;
680 (void) nstride;
681
682 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
683 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
684
685 if (IDX & LIGHT_COLORMATERIAL) {
686 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
687 VB->ColorPtr[0]->Size != 4)
688 import_color_material( ctx, stage );
689
690 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
691 CMstride = VB->ColorPtr[0]->StrideB;
692 }
693
694 VB->ColorPtr[0] = &store->LitColor[0];
695 if (IDX & LIGHT_TWOSIDE)
696 VB->ColorPtr[1] = &store->LitColor[1];
697
698 if (stage->changed_inputs == 0)
699 return;
700
701 do {
702 do {
703 GLfloat sum[2][3];
704
705 if ( CHECK_COLOR_MATERIAL(j) )
706 _mesa_update_color_material( ctx, CMcolor );
707
708 if ( CHECK_MATERIAL(j) )
709 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
710
711 if ( CHECK_VALIDATE(j) ) {
712 _mesa_validate_all_lighting_tables( ctx );
713 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
714 if (IDX & LIGHT_TWOSIDE)
715 UNCLAMPED_FLOAT_TO_CHAN(sumA[1],
716 ctx->Light.Material[1].Diffuse[3]);
717 }
718
719
720 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
721 if (IDX & LIGHT_TWOSIDE)
722 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
723
724 foreach (light, &ctx->Light.EnabledList) {
725 GLfloat n_dot_h, n_dot_VP, spec;
726
727 ACC_3V(sum[0], light->_MatAmbient[0]);
728 if (IDX & LIGHT_TWOSIDE)
729 ACC_3V(sum[1], light->_MatAmbient[1]);
730
731 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
732
733 if (n_dot_VP > 0.0F) {
734 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
735 n_dot_h = DOT3(normal, light->_h_inf_norm);
736 if (n_dot_h > 0.0F) {
737 struct gl_shine_tab *tab = ctx->_ShineTable[0];
738 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
739 ACC_SCALE_SCALAR_3V( sum[0], spec,
740 light->_MatSpecular[0]);
741 }
742 }
743 else if (IDX & LIGHT_TWOSIDE) {
744 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
745 n_dot_h = -DOT3(normal, light->_h_inf_norm);
746 if (n_dot_h > 0.0F) {
747 struct gl_shine_tab *tab = ctx->_ShineTable[1];
748 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
749 ACC_SCALE_SCALAR_3V( sum[1], spec,
750 light->_MatSpecular[1]);
751 }
752 }
753 }
754
755 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
756 Fcolor[j][3] = sumA[0];
757
758 if (IDX & LIGHT_TWOSIDE) {
759 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
760 Bcolor[j][3] = sumA[1];
761 }
762
763 j++;
764 CMSTRIDE;
765 STRIDE_F(normal, NSTRIDE);
766 } while (DO_ANOTHER_NORMAL(j));
767
768 /* Reuse the shading results while there is no change to
769 * normal or material values.
770 */
771 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
772 {
773 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
774 if (IDX & LIGHT_TWOSIDE)
775 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
776 }
777
778 } while (!CHECK_END_VB(j));
779 }
780
781
782
783
784
785 /*
786 * Use current lighting/material settings to compute the color indexes
787 * for an array of vertices.
788 * Input: n - number of vertices to light
789 * side - 0=use front material, 1=use back material
790 * vertex - array of [n] vertex position in eye coordinates
791 * normal - array of [n] surface normal vector
792 * Output: indexResult - resulting array of [n] color indexes
793 */
794 static void TAG(light_ci)( GLcontext *ctx,
795 struct vertex_buffer *VB,
796 struct gl_pipeline_stage *stage,
797 GLvector4f *input )
798 {
799 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
800 GLuint j;
801 GLuint vstride = input->stride;
802 const GLfloat *vertex = (GLfloat *) input->data;
803 GLuint nstride = VB->NormalPtr->stride;
804 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
805 GLfloat *CMcolor;
806 GLuint CMstride;
807 GLuint *flags = VB->Flag;
808 GLuint *indexResult[2];
809 struct gl_material (*new_material)[2] = VB->Material;
810 GLuint *new_material_mask = VB->MaterialMask;
811 GLuint nr = VB->Count;
812
813 /* fprintf(stderr, "%s\n", __FUNCTION__ ); */
814 (void) flags;
815 (void) nstride;
816 (void) vstride;
817
818 VB->IndexPtr[0] = &store->LitIndex[0];
819 if (IDX & LIGHT_TWOSIDE)
820 VB->IndexPtr[1] = &store->LitIndex[1];
821
822 if (stage->changed_inputs == 0)
823 return;
824
825 indexResult[0] = VB->IndexPtr[0]->data;
826 if (IDX & LIGHT_TWOSIDE)
827 indexResult[1] = VB->IndexPtr[1]->data;
828
829 if (IDX & LIGHT_COLORMATERIAL) {
830 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
831 VB->ColorPtr[0]->Size != 4)
832 import_color_material( ctx, stage );
833
834 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
835 CMstride = VB->ColorPtr[0]->StrideB;
836 }
837
838 /* loop over vertices */
839 for ( j=0 ;
840 j<nr ;
841 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
842 {
843 GLfloat diffuse[2], specular[2];
844 GLuint side = 0;
845 struct gl_light *light;
846
847 if ( CHECK_COLOR_MATERIAL(j) )
848 _mesa_update_color_material( ctx, CMcolor );
849
850 if ( CHECK_MATERIAL(j) )
851 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
852
853 if ( CHECK_VALIDATE(j) )
854 _mesa_validate_all_lighting_tables( ctx );
855
856 diffuse[0] = specular[0] = 0.0F;
857
858 if ( IDX & LIGHT_TWOSIDE ) {
859 diffuse[1] = specular[1] = 0.0F;
860 }
861
862 /* Accumulate diffuse and specular from each light source */
863 foreach (light, &ctx->Light.EnabledList) {
864
865 GLfloat attenuation = 1.0F;
866 GLfloat VP[3]; /* unit vector from vertex to light */
867 GLfloat n_dot_VP; /* dot product of l and n */
868 GLfloat *h, n_dot_h, correction = 1.0;
869
870 /* compute l and attenuation */
871 if (!(light->_Flags & LIGHT_POSITIONAL)) {
872 /* directional light */
873 COPY_3V(VP, light->_VP_inf_norm);
874 }
875 else {
876 GLfloat d; /* distance from vertex to light */
877
878 SUB_3V(VP, light->_Position, vertex);
879
880 d = (GLfloat) LEN_3FV( VP );
881 if ( d > 1e-6) {
882 GLfloat invd = 1.0F / d;
883 SELF_SCALE_SCALAR_3V(VP, invd);
884 }
885
886 attenuation = 1.0F / (light->ConstantAttenuation + d *
887 (light->LinearAttenuation + d *
888 light->QuadraticAttenuation));
889
890 /* spotlight attenuation */
891 if (light->_Flags & LIGHT_SPOT) {
892 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
893 if (PV_dot_dir < light->_CosCutoff) {
894 continue; /* this light makes no contribution */
895 }
896 else {
897 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
898 GLint k = (GLint) x;
899 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
900 + (x-k)*light->_SpotExpTable[k][1]);
901 attenuation *= spot;
902 }
903 }
904 }
905
906 if (attenuation < 1e-3)
907 continue; /* this light makes no contribution */
908
909 n_dot_VP = DOT3( normal, VP );
910
911 /* which side are we lighting? */
912 if (n_dot_VP < 0.0F) {
913 if (!(IDX & LIGHT_TWOSIDE))
914 continue;
915 side = 1;
916 correction = -1;
917 n_dot_VP = -n_dot_VP;
918 }
919
920 /* accumulate diffuse term */
921 diffuse[side] += n_dot_VP * light->_dli * attenuation;
922
923 /* specular term */
924 if (ctx->Light.Model.LocalViewer) {
925 GLfloat v[3];
926 COPY_3V(v, vertex);
927 NORMALIZE_3FV(v);
928 SUB_3V(VP, VP, v); /* h = VP + VPe */
929 h = VP;
930 NORMALIZE_3FV(h);
931 }
932 else if (light->_Flags & LIGHT_POSITIONAL) {
933 h = VP;
934 /* Strangely, disabling this addition fixes a conformance
935 * problem. If this code is enabled, l_sed.c fails.
936 */
937 /*ACC_3V(h, ctx->_EyeZDir);*/
938 NORMALIZE_3FV(h);
939 }
940 else {
941 h = light->_h_inf_norm;
942 }
943
944 n_dot_h = correction * DOT3(normal, h);
945 if (n_dot_h > 0.0F) {
946 GLfloat spec_coef;
947 struct gl_shine_tab *tab = ctx->_ShineTable[side];
948 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
949 specular[side] += spec_coef * light->_sli * attenuation;
950 }
951 } /*loop over lights*/
952
953 /* Now compute final color index */
954 for (side = 0 ; side < NR_SIDES ; side++) {
955 struct gl_material *mat = &ctx->Light.Material[side];
956 GLfloat index;
957
958 if (specular[side] > 1.0F) {
959 index = mat->SpecularIndex;
960 }
961 else {
962 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
963 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
964
965 index = mat->AmbientIndex
966 + diffuse[side] * (1.0F-specular[side]) * d_a
967 + specular[side] * s_a;
968
969 if (index > mat->SpecularIndex) {
970 index = mat->SpecularIndex;
971 }
972 }
973 indexResult[side][j] = (GLuint) (GLint) index;
974 }
975 } /*for vertex*/
976 }
977
978
979
980 static void TAG(init_light_tab)( void )
981 {
982 _tnl_light_tab[IDX] = TAG(light_rgba);
983 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
984 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
985 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
986 _tnl_light_ci_tab[IDX] = TAG(light_ci);
987 }
988
989
990 #undef TAG
991 #undef IDX
992 #undef NR_SIDES
993 #undef NSTRIDE
994 #undef VSTRIDE
995 #undef CHECK_MATERIAL
996 #undef CHECK_END_VB
997 #undef DO_ANOTHER_NORMAL
998 #undef REUSE_LIGHT_RESULTS
999 #undef CMSTRIDE
1000 #undef CHECK_COLOR_MATERIAL
1001 #undef CHECK_VALIDATE