re-disable TRACE
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * Authors:
26 * Brian Paul
27 * Keith Whitwell <keith@tungstengraphics.com>
28 */
29
30
31 #if IDX & LIGHT_TWOSIDE
32 # define NR_SIDES 2
33 #else
34 # define NR_SIDES 1
35 #endif
36
37
38 /* define TRACE to trace lighting code */
39 /* #define TRACE 1 */
40
41 /*
42 * ctx is the current context
43 * VB is the vertex buffer
44 * stage is the lighting stage-private data
45 * input is the vector of eye or object-space vertex coordinates
46 */
47 static void TAG(light_rgba_spec)( GLcontext *ctx,
48 struct vertex_buffer *VB,
49 struct tnl_pipeline_stage *stage,
50 GLvector4f *input )
51 {
52 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
53 GLfloat (*base)[3] = ctx->Light._BaseColor;
54 GLfloat sumA[2];
55 GLuint j;
56
57 const GLuint vstride = input->stride;
58 const GLfloat *vertex = (GLfloat *)input->data;
59 const GLuint nstride = VB->NormalPtr->stride;
60 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
61
62 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
63 GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data;
64 #if IDX & LIGHT_TWOSIDE
65 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
66 GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data;
67 #endif
68
69 const GLuint nr = VB->Count;
70
71 (void) nstride;
72 (void) vstride;
73
74 #ifdef TRACE
75 fprintf(stderr, "%s\n", __FUNCTION__ );
76 #endif
77
78 VB->ColorPtr[0] = &store->LitColor[0];
79 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
80 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
81
82 #if IDX & LIGHT_TWOSIDE
83 VB->ColorPtr[1] = &store->LitColor[1];
84 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
85 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
86 #endif
87
88 /* Side-effects done, can we finish now?
89 */
90 if (stage->changed_inputs == 0)
91 return;
92
93 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
94 GLfloat sum[2][3], spec[2][3];
95 struct gl_light *light;
96
97 #if IDX & LIGHT_MATERIAL
98 update_materials( ctx, store );
99 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
100 #if IDX & LIGHT_TWOSIDE
101 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
102 #endif
103 #endif
104
105 COPY_3V(sum[0], base[0]);
106 ZERO_3V(spec[0]);
107
108 #if IDX & LIGHT_TWOSIDE
109 COPY_3V(sum[1], base[1]);
110 ZERO_3V(spec[1]);
111 #endif
112
113 /* Add contribution from each enabled light source */
114 foreach (light, &ctx->Light.EnabledList) {
115 GLfloat n_dot_h;
116 GLfloat correction;
117 GLint side;
118 GLfloat contrib[3];
119 GLfloat attenuation;
120 GLfloat VP[3]; /* unit vector from vertex to light */
121 GLfloat n_dot_VP; /* n dot VP */
122 GLfloat *h;
123
124 /* compute VP and attenuation */
125 if (!(light->_Flags & LIGHT_POSITIONAL)) {
126 /* directional light */
127 COPY_3V(VP, light->_VP_inf_norm);
128 attenuation = light->_VP_inf_spot_attenuation;
129 }
130 else {
131 GLfloat d; /* distance from vertex to light */
132
133 SUB_3V(VP, light->_Position, vertex);
134
135 d = (GLfloat) LEN_3FV( VP );
136
137 if (d > 1e-6) {
138 GLfloat invd = 1.0F / d;
139 SELF_SCALE_SCALAR_3V(VP, invd);
140 }
141
142 attenuation = 1.0F / (light->ConstantAttenuation + d *
143 (light->LinearAttenuation + d *
144 light->QuadraticAttenuation));
145
146 /* spotlight attenuation */
147 if (light->_Flags & LIGHT_SPOT) {
148 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
149
150 if (PV_dot_dir<light->_CosCutoff) {
151 continue; /* this light makes no contribution */
152 }
153 else {
154 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
155 GLint k = (GLint) x;
156 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
157 + (x-k)*light->_SpotExpTable[k][1]);
158 attenuation *= spot;
159 }
160 }
161 }
162
163 if (attenuation < 1e-3)
164 continue; /* this light makes no contribution */
165
166 /* Compute dot product or normal and vector from V to light pos */
167 n_dot_VP = DOT3( normal, VP );
168
169 /* Which side gets the diffuse & specular terms? */
170 if (n_dot_VP < 0.0F) {
171 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
172 #if IDX & LIGHT_TWOSIDE
173 side = 1;
174 correction = -1;
175 n_dot_VP = -n_dot_VP;
176 #else
177 continue;
178 #endif
179 }
180 else {
181 #if IDX & LIGHT_TWOSIDE
182 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
183 #endif
184 side = 0;
185 correction = 1;
186 }
187
188 /* diffuse term */
189 COPY_3V(contrib, light->_MatAmbient[side]);
190 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
191 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
192
193 /* specular term - cannibalize VP... */
194 if (ctx->Light.Model.LocalViewer) {
195 GLfloat v[3];
196 COPY_3V(v, vertex);
197 NORMALIZE_3FV(v);
198 SUB_3V(VP, VP, v); /* h = VP + VPe */
199 h = VP;
200 NORMALIZE_3FV(h);
201 }
202 else if (light->_Flags & LIGHT_POSITIONAL) {
203 h = VP;
204 ACC_3V(h, ctx->_EyeZDir);
205 NORMALIZE_3FV(h);
206 }
207 else {
208 h = light->_h_inf_norm;
209 }
210
211 n_dot_h = correction * DOT3(normal, h);
212
213 if (n_dot_h > 0.0F) {
214 GLfloat spec_coef;
215 struct gl_shine_tab *tab = ctx->_ShineTable[side];
216 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
217
218 if (spec_coef > 1.0e-10) {
219 spec_coef *= attenuation;
220 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
221 light->_MatSpecular[side]);
222 }
223 }
224 } /*loop over lights*/
225
226 COPY_3V( Fcolor[j], sum[0] );
227 COPY_3V( Fspec[j], spec[0] );
228 Fcolor[j][3] = sumA[0];
229
230 #if IDX & LIGHT_TWOSIDE
231 COPY_3V( Bcolor[j], sum[1] );
232 COPY_3V( Bspec[j], spec[1] );
233 Bcolor[j][3] = sumA[1];
234 #endif
235 }
236 }
237
238
239 static void TAG(light_rgba)( GLcontext *ctx,
240 struct vertex_buffer *VB,
241 struct tnl_pipeline_stage *stage,
242 GLvector4f *input )
243 {
244 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
245 GLuint j;
246
247 GLfloat (*base)[3] = ctx->Light._BaseColor;
248 GLfloat sumA[2];
249
250 const GLuint vstride = input->stride;
251 const GLfloat *vertex = (GLfloat *) input->data;
252 const GLuint nstride = VB->NormalPtr->stride;
253 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
254
255 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
256 #if IDX & LIGHT_TWOSIDE
257 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
258 #endif
259
260 const GLuint nr = VB->Count;
261
262 #ifdef TRACE
263 fprintf(stderr, "%s\n", __FUNCTION__ );
264 #endif
265
266 (void) nstride;
267 (void) vstride;
268
269 VB->ColorPtr[0] = &store->LitColor[0];
270 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
271
272 #if IDX & LIGHT_TWOSIDE
273 VB->ColorPtr[1] = &store->LitColor[1];
274 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
275 #endif
276
277 if (stage->changed_inputs == 0)
278 return;
279
280 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
281 GLfloat sum[2][3];
282 struct gl_light *light;
283
284 #if IDX & LIGHT_MATERIAL
285 update_materials( ctx, store );
286 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
287 #if IDX & LIGHT_TWOSIDE
288 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
289 #endif
290 #endif
291
292 COPY_3V(sum[0], base[0]);
293
294 #if IDX & LIGHT_TWOSIDE
295 COPY_3V(sum[1], base[1]);
296 #endif
297
298 /* Add contribution from each enabled light source */
299 foreach (light, &ctx->Light.EnabledList) {
300
301 GLfloat n_dot_h;
302 GLfloat correction;
303 GLint side;
304 GLfloat contrib[3];
305 GLfloat attenuation = 1.0;
306 GLfloat VP[3]; /* unit vector from vertex to light */
307 GLfloat n_dot_VP; /* n dot VP */
308 GLfloat *h;
309
310 /* compute VP and attenuation */
311 if (!(light->_Flags & LIGHT_POSITIONAL)) {
312 /* directional light */
313 COPY_3V(VP, light->_VP_inf_norm);
314 attenuation = light->_VP_inf_spot_attenuation;
315 }
316 else {
317 GLfloat d; /* distance from vertex to light */
318
319
320 SUB_3V(VP, light->_Position, vertex);
321
322 d = (GLfloat) LEN_3FV( VP );
323
324 if ( d > 1e-6) {
325 GLfloat invd = 1.0F / d;
326 SELF_SCALE_SCALAR_3V(VP, invd);
327 }
328
329 attenuation = 1.0F / (light->ConstantAttenuation + d *
330 (light->LinearAttenuation + d *
331 light->QuadraticAttenuation));
332
333 /* spotlight attenuation */
334 if (light->_Flags & LIGHT_SPOT) {
335 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
336
337 if (PV_dot_dir<light->_CosCutoff) {
338 continue; /* this light makes no contribution */
339 }
340 else {
341 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
342 GLint k = (GLint) x;
343 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
344 + (x-k)*light->_SpotExpTable[k][1]);
345 attenuation *= spot;
346 }
347 }
348 }
349
350 if (attenuation < 1e-3)
351 continue; /* this light makes no contribution */
352
353 /* Compute dot product or normal and vector from V to light pos */
354 n_dot_VP = DOT3( normal, VP );
355
356 /* which side are we lighting? */
357 if (n_dot_VP < 0.0F) {
358 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
359 #if IDX & LIGHT_TWOSIDE
360 side = 1;
361 correction = -1;
362 n_dot_VP = -n_dot_VP;
363 #else
364 continue;
365 #endif
366 }
367 else {
368 #if IDX & LIGHT_TWOSIDE
369 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
370 #endif
371 side = 0;
372 correction = 1;
373 }
374
375 COPY_3V(contrib, light->_MatAmbient[side]);
376
377 /* diffuse term */
378 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
379
380 /* specular term - cannibalize VP... */
381 {
382 if (ctx->Light.Model.LocalViewer) {
383 GLfloat v[3];
384 COPY_3V(v, vertex);
385 NORMALIZE_3FV(v);
386 SUB_3V(VP, VP, v); /* h = VP + VPe */
387 h = VP;
388 NORMALIZE_3FV(h);
389 }
390 else if (light->_Flags & LIGHT_POSITIONAL) {
391 h = VP;
392 ACC_3V(h, ctx->_EyeZDir);
393 NORMALIZE_3FV(h);
394 }
395 else {
396 h = light->_h_inf_norm;
397 }
398
399 n_dot_h = correction * DOT3(normal, h);
400
401 if (n_dot_h > 0.0F)
402 {
403 GLfloat spec_coef;
404 struct gl_shine_tab *tab = ctx->_ShineTable[side];
405
406 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
407
408 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
409 light->_MatSpecular[side]);
410 }
411 }
412
413 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
414 }
415
416 COPY_3V( Fcolor[j], sum[0] );
417 Fcolor[j][3] = sumA[0];
418
419 #if IDX & LIGHT_TWOSIDE
420 COPY_3V( Bcolor[j], sum[1] );
421 Bcolor[j][3] = sumA[1];
422 #endif
423 }
424 }
425
426
427
428
429 /* As below, but with just a single light.
430 */
431 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
432 struct vertex_buffer *VB,
433 struct tnl_pipeline_stage *stage,
434 GLvector4f *input )
435
436 {
437 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
438 const GLuint nstride = VB->NormalPtr->stride;
439 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
440 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
441 #if IDX & LIGHT_TWOSIDE
442 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
443 #endif
444 const struct gl_light *light = ctx->Light.EnabledList.next;
445 GLuint j = 0;
446 GLfloat base[2][4];
447 const GLuint nr = VB->Count;
448
449 #ifdef TRACE
450 fprintf(stderr, "%s\n", __FUNCTION__ );
451 #endif
452
453 (void) input; /* doesn't refer to Eye or Obj */
454 (void) nr;
455 (void) nstride;
456
457 VB->ColorPtr[0] = &store->LitColor[0];
458 #if IDX & LIGHT_TWOSIDE
459 VB->ColorPtr[1] = &store->LitColor[1];
460 #endif
461
462 if (stage->changed_inputs == 0)
463 return;
464
465 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
466
467 GLfloat n_dot_VP;
468
469 #if IDX & LIGHT_MATERIAL
470 update_materials( ctx, store );
471 #endif
472
473 /* No attenuation, so incoporate _MatAmbient into base color.
474 */
475 #if !(IDX & LIGHT_MATERIAL)
476 if ( j == 0 )
477 #endif
478 {
479 COPY_3V(base[0], light->_MatAmbient[0]);
480 ACC_3V(base[0], ctx->Light._BaseColor[0] );
481 base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
482
483 #if IDX & LIGHT_TWOSIDE
484 COPY_3V(base[1], light->_MatAmbient[1]);
485 ACC_3V(base[1], ctx->Light._BaseColor[1]);
486 base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
487 #endif
488 }
489
490 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
491
492 if (n_dot_VP < 0.0F) {
493 #if IDX & LIGHT_TWOSIDE
494 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
495 GLfloat sum[3];
496 COPY_3V(sum, base[1]);
497 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
498 if (n_dot_h > 0.0F) {
499 GLfloat spec;
500 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
501 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
502 }
503 COPY_3V(Bcolor[j], sum );
504 Bcolor[j][3] = base[1][3];
505 #endif
506 COPY_4FV(Fcolor[j], base[0]);
507 }
508 else {
509 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
510 GLfloat sum[3];
511 COPY_3V(sum, base[0]);
512 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
513 if (n_dot_h > 0.0F) {
514 GLfloat spec;
515 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
516 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
517
518 }
519 COPY_3V(Fcolor[j], sum );
520 Fcolor[j][3] = base[0][3];
521 #if IDX & LIGHT_TWOSIDE
522 COPY_4FV(Bcolor[j], base[1]);
523 #endif
524 }
525 }
526 }
527
528
529 /* Light infinite lights
530 */
531 static void TAG(light_fast_rgba)( GLcontext *ctx,
532 struct vertex_buffer *VB,
533 struct tnl_pipeline_stage *stage,
534 GLvector4f *input )
535 {
536 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
537 GLfloat sumA[2];
538 const GLuint nstride = VB->NormalPtr->stride;
539 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
540 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
541 #if IDX & LIGHT_TWOSIDE
542 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
543 #endif
544 GLuint j = 0;
545 const GLuint nr = VB->Count;
546 const struct gl_light *light;
547
548 #ifdef TRACE
549 fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
550 #endif
551
552 (void) input;
553 (void) nr;
554 (void) nstride;
555
556 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
557 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
558
559 VB->ColorPtr[0] = &store->LitColor[0];
560 #if IDX & LIGHT_TWOSIDE
561 VB->ColorPtr[1] = &store->LitColor[1];
562 #endif
563
564 if (stage->changed_inputs == 0)
565 return;
566
567 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
568
569 GLfloat sum[2][3];
570
571 #if IDX & LIGHT_MATERIAL
572 update_materials( ctx, store );
573
574 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
575 #if IDX & LIGHT_TWOSIDE
576 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
577 #endif
578 #endif
579
580
581 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
582 #if IDX & LIGHT_TWOSIDE
583 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
584 #endif
585
586 foreach (light, &ctx->Light.EnabledList) {
587 GLfloat n_dot_h, n_dot_VP, spec;
588
589 ACC_3V(sum[0], light->_MatAmbient[0]);
590 #if IDX & LIGHT_TWOSIDE
591 ACC_3V(sum[1], light->_MatAmbient[1]);
592 #endif
593
594 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
595
596 if (n_dot_VP > 0.0F) {
597 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
598 n_dot_h = DOT3(normal, light->_h_inf_norm);
599 if (n_dot_h > 0.0F) {
600 struct gl_shine_tab *tab = ctx->_ShineTable[0];
601 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
602 ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]);
603 }
604 }
605 #if IDX & LIGHT_TWOSIDE
606 else {
607 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
608 n_dot_h = -DOT3(normal, light->_h_inf_norm);
609 if (n_dot_h > 0.0F) {
610 struct gl_shine_tab *tab = ctx->_ShineTable[1];
611 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
612 ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]);
613 }
614 }
615 #endif
616 }
617
618 COPY_3V( Fcolor[j], sum[0] );
619 Fcolor[j][3] = sumA[0];
620
621 #if IDX & LIGHT_TWOSIDE
622 COPY_3V( Bcolor[j], sum[1] );
623 Bcolor[j][3] = sumA[1];
624 #endif
625 }
626 }
627
628
629
630
631
632 /*
633 * Use current lighting/material settings to compute the color indexes
634 * for an array of vertices.
635 * Input: n - number of vertices to light
636 * side - 0=use front material, 1=use back material
637 * vertex - array of [n] vertex position in eye coordinates
638 * normal - array of [n] surface normal vector
639 * Output: indexResult - resulting array of [n] color indexes
640 */
641 static void TAG(light_ci)( GLcontext *ctx,
642 struct vertex_buffer *VB,
643 struct tnl_pipeline_stage *stage,
644 GLvector4f *input )
645 {
646 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
647 GLuint j;
648 const GLuint vstride = input->stride;
649 const GLfloat *vertex = (GLfloat *) input->data;
650 const GLuint nstride = VB->NormalPtr->stride;
651 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
652 GLfloat *indexResult[2];
653 const GLuint nr = VB->Count;
654
655 #ifdef TRACE
656 fprintf(stderr, "%s\n", __FUNCTION__ );
657 #endif
658
659 (void) nstride;
660 (void) vstride;
661
662 VB->IndexPtr[0] = &store->LitIndex[0];
663 #if IDX & LIGHT_TWOSIDE
664 VB->IndexPtr[1] = &store->LitIndex[1];
665 #endif
666
667 if (stage->changed_inputs == 0)
668 return;
669
670 indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data;
671 #if IDX & LIGHT_TWOSIDE
672 indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data;
673 #endif
674
675 /* loop over vertices */
676 for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) {
677 GLfloat diffuse[2], specular[2];
678 GLuint side = 0;
679 struct gl_light *light;
680
681 #if IDX & LIGHT_MATERIAL
682 update_materials( ctx, store );
683 #endif
684
685 diffuse[0] = specular[0] = 0.0F;
686
687 #if IDX & LIGHT_TWOSIDE
688 diffuse[1] = specular[1] = 0.0F;
689 #endif
690
691 /* Accumulate diffuse and specular from each light source */
692 foreach (light, &ctx->Light.EnabledList) {
693
694 GLfloat attenuation = 1.0F;
695 GLfloat VP[3]; /* unit vector from vertex to light */
696 GLfloat n_dot_VP; /* dot product of l and n */
697 GLfloat *h, n_dot_h, correction = 1.0;
698
699 /* compute l and attenuation */
700 if (!(light->_Flags & LIGHT_POSITIONAL)) {
701 /* directional light */
702 COPY_3V(VP, light->_VP_inf_norm);
703 }
704 else {
705 GLfloat d; /* distance from vertex to light */
706
707 SUB_3V(VP, light->_Position, vertex);
708
709 d = (GLfloat) LEN_3FV( VP );
710 if ( d > 1e-6) {
711 GLfloat invd = 1.0F / d;
712 SELF_SCALE_SCALAR_3V(VP, invd);
713 }
714
715 attenuation = 1.0F / (light->ConstantAttenuation + d *
716 (light->LinearAttenuation + d *
717 light->QuadraticAttenuation));
718
719 /* spotlight attenuation */
720 if (light->_Flags & LIGHT_SPOT) {
721 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
722 if (PV_dot_dir < light->_CosCutoff) {
723 continue; /* this light makes no contribution */
724 }
725 else {
726 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
727 GLint k = (GLint) x;
728 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
729 + (x-k)*light->_SpotExpTable[k][1]);
730 attenuation *= spot;
731 }
732 }
733 }
734
735 if (attenuation < 1e-3)
736 continue; /* this light makes no contribution */
737
738 n_dot_VP = DOT3( normal, VP );
739
740 /* which side are we lighting? */
741 if (n_dot_VP < 0.0F) {
742 #if IDX & LIGHT_TWOSIDE
743 side = 1;
744 correction = -1;
745 n_dot_VP = -n_dot_VP;
746 #else
747 continue;
748 #endif
749 }
750
751 /* accumulate diffuse term */
752 diffuse[side] += n_dot_VP * light->_dli * attenuation;
753
754 /* specular term */
755 if (ctx->Light.Model.LocalViewer) {
756 GLfloat v[3];
757 COPY_3V(v, vertex);
758 NORMALIZE_3FV(v);
759 SUB_3V(VP, VP, v); /* h = VP + VPe */
760 h = VP;
761 NORMALIZE_3FV(h);
762 }
763 else if (light->_Flags & LIGHT_POSITIONAL) {
764 h = VP;
765 /* Strangely, disabling this addition fixes a conformance
766 * problem. If this code is enabled, l_sed.c fails.
767 */
768 /*ACC_3V(h, ctx->_EyeZDir);*/
769 NORMALIZE_3FV(h);
770 }
771 else {
772 h = light->_h_inf_norm;
773 }
774
775 n_dot_h = correction * DOT3(normal, h);
776 if (n_dot_h > 0.0F) {
777 GLfloat spec_coef;
778 struct gl_shine_tab *tab = ctx->_ShineTable[side];
779 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
780 specular[side] += spec_coef * light->_sli * attenuation;
781 }
782 } /*loop over lights*/
783
784 /* Now compute final color index */
785 for (side = 0 ; side < NR_SIDES ; side++) {
786 const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side];
787 GLfloat index;
788
789 if (specular[side] > 1.0F) {
790 index = ind[MAT_INDEX_SPECULAR];
791 }
792 else {
793 GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT];
794 GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT];
795 index = (ind[MAT_INDEX_AMBIENT]
796 + diffuse[side] * (1.0F-specular[side]) * d_a
797 + specular[side] * s_a);
798 if (index > ind[MAT_INDEX_SPECULAR]) {
799 index = ind[MAT_INDEX_SPECULAR];
800 }
801 }
802 indexResult[side][j] = index;
803 }
804 } /*for vertex*/
805 }
806
807
808
809 static void TAG(init_light_tab)( void )
810 {
811 _tnl_light_tab[IDX] = TAG(light_rgba);
812 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
813 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
814 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
815 _tnl_light_ci_tab[IDX] = TAG(light_ci);
816 }
817
818
819 #undef TAG
820 #undef IDX
821 #undef NR_SIDES