f2bcde671485ae770dd30aaf92f04037a220ee80
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /* $Id: t_vb_lighttmp.h,v 1.1 2000/12/26 05:09:33 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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_4UB(CMcolor, (4 * sizeof(GLubyte)))
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 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_4UB(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 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 const GLchan *sumA = ctx->Light._BaseAlpha;
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 GLchan (*CMcolor)[4];
101 GLuint CMstride;
102
103 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].data;
104 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].data;
105 GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].data;
106 GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].data;
107 GLuint nr = VB->Count;
108
109 GLuint *flags = VB->Flag;
110 struct gl_material (*new_material)[2] = VB->Material;
111 GLuint *new_material_mask = VB->MaterialMask;
112
113 (void) flags;
114 (void) nstride;
115 (void) vstride;
116
117 if (IDX & LIGHT_COLORMATERIAL) {
118 CMcolor = (GLchan (*)[4]) VB->ColorPtr[0]->data;
119 CMstride = VB->ColorPtr[0]->stride;
120 }
121
122 VB->ColorPtr[0] = &store->LitColor[0];
123 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
124
125 if (IDX & LIGHT_TWOSIDE) {
126 VB->ColorPtr[1] = &store->LitColor[1];
127 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
128 }
129
130 /* Side-effects done, can we finish now?
131 */
132 if (stage->changed_inputs == 0)
133 return;
134
135 for ( j=0 ;
136 j<nr ;
137 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
138 {
139 GLfloat sum[2][3], spec[2][3];
140 struct gl_light *light;
141
142 if ( CHECK_COLOR_MATERIAL(j) )
143 gl_update_color_material( ctx, CMcolor[j] );
144
145 if ( CHECK_MATERIAL(j) )
146 gl_update_material( ctx, new_material[j], new_material_mask[j] );
147
148 if ( CHECK_VALIDATE(j) )
149 gl_validate_all_lighting_tables( ctx );
150
151 COPY_3V(sum[0], base[0]);
152 ZERO_3V(spec[0]);
153
154 if (IDX & LIGHT_TWOSIDE) {
155 COPY_3V(sum[1], base[1]);
156 ZERO_3V(spec[1]);
157 }
158
159 /* Add contribution from each enabled light source */
160 foreach (light, &ctx->Light.EnabledList) {
161 GLfloat n_dot_h;
162 GLfloat correction;
163 GLint side;
164 GLfloat contrib[3];
165 GLfloat attenuation;
166 GLfloat VP[3]; /* unit vector from vertex to light */
167 GLfloat n_dot_VP; /* n dot VP */
168 GLfloat *h;
169
170 /* compute VP and attenuation */
171 if (!(light->_Flags & LIGHT_POSITIONAL)) {
172 /* directional light */
173 COPY_3V(VP, light->_VP_inf_norm);
174 attenuation = light->_VP_inf_spot_attenuation;
175 }
176 else {
177 GLfloat d; /* distance from vertex to light */
178
179 SUB_3V(VP, light->_Position, vertex);
180
181 d = (GLfloat) LEN_3FV( VP );
182
183 if (d > 1e-6) {
184 GLfloat invd = 1.0F / d;
185 SELF_SCALE_SCALAR_3V(VP, invd);
186 }
187
188 attenuation = 1.0F / (light->ConstantAttenuation + d *
189 (light->LinearAttenuation + d *
190 light->QuadraticAttenuation));
191
192 /* spotlight attenuation */
193 if (light->_Flags & LIGHT_SPOT) {
194 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
195
196 if (PV_dot_dir<light->_CosCutoff) {
197 continue; /* this light makes no contribution */
198 }
199 else {
200 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
201 int k = (int) x;
202 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
203 + (x-k)*light->_SpotExpTable[k][1]);
204 attenuation *= spot;
205 }
206 }
207 }
208
209
210 if (attenuation < 1e-3)
211 continue; /* this light makes no contribution */
212
213 /* Compute dot product or normal and vector from V to light pos */
214 n_dot_VP = DOT3( normal, VP );
215
216 /* Which side gets the diffuse & specular terms? */
217 if (n_dot_VP < 0.0F) {
218 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
219 if (!(IDX & LIGHT_TWOSIDE)) {
220 continue;
221 }
222 side = 1;
223 correction = -1;
224 n_dot_VP = -n_dot_VP;
225 }
226 else {
227 if (IDX & LIGHT_TWOSIDE) {
228 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
229 }
230 side = 0;
231 correction = 1;
232 }
233
234 /* diffuse term */
235 COPY_3V(contrib, light->_MatAmbient[side]);
236 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
237 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
238
239 /* specular term - cannibalize VP... */
240 if (ctx->Light.Model.LocalViewer) {
241 GLfloat v[3];
242 COPY_3V(v, vertex);
243 NORMALIZE_3FV(v);
244 SUB_3V(VP, VP, v); /* h = VP + VPe */
245 h = VP;
246 NORMALIZE_3FV(h);
247 }
248 else if (light->_Flags & LIGHT_POSITIONAL) {
249 h = VP;
250 ACC_3V(h, ctx->_EyeZDir);
251 NORMALIZE_3FV(h);
252 }
253 else {
254 h = light->_h_inf_norm;
255 }
256
257 n_dot_h = correction * DOT3(normal, h);
258
259 if (n_dot_h > 0.0F) {
260 GLfloat spec_coef;
261 struct gl_shine_tab *tab = ctx->_ShineTable[side];
262 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
263
264 if (spec_coef > 1.0e-10) {
265 spec_coef *= attenuation;
266 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
267 light->_MatSpecular[side]);
268 }
269 }
270 } /*loop over lights*/
271
272 FLOAT_RGB_TO_CHAN_RGB( Fcolor[j], sum[0] );
273 FLOAT_RGB_TO_CHAN_RGB( Fspec[j], spec[0] );
274 Fcolor[j][3] = sumA[0];
275
276 if (IDX & LIGHT_TWOSIDE) {
277 FLOAT_RGB_TO_CHAN_RGB( Bcolor[j], sum[1] );
278 FLOAT_RGB_TO_CHAN_RGB( Bspec[j], spec[1] );
279 Bcolor[j][3] = sumA[1];
280 }
281 }
282
283 if ( CHECK_COLOR_MATERIAL(j) )
284 gl_update_color_material( ctx, CMcolor[j] );
285
286 if ( CHECK_MATERIAL(j) )
287 gl_update_material( ctx, new_material[j], new_material_mask[j] );
288
289 if ( CHECK_VALIDATE(j) )
290 gl_validate_all_lighting_tables( ctx );
291 }
292
293
294 static void TAG(light_rgba)( GLcontext *ctx,
295 struct vertex_buffer *VB,
296 struct gl_pipeline_stage *stage,
297 GLvector4f *input )
298 {
299 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
300 GLuint j;
301
302 GLfloat (*base)[3] = ctx->Light._BaseColor;
303 const GLchan *sumA = ctx->Light._BaseAlpha;
304
305 GLuint vstride = input->stride;
306 const GLfloat *vertex = (GLfloat *) input->data;
307 GLuint nstride = VB->NormalPtr->stride;
308 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
309
310 GLubyte (*CMcolor)[4];
311 GLuint CMstride;
312
313 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].data;
314 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].data;
315 GLuint *flags = VB->Flag;
316
317 struct gl_material (*new_material)[2] = VB->Material;
318 GLuint *new_material_mask = VB->MaterialMask;
319 GLuint nr = VB->Count;
320
321 (void) flags;
322 (void) nstride;
323 (void) vstride;
324
325 if (IDX & LIGHT_COLORMATERIAL) {
326 CMcolor = VB->ColorPtr[0]->data;
327 CMstride = VB->ColorPtr[0]->stride;
328 }
329
330 VB->ColorPtr[0] = &store->LitColor[0];
331 if (IDX & LIGHT_TWOSIDE)
332 VB->ColorPtr[1] = &store->LitColor[1];
333
334 if (stage->changed_inputs == 0)
335 return;
336
337 for ( j=0 ;
338 j<nr ;
339 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
340 {
341 GLfloat sum[2][3];
342 struct gl_light *light;
343
344 if ( CHECK_COLOR_MATERIAL(j) )
345 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
346
347 if ( CHECK_MATERIAL(j) )
348 gl_update_material( ctx, new_material[j], new_material_mask[j] );
349
350 if ( CHECK_VALIDATE(j) )
351 gl_validate_all_lighting_tables( ctx );
352
353 COPY_3V(sum[0], base[0]);
354
355 if ( IDX & LIGHT_TWOSIDE )
356 COPY_3V(sum[1], base[1]);
357
358 /* Add contribution from each enabled light source */
359 foreach (light, &ctx->Light.EnabledList) {
360
361 GLfloat n_dot_h;
362 GLfloat correction;
363 GLint side;
364 GLfloat contrib[3];
365 GLfloat attenuation = 1.0;
366 GLfloat VP[3]; /* unit vector from vertex to light */
367 GLfloat n_dot_VP; /* n dot VP */
368 GLfloat *h;
369
370 /* compute VP and attenuation */
371 if (!(light->_Flags & LIGHT_POSITIONAL)) {
372 /* directional light */
373 COPY_3V(VP, light->_VP_inf_norm);
374 attenuation = light->_VP_inf_spot_attenuation;
375 }
376 else {
377 GLfloat d; /* distance from vertex to light */
378
379
380 SUB_3V(VP, light->_Position, vertex);
381
382 d = LEN_3FV( VP );
383
384 if ( d > 1e-6) {
385 GLfloat invd = 1.0F / d;
386 SELF_SCALE_SCALAR_3V(VP, invd);
387 }
388
389 attenuation = 1.0F / (light->ConstantAttenuation + d *
390 (light->LinearAttenuation + d *
391 light->QuadraticAttenuation));
392
393 /* spotlight attenuation */
394 if (light->_Flags & LIGHT_SPOT) {
395 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
396
397 if (PV_dot_dir<light->_CosCutoff) {
398 continue; /* this light makes no contribution */
399 }
400 else {
401 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
402 int k = (int) x;
403 GLfloat spot = (light->_SpotExpTable[k][0]
404 + (x-k)*light->_SpotExpTable[k][1]);
405 attenuation *= spot;
406 }
407 }
408 }
409
410
411 if (attenuation < 1e-3)
412 continue; /* this light makes no contribution */
413
414
415 /* Compute dot product or normal and vector from V to light pos */
416 n_dot_VP = DOT3( normal, VP );
417
418 /* which side are we lighting? */
419 if (n_dot_VP < 0.0F) {
420 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
421
422 if (!(IDX & LIGHT_TWOSIDE))
423 continue;
424
425 side = 1;
426 correction = -1;
427 n_dot_VP = -n_dot_VP;
428 }
429 else {
430 if (IDX & LIGHT_TWOSIDE) {
431 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
432 }
433 side = 0;
434 correction = 1;
435 }
436
437 COPY_3V(contrib, light->_MatAmbient[side]);
438
439 /* diffuse term */
440 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
441
442 /* specular term - cannibalize VP... */
443 {
444 if (ctx->Light.Model.LocalViewer) {
445 GLfloat v[3];
446 COPY_3V(v, vertex);
447 NORMALIZE_3FV(v);
448 SUB_3V(VP, VP, v); /* h = VP + VPe */
449 h = VP;
450 NORMALIZE_3FV(h);
451 }
452 else if (light->_Flags & LIGHT_POSITIONAL) {
453 h = VP;
454 ACC_3V(h, ctx->_EyeZDir);
455 NORMALIZE_3FV(h);
456 }
457 else {
458 h = light->_h_inf_norm;
459 }
460
461 n_dot_h = correction * DOT3(normal, h);
462
463 if (n_dot_h > 0.0F)
464 {
465 GLfloat spec_coef;
466 struct gl_shine_tab *tab = ctx->_ShineTable[side];
467
468 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
469
470 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
471 light->_MatSpecular[side]);
472 }
473 }
474
475 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
476 }
477
478 FLOAT_RGB_TO_CHAN_RGB( Fcolor[j], sum[0] );
479 Fcolor[j][3] = sumA[0];
480
481 if (IDX & LIGHT_TWOSIDE) {
482 FLOAT_RGB_TO_CHAN_RGB( Bcolor[j], sum[1] );
483 Bcolor[j][3] = sumA[1];
484 }
485 }
486
487 if ( CHECK_COLOR_MATERIAL(j) )
488 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
489
490 if ( CHECK_MATERIAL(j) )
491 gl_update_material( ctx, new_material[j], new_material_mask[j] );
492
493 if ( CHECK_VALIDATE(j) )
494 gl_validate_all_lighting_tables( ctx );
495 }
496
497
498
499
500 /* As below, but with just a single light.
501 */
502 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
503 struct vertex_buffer *VB,
504 struct gl_pipeline_stage *stage,
505 GLvector4f *input )
506
507 {
508 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
509 GLuint nstride = VB->NormalPtr->stride;
510 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
511 GLubyte (*CMcolor)[4];
512 GLuint CMstride;
513 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].data;
514 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].data;
515 struct gl_light *light = ctx->Light.EnabledList.next;
516 GLuint *flags = VB->Flag;
517 GLchan baseubyte[2][4];
518 GLuint j = 0;
519 struct gl_material (*new_material)[2] = VB->Material;
520 GLuint *new_material_mask = VB->MaterialMask;
521 GLfloat base[2][3];
522 GLuint nr = VB->Count;
523
524 (void) input; /* doesn't refer to Eye or Obj */
525 (void) flags;
526 (void) nr;
527 (void) nstride;
528
529 if (IDX & LIGHT_COLORMATERIAL) {
530 CMcolor = VB->ColorPtr[0]->data;
531 CMstride = VB->ColorPtr[0]->stride;
532 }
533
534 VB->ColorPtr[0] = &store->LitColor[0];
535 if (IDX & LIGHT_TWOSIDE)
536 VB->ColorPtr[1] = &store->LitColor[1];
537
538 if (stage->changed_inputs == 0)
539 return;
540
541 if ( CHECK_COLOR_MATERIAL(j) )
542 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
543
544 if ( CHECK_MATERIAL(j) )
545 gl_update_material( ctx, new_material[j], new_material_mask[j] );
546
547 if ( CHECK_VALIDATE(j) )
548 gl_validate_all_lighting_tables( ctx );
549
550 baseubyte[0][3] = ctx->Light._BaseAlpha[0];
551 baseubyte[1][3] = ctx->Light._BaseAlpha[1];
552
553 do {
554 /* No attenuation, so incoporate _MatAmbient into base color.
555 */
556 {
557 COPY_3V(base[0], light->_MatAmbient[0]);
558 ACC_3V(base[0], ctx->Light._BaseColor[0] );
559 FLOAT_RGB_TO_CHAN_RGB( baseubyte[0], base[0] );
560
561 if (IDX & LIGHT_TWOSIDE) {
562 COPY_3V(base[1], light->_MatAmbient[1]);
563 ACC_3V(base[1], ctx->Light._BaseColor[1]);
564 FLOAT_RGB_TO_CHAN_RGB( baseubyte[1], base[1]);
565 }
566 }
567
568 do {
569 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
570
571 COPY_CHAN4(Fcolor[j], baseubyte[0]);
572 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], baseubyte[1]);
573
574 if (n_dot_VP < 0.0F) {
575 if (IDX & LIGHT_TWOSIDE) {
576 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
577 GLfloat sum[3];
578 COPY_3V(sum, base[1]);
579 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
580 if (n_dot_h > 0.0F) {
581 GLfloat spec;
582 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
583 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
584 }
585 FLOAT_RGB_TO_CHAN_RGB(Bcolor[j], sum );
586 }
587 } else {
588 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
589 GLfloat sum[3];
590 COPY_3V(sum, base[0]);
591 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
592 if (n_dot_h > 0.0F) {
593 GLfloat spec;
594 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
595 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
596
597 }
598 FLOAT_RGB_TO_CHAN_RGB(Fcolor[j], sum );
599 }
600
601 j++;
602 STRIDE_F(normal, NSTRIDE);
603 } while (DO_ANOTHER_NORMAL(j));
604
605
606 for ( ; REUSE_LIGHT_RESULTS(j) ; j++ ) {
607 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
608 if (IDX & LIGHT_TWOSIDE)
609 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
610 STRIDE_F(normal, NSTRIDE);
611 }
612
613 /* Have to recompute our base colors on material change.
614 */
615 if ( CHECK_MATERIAL(j) )
616 gl_update_material( ctx, new_material[j], new_material_mask[j] );
617
618 if ( CHECK_COLOR_MATERIAL(j) )
619 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
620
621 if ( CHECK_VALIDATE(j) )
622 gl_validate_all_lighting_tables( ctx );
623
624 } while (!CHECK_END_VB(j));
625 }
626
627
628 /* Light infinite lights
629 */
630 static void TAG(light_fast_rgba)( GLcontext *ctx,
631 struct vertex_buffer *VB,
632 struct gl_pipeline_stage *stage,
633 GLvector4f *input )
634 {
635 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
636 const GLchan *sumA = ctx->Light._BaseAlpha;
637 GLuint nstride = VB->NormalPtr->stride;
638 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
639 GLubyte (*CMcolor)[4];
640 GLuint CMstride;
641 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].data;
642 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].data;
643 GLuint *flags = VB->Flag;
644 GLuint j = 0;
645 struct gl_material (*new_material)[2] = VB->Material;
646 GLuint *new_material_mask = VB->MaterialMask;
647 GLuint nr = VB->Count;
648 struct gl_light *light;
649
650 (void) flags;
651 (void) input;
652 (void) nr;
653 (void) nstride;
654
655 if (IDX & LIGHT_COLORMATERIAL) {
656 CMcolor = VB->ColorPtr[0]->data;
657 CMstride = VB->ColorPtr[0]->stride;
658 }
659
660 VB->ColorPtr[0] = &store->LitColor[0];
661 if (IDX & LIGHT_TWOSIDE)
662 VB->ColorPtr[1] = &store->LitColor[1];
663
664 if ( CHECK_COLOR_MATERIAL(j) )
665 gl_update_color_material( ctx, *CMcolor );
666
667 if ( CHECK_MATERIAL(j) )
668 gl_update_material( ctx, new_material[j], new_material_mask[j] );
669
670 if ( CHECK_VALIDATE(j) )
671 gl_validate_all_lighting_tables( ctx );
672
673 do {
674 do {
675 GLfloat sum[2][3];
676
677 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
678 if (IDX & LIGHT_TWOSIDE)
679 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
680
681 foreach (light, &ctx->Light.EnabledList) {
682 GLfloat n_dot_h, n_dot_VP, spec;
683
684 ACC_3V(sum[0], light->_MatAmbient[0]);
685 if (IDX & LIGHT_TWOSIDE)
686 ACC_3V(sum[1], light->_MatAmbient[1]);
687
688 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
689
690 if (n_dot_VP > 0.0F) {
691 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
692 n_dot_h = DOT3(normal, light->_h_inf_norm);
693 if (n_dot_h > 0.0F) {
694 struct gl_shine_tab *tab = ctx->_ShineTable[0];
695 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
696 ACC_SCALE_SCALAR_3V( sum[0], spec,
697 light->_MatSpecular[0]);
698 }
699 }
700 else if (IDX & LIGHT_TWOSIDE) {
701 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
702 n_dot_h = -DOT3(normal, light->_h_inf_norm);
703 if (n_dot_h > 0.0F) {
704 struct gl_shine_tab *tab = ctx->_ShineTable[1];
705 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
706 ACC_SCALE_SCALAR_3V( sum[1], spec,
707 light->_MatSpecular[1]);
708 }
709 }
710 }
711
712 FLOAT_RGB_TO_CHAN_RGB( Fcolor[j], sum[0] );
713 Fcolor[j][3] = sumA[0];
714
715 if (IDX & LIGHT_TWOSIDE) {
716 FLOAT_RGB_TO_CHAN_RGB( Bcolor[j], sum[1] );
717 Bcolor[j][3] = sumA[1];
718 }
719
720 j++;
721 STRIDE_F(normal, NSTRIDE);
722 } while (DO_ANOTHER_NORMAL(j));
723
724 /* Reuse the shading results while there is no change to
725 * normal or material values.
726 */
727 for ( ; REUSE_LIGHT_RESULTS(j) ; j++ ) {
728 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
729 if (IDX & LIGHT_TWOSIDE)
730 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
731 STRIDE_F(normal, NSTRIDE);
732 }
733
734 if ( CHECK_COLOR_MATERIAL(j) )
735 gl_update_color_material( ctx, CMcolor[j] );
736
737 if ( CHECK_MATERIAL(j) )
738 gl_update_material( ctx, new_material[j], new_material_mask[j] );
739
740 if ( CHECK_VALIDATE(j) )
741 gl_validate_all_lighting_tables( ctx );
742
743 } while (!CHECK_END_VB(j));
744 }
745
746
747
748
749
750 /*
751 * Use current lighting/material settings to compute the color indexes
752 * for an array of vertices.
753 * Input: n - number of vertices to light
754 * side - 0=use front material, 1=use back material
755 * vertex - array of [n] vertex position in eye coordinates
756 * normal - array of [n] surface normal vector
757 * Output: indexResult - resulting array of [n] color indexes
758 */
759 static void TAG(light_ci)( GLcontext *ctx,
760 struct vertex_buffer *VB,
761 struct gl_pipeline_stage *stage,
762 GLvector4f *input )
763 {
764 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
765 GLuint j;
766 GLuint vstride = input->stride;
767 const GLfloat *vertex = (GLfloat *) input->data;
768 GLuint nstride = VB->NormalPtr->stride;
769 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
770 GLubyte (*CMcolor)[4];
771 GLuint CMstride;
772 GLuint *flags = VB->Flag;
773 GLuint *indexResult[2];
774 struct gl_material (*new_material)[2] = VB->Material;
775 GLuint *new_material_mask = VB->MaterialMask;
776 GLuint nr = VB->Count;
777
778 (void) flags;
779 (void) nstride;
780 (void) vstride;
781
782 VB->IndexPtr[0] = &store->LitIndex[0];
783 if (IDX & LIGHT_TWOSIDE)
784 VB->IndexPtr[1] = &store->LitIndex[1];
785
786 indexResult[0] = VB->IndexPtr[0]->data;
787 indexResult[1] = VB->IndexPtr[1]->data;
788
789 if (IDX & LIGHT_COLORMATERIAL) {
790 CMcolor = VB->ColorPtr[0]->data;
791 CMstride = VB->ColorPtr[0]->stride;
792 }
793
794 /* loop over vertices */
795 for ( j=0 ;
796 j<nr ;
797 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
798 {
799 GLfloat diffuse[2], specular[2];
800 GLuint side = 0;
801 struct gl_light *light;
802
803 if ( CHECK_COLOR_MATERIAL(j) )
804 gl_update_color_material( ctx, (GLchan *)CMcolor[j] );
805
806 if ( CHECK_MATERIAL(j) )
807 gl_update_material( ctx, new_material[j], new_material_mask[j] );
808
809 if ( CHECK_VALIDATE(j) )
810 gl_validate_all_lighting_tables( ctx );
811
812 diffuse[0] = specular[0] = 0.0F;
813
814 if ( IDX & LIGHT_TWOSIDE ) {
815 diffuse[1] = specular[1] = 0.0F;
816 }
817
818 /* Accumulate diffuse and specular from each light source */
819 foreach (light, &ctx->Light.EnabledList) {
820
821 GLfloat attenuation = 1.0F;
822 GLfloat VP[3]; /* unit vector from vertex to light */
823 GLfloat n_dot_VP; /* dot product of l and n */
824 GLfloat *h, n_dot_h, correction = 1.0;
825
826 /* compute l and attenuation */
827 if (!(light->_Flags & LIGHT_POSITIONAL)) {
828 /* directional light */
829 COPY_3V(VP, light->_VP_inf_norm);
830 }
831 else {
832 GLfloat d; /* distance from vertex to light */
833
834 SUB_3V(VP, light->_Position, vertex);
835
836 d = LEN_3FV( VP );
837 if ( d > 1e-6) {
838 GLfloat invd = 1.0F / d;
839 SELF_SCALE_SCALAR_3V(VP, invd);
840 }
841
842 attenuation = 1.0F / (light->ConstantAttenuation + d *
843 (light->LinearAttenuation + d *
844 light->QuadraticAttenuation));
845
846 /* spotlight attenuation */
847 if (light->_Flags & LIGHT_SPOT) {
848 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
849 if (PV_dot_dir<light->_CosCutoff) {
850 continue; /* this light makes no contribution */
851 }
852 else {
853 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
854 int k = (int) x;
855 GLfloat spot = (light->_SpotExpTable[k][0]
856 + (x-k)*light->_SpotExpTable[k][1]);
857 attenuation *= spot;
858 }
859 }
860 }
861
862 if (attenuation < 1e-3)
863 continue; /* this light makes no contribution */
864
865 n_dot_VP = DOT3( normal, VP );
866
867 /* which side are we lighting? */
868 if (n_dot_VP < 0.0F) {
869 if (!(IDX & LIGHT_TWOSIDE))
870 continue;
871 side = 1;
872 correction = -1;
873 n_dot_VP = -n_dot_VP;
874 }
875
876 /* accumulate diffuse term */
877 diffuse[side] += n_dot_VP * light->_dli * attenuation;
878
879 /* specular term */
880 if (ctx->Light.Model.LocalViewer) {
881 GLfloat v[3];
882 COPY_3V(v, vertex);
883 NORMALIZE_3FV(v);
884 SUB_3V(VP, VP, v); /* h = VP + VPe */
885 h = VP;
886 NORMALIZE_3FV(h);
887 }
888 else if (light->_Flags & LIGHT_POSITIONAL) {
889 h = VP;
890 ACC_3V(h, ctx->_EyeZDir);
891 NORMALIZE_3FV(h);
892 }
893 else {
894 h = light->_h_inf_norm;
895 }
896
897 n_dot_h = correction * DOT3(normal, h);
898
899 if (n_dot_h > 0.0F)
900 {
901 GLfloat spec_coef;
902 struct gl_shine_tab *tab = ctx->_ShineTable[side];
903 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
904 specular[side] += spec_coef * light->_sli * attenuation;
905 }
906 } /*loop over lights*/
907
908 /* Now compute final color index */
909 for (side = 0 ; side < NR_SIDES ; side++) {
910 struct gl_material *mat = &ctx->Light.Material[side];
911 GLfloat index;
912
913 if (specular[side] > 1.0F) {
914 index = mat->SpecularIndex;
915 }
916 else {
917 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
918 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
919
920 index = mat->AmbientIndex
921 + diffuse[side] * (1.0F-specular[side]) * d_a
922 + specular[side] * s_a;
923
924 if (index > mat->SpecularIndex) {
925 index = mat->SpecularIndex;
926 }
927 }
928 indexResult[side][j] = (GLuint) (GLint) index;
929 }
930 } /*for vertex*/
931
932 if ( CHECK_COLOR_MATERIAL(j) )
933 gl_update_color_material( ctx, CMcolor[j] );
934
935 if ( CHECK_MATERIAL(j) )
936 gl_update_material( ctx, new_material[j], new_material_mask[j] );
937
938 if ( CHECK_VALIDATE(j) )
939 gl_validate_all_lighting_tables( ctx );
940 }
941
942
943
944 static void TAG(init_light_tab)( void )
945 {
946 _tnl_light_tab[IDX] = TAG(light_rgba);
947 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
948 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
949 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
950 _tnl_light_ci_tab[IDX] = TAG(light_ci);
951 }
952
953
954 #undef TAG
955 #undef IDX
956 #undef NR_SIDES
957 #undef NSTRIDE
958 #undef VSTRIDE
959 #undef CHECK_MATERIAL
960 #undef CHECK_END_VB
961 #undef DO_ANOTHER_NORMAL
962 #undef REUSE_LIGHT_RESULTS
963 #undef CMSTRIDE
964 #undef CHECK_COLOR_MATERIAL
965 #undef CHECK_VALIDATE