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