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