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