Fixed MAXFIFO_S4. Removed WAIT_IDLE_EMPTY from savage_BCI_swap which resulted
[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 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
257 GLfloat (*color[2])[4];
258
259 const GLuint nr = VB->Count;
260
261 #ifdef TRACE
262 fprintf(stderr, "%s\n", __FUNCTION__ );
263 #endif
264
265 (void) nstride;
266 (void) vstride;
267
268 color[0] = Fcolor;
269 color[1] = Bcolor;
270
271 VB->ColorPtr[0] = &store->LitColor[0];
272 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
273
274 #if IDX & LIGHT_TWOSIDE
275 VB->ColorPtr[1] = &store->LitColor[1];
276 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
277 #endif
278
279 if (stage->changed_inputs == 0)
280 return;
281
282 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
283 GLfloat sum[2][3];
284 struct gl_light *light;
285
286 if ( IDX & LIGHT_MATERIAL ) {
287 update_materials( ctx, store );
288 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
289 #if IDX & LIGHT_TWOSIDE
290 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
291 #endif
292 }
293
294 COPY_3V(sum[0], base[0]);
295
296 if ( IDX & LIGHT_TWOSIDE )
297 COPY_3V(sum[1], base[1]);
298
299 /* Add contribution from each enabled light source */
300 foreach (light, &ctx->Light.EnabledList) {
301
302 GLfloat n_dot_h;
303 GLfloat correction;
304 GLint side;
305 GLfloat contrib[3];
306 GLfloat attenuation = 1.0;
307 GLfloat VP[3]; /* unit vector from vertex to light */
308 GLfloat n_dot_VP; /* n dot VP */
309 GLfloat *h;
310
311 /* compute VP and attenuation */
312 if (!(light->_Flags & LIGHT_POSITIONAL)) {
313 /* directional light */
314 COPY_3V(VP, light->_VP_inf_norm);
315 attenuation = light->_VP_inf_spot_attenuation;
316 }
317 else {
318 GLfloat d; /* distance from vertex to light */
319
320
321 SUB_3V(VP, light->_Position, vertex);
322
323 d = (GLfloat) LEN_3FV( VP );
324
325 if ( d > 1e-6) {
326 GLfloat invd = 1.0F / d;
327 SELF_SCALE_SCALAR_3V(VP, invd);
328 }
329
330 attenuation = 1.0F / (light->ConstantAttenuation + d *
331 (light->LinearAttenuation + d *
332 light->QuadraticAttenuation));
333
334 /* spotlight attenuation */
335 if (light->_Flags & LIGHT_SPOT) {
336 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
337
338 if (PV_dot_dir<light->_CosCutoff) {
339 continue; /* this light makes no contribution */
340 }
341 else {
342 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
343 GLint k = (GLint) x;
344 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
345 + (x-k)*light->_SpotExpTable[k][1]);
346 attenuation *= spot;
347 }
348 }
349 }
350
351 if (attenuation < 1e-3)
352 continue; /* this light makes no contribution */
353
354 /* Compute dot product or normal and vector from V to light pos */
355 n_dot_VP = DOT3( normal, VP );
356
357 /* which side are we lighting? */
358 if (n_dot_VP < 0.0F) {
359 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
360 #if IDX & LIGHT_TWOSIDE
361 side = 1;
362 correction = -1;
363 n_dot_VP = -n_dot_VP;
364 #else
365 continue;
366 #endif
367 }
368 else {
369 #if IDX & LIGHT_TWOSIDE
370 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
371 #endif
372 side = 0;
373 correction = 1;
374 }
375
376 COPY_3V(contrib, light->_MatAmbient[side]);
377
378 /* diffuse term */
379 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
380
381 /* specular term - cannibalize VP... */
382 {
383 if (ctx->Light.Model.LocalViewer) {
384 GLfloat v[3];
385 COPY_3V(v, vertex);
386 NORMALIZE_3FV(v);
387 SUB_3V(VP, VP, v); /* h = VP + VPe */
388 h = VP;
389 NORMALIZE_3FV(h);
390 }
391 else if (light->_Flags & LIGHT_POSITIONAL) {
392 h = VP;
393 ACC_3V(h, ctx->_EyeZDir);
394 NORMALIZE_3FV(h);
395 }
396 else {
397 h = light->_h_inf_norm;
398 }
399
400 n_dot_h = correction * DOT3(normal, h);
401
402 if (n_dot_h > 0.0F)
403 {
404 GLfloat spec_coef;
405 struct gl_shine_tab *tab = ctx->_ShineTable[side];
406
407 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
408
409 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
410 light->_MatSpecular[side]);
411 }
412 }
413
414 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
415 }
416
417 COPY_3V( Fcolor[j], sum[0] );
418 Fcolor[j][3] = sumA[0];
419
420 #if IDX & LIGHT_TWOSIDE
421 COPY_3V( Bcolor[j], sum[1] );
422 Bcolor[j][3] = sumA[1];
423 #endif
424 }
425 }
426
427
428
429
430 /* As below, but with just a single light.
431 */
432 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
433 struct vertex_buffer *VB,
434 struct tnl_pipeline_stage *stage,
435 GLvector4f *input )
436
437 {
438 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
439 const GLuint nstride = VB->NormalPtr->stride;
440 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
441 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
442 #if IDX & LIGHT_TWOSIDE
443 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
444 #endif
445 const struct gl_light *light = ctx->Light.EnabledList.next;
446 GLuint j = 0;
447 GLfloat base[2][4];
448 const GLuint nr = VB->Count;
449
450 #ifdef TRACE
451 fprintf(stderr, "%s\n", __FUNCTION__ );
452 #endif
453
454 (void) input; /* doesn't refer to Eye or Obj */
455 (void) nr;
456 (void) nstride;
457
458 VB->ColorPtr[0] = &store->LitColor[0];
459 #if IDX & LIGHT_TWOSIDE
460 VB->ColorPtr[1] = &store->LitColor[1];
461 #endif
462
463 if (stage->changed_inputs == 0)
464 return;
465
466 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
467
468 GLfloat n_dot_VP;
469
470 if ( IDX & LIGHT_MATERIAL )
471 update_materials( ctx, store );
472
473 /* No attenuation, so incoporate _MatAmbient into base color.
474 */
475 if ( j == 0 || (IDX & LIGHT_MATERIAL) ) {
476 COPY_3V(base[0], light->_MatAmbient[0]);
477 ACC_3V(base[0], ctx->Light._BaseColor[0] );
478 base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
479
480 #if IDX & LIGHT_TWOSIDE
481 COPY_3V(base[1], light->_MatAmbient[1]);
482 ACC_3V(base[1], ctx->Light._BaseColor[1]);
483 base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
484 #endif
485 }
486
487 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
488
489 if (n_dot_VP < 0.0F) {
490 #if IDX & LIGHT_TWOSIDE
491 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
492 GLfloat sum[3];
493 COPY_3V(sum, base[1]);
494 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
495 if (n_dot_h > 0.0F) {
496 GLfloat spec;
497 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
498 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
499 }
500 COPY_3V(Bcolor[j], sum );
501 Bcolor[j][3] = base[1][3];
502 #endif
503 COPY_4FV(Fcolor[j], base[0]);
504 }
505 else {
506 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
507 GLfloat sum[3];
508 COPY_3V(sum, base[0]);
509 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
510 if (n_dot_h > 0.0F) {
511 GLfloat spec;
512 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
513 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
514
515 }
516 COPY_3V(Fcolor[j], sum );
517 Fcolor[j][3] = base[0][3];
518 #if IDX & LIGHT_TWOSIDE
519 COPY_4FV(Bcolor[j], base[1]);
520 #endif
521 }
522 }
523 }
524
525
526 /* Light infinite lights
527 */
528 static void TAG(light_fast_rgba)( GLcontext *ctx,
529 struct vertex_buffer *VB,
530 struct tnl_pipeline_stage *stage,
531 GLvector4f *input )
532 {
533 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
534 GLfloat sumA[2];
535 const GLuint nstride = VB->NormalPtr->stride;
536 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
537 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
538 #if IDX & LIGHT_TWOSIDE
539 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
540 #endif
541 GLuint j = 0;
542 const GLuint nr = VB->Count;
543 const struct gl_light *light;
544
545 #ifdef TRACE
546 fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
547 #endif
548
549 (void) input;
550 (void) nr;
551 (void) nstride;
552
553 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
554 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
555
556 VB->ColorPtr[0] = &store->LitColor[0];
557 #if IDX & LIGHT_TWOSIDE
558 VB->ColorPtr[1] = &store->LitColor[1];
559 #endif
560
561 if (stage->changed_inputs == 0)
562 return;
563
564 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
565
566 GLfloat sum[2][3];
567
568 if ( IDX & LIGHT_MATERIAL ) {
569 update_materials( ctx, store );
570
571 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
572 #if IDX & LIGHT_TWOSIDE
573 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
574 #endif
575 }
576
577
578 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
579 #if IDX & LIGHT_TWOSIDE
580 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
581 #endif
582
583 foreach (light, &ctx->Light.EnabledList) {
584 GLfloat n_dot_h, n_dot_VP, spec;
585
586 ACC_3V(sum[0], light->_MatAmbient[0]);
587 #if IDX & LIGHT_TWOSIDE
588 ACC_3V(sum[1], light->_MatAmbient[1]);
589 #endif
590
591 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
592
593 if (n_dot_VP > 0.0F) {
594 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
595 n_dot_h = DOT3(normal, light->_h_inf_norm);
596 if (n_dot_h > 0.0F) {
597 struct gl_shine_tab *tab = ctx->_ShineTable[0];
598 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
599 ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]);
600 }
601 }
602 #if IDX & LIGHT_TWOSIDE
603 else {
604 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
605 n_dot_h = -DOT3(normal, light->_h_inf_norm);
606 if (n_dot_h > 0.0F) {
607 struct gl_shine_tab *tab = ctx->_ShineTable[1];
608 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
609 ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]);
610 }
611 }
612 #endif
613 }
614
615 COPY_3V( Fcolor[j], sum[0] );
616 Fcolor[j][3] = sumA[0];
617
618 #if IDX & LIGHT_TWOSIDE
619 COPY_3V( Bcolor[j], sum[1] );
620 Bcolor[j][3] = sumA[1];
621 #endif
622 }
623 }
624
625
626
627
628
629 /*
630 * Use current lighting/material settings to compute the color indexes
631 * for an array of vertices.
632 * Input: n - number of vertices to light
633 * side - 0=use front material, 1=use back material
634 * vertex - array of [n] vertex position in eye coordinates
635 * normal - array of [n] surface normal vector
636 * Output: indexResult - resulting array of [n] color indexes
637 */
638 static void TAG(light_ci)( GLcontext *ctx,
639 struct vertex_buffer *VB,
640 struct tnl_pipeline_stage *stage,
641 GLvector4f *input )
642 {
643 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
644 GLuint j;
645 const GLuint vstride = input->stride;
646 const GLfloat *vertex = (GLfloat *) input->data;
647 const GLuint nstride = VB->NormalPtr->stride;
648 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
649 GLfloat *indexResult[2];
650 const GLuint nr = VB->Count;
651
652 #ifdef TRACE
653 fprintf(stderr, "%s\n", __FUNCTION__ );
654 #endif
655
656 (void) nstride;
657 (void) vstride;
658
659 VB->IndexPtr[0] = &store->LitIndex[0];
660 #if IDX & LIGHT_TWOSIDE
661 VB->IndexPtr[1] = &store->LitIndex[1];
662 #endif
663
664 if (stage->changed_inputs == 0)
665 return;
666
667 indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data;
668 #if IDX & LIGHT_TWOSIDE
669 indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data;
670 #endif
671
672 /* loop over vertices */
673 for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) {
674 GLfloat diffuse[2], specular[2];
675 GLuint side = 0;
676 struct gl_light *light;
677
678 if ( IDX & LIGHT_MATERIAL )
679 update_materials( ctx, store );
680
681 diffuse[0] = specular[0] = 0.0F;
682
683 if ( IDX & LIGHT_TWOSIDE ) {
684 diffuse[1] = specular[1] = 0.0F;
685 }
686
687 /* Accumulate diffuse and specular from each light source */
688 foreach (light, &ctx->Light.EnabledList) {
689
690 GLfloat attenuation = 1.0F;
691 GLfloat VP[3]; /* unit vector from vertex to light */
692 GLfloat n_dot_VP; /* dot product of l and n */
693 GLfloat *h, n_dot_h, correction = 1.0;
694
695 /* compute l and attenuation */
696 if (!(light->_Flags & LIGHT_POSITIONAL)) {
697 /* directional light */
698 COPY_3V(VP, light->_VP_inf_norm);
699 }
700 else {
701 GLfloat d; /* distance from vertex to light */
702
703 SUB_3V(VP, light->_Position, vertex);
704
705 d = (GLfloat) LEN_3FV( VP );
706 if ( d > 1e-6) {
707 GLfloat invd = 1.0F / d;
708 SELF_SCALE_SCALAR_3V(VP, invd);
709 }
710
711 attenuation = 1.0F / (light->ConstantAttenuation + d *
712 (light->LinearAttenuation + d *
713 light->QuadraticAttenuation));
714
715 /* spotlight attenuation */
716 if (light->_Flags & LIGHT_SPOT) {
717 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
718 if (PV_dot_dir < light->_CosCutoff) {
719 continue; /* this light makes no contribution */
720 }
721 else {
722 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
723 GLint k = (GLint) x;
724 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
725 + (x-k)*light->_SpotExpTable[k][1]);
726 attenuation *= spot;
727 }
728 }
729 }
730
731 if (attenuation < 1e-3)
732 continue; /* this light makes no contribution */
733
734 n_dot_VP = DOT3( normal, VP );
735
736 /* which side are we lighting? */
737 if (n_dot_VP < 0.0F) {
738 #if IDX & LIGHT_TWOSIDE
739 side = 1;
740 correction = -1;
741 n_dot_VP = -n_dot_VP;
742 #else
743 continue;
744 #endif
745 }
746
747 /* accumulate diffuse term */
748 diffuse[side] += n_dot_VP * light->_dli * attenuation;
749
750 /* specular term */
751 if (ctx->Light.Model.LocalViewer) {
752 GLfloat v[3];
753 COPY_3V(v, vertex);
754 NORMALIZE_3FV(v);
755 SUB_3V(VP, VP, v); /* h = VP + VPe */
756 h = VP;
757 NORMALIZE_3FV(h);
758 }
759 else if (light->_Flags & LIGHT_POSITIONAL) {
760 h = VP;
761 /* Strangely, disabling this addition fixes a conformance
762 * problem. If this code is enabled, l_sed.c fails.
763 */
764 /*ACC_3V(h, ctx->_EyeZDir);*/
765 NORMALIZE_3FV(h);
766 }
767 else {
768 h = light->_h_inf_norm;
769 }
770
771 n_dot_h = correction * DOT3(normal, h);
772 if (n_dot_h > 0.0F) {
773 GLfloat spec_coef;
774 struct gl_shine_tab *tab = ctx->_ShineTable[side];
775 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
776 specular[side] += spec_coef * light->_sli * attenuation;
777 }
778 } /*loop over lights*/
779
780 /* Now compute final color index */
781 for (side = 0 ; side < NR_SIDES ; side++) {
782 const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side];
783 GLfloat index;
784
785 if (specular[side] > 1.0F) {
786 index = ind[MAT_INDEX_SPECULAR];
787 }
788 else {
789 GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT];
790 GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT];
791 index = (ind[MAT_INDEX_AMBIENT]
792 + diffuse[side] * (1.0F-specular[side]) * d_a
793 + specular[side] * s_a);
794 if (index > ind[MAT_INDEX_SPECULAR]) {
795 index = ind[MAT_INDEX_SPECULAR];
796 }
797 }
798 indexResult[side][j] = index;
799 }
800 } /*for vertex*/
801 }
802
803
804
805 static void TAG(init_light_tab)( void )
806 {
807 _tnl_light_tab[IDX] = TAG(light_rgba);
808 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
809 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
810 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
811 _tnl_light_ci_tab[IDX] = TAG(light_ci);
812 }
813
814
815 #undef TAG
816 #undef IDX
817 #undef NR_SIDES