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