Clean-up/renaming of the per-vertex attribute bits, specifically, the
[mesa.git] / src / mesa / tnl / t_vb_lighttmp.h
1 /* $Id: t_vb_lighttmp.h,v 1.24 2002/01/22 14:35:17 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
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 nstride /*(3 * sizeof(GLfloat))*/
36 # define CHECK_MATERIAL(x) (flags[x] & VERT_BIT_MATERIAL)
37 # define CHECK_END_VB(x) (flags[x] & VERT_BIT_END_VB)
38 # if (IDX & LIGHT_COLORMATERIAL)
39 # define CMSTRIDE STRIDE_F(CMcolor, CMstride)
40 # define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0)
41 # define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL))
42 # define DO_ANOTHER_NORMAL(x) \
43 ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
44 # define REUSE_LIGHT_RESULTS(x) \
45 ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
46 # else
47 # define CMSTRIDE (void)0
48 # define CHECK_COLOR_MATERIAL(x) 0
49 # define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL))
50 # define DO_ANOTHER_NORMAL(x) \
51 ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
52 # define REUSE_LIGHT_RESULTS(x) \
53 ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_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 /* define TRACE if to trace lighting code */
84
85
86 /*
87 * ctx is the current context
88 * VB is the vertex buffer
89 * stage is the lighting stage-private data
90 * input is the vector of eye or object-space vertex coordinates
91 */
92 static void TAG(light_rgba_spec)( GLcontext *ctx,
93 struct vertex_buffer *VB,
94 struct gl_pipeline_stage *stage,
95 GLvector4f *input )
96 {
97 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
98 GLfloat (*base)[3] = ctx->Light._BaseColor;
99 GLchan sumA[2];
100 GLuint j;
101
102 const GLuint vstride = input->stride;
103 const GLfloat *vertex = (GLfloat *)input->data;
104 const GLuint nstride = VB->NormalPtr->stride;
105 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
106
107 GLfloat *CMcolor;
108 GLuint CMstride;
109
110 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
111 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
112 GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
113 GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
114
115 const GLuint nr = VB->Count;
116 const GLuint *flags = VB->Flag;
117 struct gl_material (*new_material)[2] = VB->Material;
118 const GLuint *new_material_mask = VB->MaterialMask;
119
120 (void) flags;
121 (void) nstride;
122 (void) vstride;
123
124 #ifdef TRACE
125 fprintf(stderr, "%s\n", __FUNCTION__ );
126 #endif
127
128 if (IDX & LIGHT_COLORMATERIAL) {
129 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
130 VB->ColorPtr[0]->Size != 4)
131 import_color_material( ctx, stage );
132
133 CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
134 CMstride = VB->ColorPtr[0]->StrideB;
135 }
136
137 VB->ColorPtr[0] = &store->LitColor[0];
138 VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
139 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
140
141 if (IDX & LIGHT_TWOSIDE) {
142 VB->ColorPtr[1] = &store->LitColor[1];
143 VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
144 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
145 }
146
147 /* Side-effects done, can we finish now?
148 */
149 if (stage->changed_inputs == 0)
150 return;
151
152 for ( j=0 ;
153 j<nr ;
154 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
155 {
156 GLfloat sum[2][3], spec[2][3];
157 struct gl_light *light;
158
159 if ( CHECK_COLOR_MATERIAL(j) )
160 _mesa_update_color_material( ctx, CMcolor );
161
162 if ( CHECK_MATERIAL(j) )
163 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
164
165 if ( CHECK_VALIDATE(j) ) {
166 _mesa_validate_all_lighting_tables( ctx );
167 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
168 if (IDX & LIGHT_TWOSIDE)
169 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
170 }
171
172 COPY_3V(sum[0], base[0]);
173 ZERO_3V(spec[0]);
174
175 if (IDX & LIGHT_TWOSIDE) {
176 COPY_3V(sum[1], base[1]);
177 ZERO_3V(spec[1]);
178 }
179
180 /* Add contribution from each enabled light source */
181 foreach (light, &ctx->Light.EnabledList) {
182 GLfloat n_dot_h;
183 GLfloat correction;
184 GLint side;
185 GLfloat contrib[3];
186 GLfloat attenuation;
187 GLfloat VP[3]; /* unit vector from vertex to light */
188 GLfloat n_dot_VP; /* n dot VP */
189 GLfloat *h;
190
191 /* compute VP and attenuation */
192 if (!(light->_Flags & LIGHT_POSITIONAL)) {
193 /* directional light */
194 COPY_3V(VP, light->_VP_inf_norm);
195 attenuation = light->_VP_inf_spot_attenuation;
196 }
197 else {
198 GLfloat d; /* distance from vertex to light */
199
200 SUB_3V(VP, light->_Position, vertex);
201
202 d = (GLfloat) LEN_3FV( VP );
203
204 if (d > 1e-6) {
205 GLfloat invd = 1.0F / d;
206 SELF_SCALE_SCALAR_3V(VP, invd);
207 }
208
209 attenuation = 1.0F / (light->ConstantAttenuation + d *
210 (light->LinearAttenuation + d *
211 light->QuadraticAttenuation));
212
213 /* spotlight attenuation */
214 if (light->_Flags & LIGHT_SPOT) {
215 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
216
217 if (PV_dot_dir<light->_CosCutoff) {
218 continue; /* this light makes no contribution */
219 }
220 else {
221 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
222 GLint k = (GLint) x;
223 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
224 + (x-k)*light->_SpotExpTable[k][1]);
225 attenuation *= spot;
226 }
227 }
228 }
229
230 if (attenuation < 1e-3)
231 continue; /* this light makes no contribution */
232
233 /* Compute dot product or normal and vector from V to light pos */
234 n_dot_VP = DOT3( normal, VP );
235
236 /* Which side gets the diffuse & specular terms? */
237 if (n_dot_VP < 0.0F) {
238 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
239 if (!(IDX & LIGHT_TWOSIDE)) {
240 continue;
241 }
242 side = 1;
243 correction = -1;
244 n_dot_VP = -n_dot_VP;
245 }
246 else {
247 if (IDX & LIGHT_TWOSIDE) {
248 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
249 }
250 side = 0;
251 correction = 1;
252 }
253
254 /* diffuse term */
255 COPY_3V(contrib, light->_MatAmbient[side]);
256 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
257 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
258
259 /* specular term - cannibalize VP... */
260 if (ctx->Light.Model.LocalViewer) {
261 GLfloat v[3];
262 COPY_3V(v, vertex);
263 NORMALIZE_3FV(v);
264 SUB_3V(VP, VP, v); /* h = VP + VPe */
265 h = VP;
266 NORMALIZE_3FV(h);
267 }
268 else if (light->_Flags & LIGHT_POSITIONAL) {
269 h = VP;
270 ACC_3V(h, ctx->_EyeZDir);
271 NORMALIZE_3FV(h);
272 }
273 else {
274 h = light->_h_inf_norm;
275 }
276
277 n_dot_h = correction * DOT3(normal, h);
278
279 if (n_dot_h > 0.0F) {
280 GLfloat spec_coef;
281 struct gl_shine_tab *tab = ctx->_ShineTable[side];
282 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
283
284 if (spec_coef > 1.0e-10) {
285 spec_coef *= attenuation;
286 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
287 light->_MatSpecular[side]);
288 }
289 }
290 } /*loop over lights*/
291
292 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
293 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
294 Fcolor[j][3] = sumA[0];
295
296 if (IDX & LIGHT_TWOSIDE) {
297 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
298 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
299 Bcolor[j][3] = sumA[1];
300 }
301 }
302 }
303
304
305 static void TAG(light_rgba)( GLcontext *ctx,
306 struct vertex_buffer *VB,
307 struct gl_pipeline_stage *stage,
308 GLvector4f *input )
309 {
310 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
311 GLuint j;
312
313 GLfloat (*base)[3] = ctx->Light._BaseColor;
314 GLchan sumA[2];
315
316 const GLuint vstride = input->stride;
317 const GLfloat *vertex = (GLfloat *) input->data;
318 const GLuint nstride = VB->NormalPtr->stride;
319 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
320
321 GLfloat *CMcolor;
322 GLuint CMstride;
323
324 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
325 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
326 GLchan (*color[2])[4];
327 const GLuint *flags = VB->Flag;
328
329 struct gl_material (*new_material)[2] = VB->Material;
330 const GLuint *new_material_mask = VB->MaterialMask;
331 const GLuint nr = VB->Count;
332
333 #ifdef TRACE
334 fprintf(stderr, "%s\n", __FUNCTION__ );
335 #endif
336
337 (void) flags;
338 (void) nstride;
339 (void) vstride;
340
341 color[0] = Fcolor;
342 color[1] = Bcolor;
343
344 if (IDX & LIGHT_COLORMATERIAL) {
345 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
346 VB->ColorPtr[0]->Size != 4)
347 import_color_material( ctx, stage );
348
349 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
350 CMstride = VB->ColorPtr[0]->StrideB;
351 }
352
353 VB->ColorPtr[0] = &store->LitColor[0];
354 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
355
356 if (IDX & LIGHT_TWOSIDE) {
357 VB->ColorPtr[1] = &store->LitColor[1];
358 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
359 }
360
361 if (stage->changed_inputs == 0)
362 return;
363
364 for ( j=0 ;
365 j<nr ;
366 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
367 {
368 GLfloat sum[2][3];
369 struct gl_light *light;
370
371 if ( CHECK_COLOR_MATERIAL(j) )
372 _mesa_update_color_material( ctx, CMcolor );
373
374 if ( CHECK_MATERIAL(j) )
375 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
376
377 if ( CHECK_VALIDATE(j) ) {
378 _mesa_validate_all_lighting_tables( ctx );
379 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
380 if (IDX & LIGHT_TWOSIDE)
381 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
382 }
383
384 COPY_3V(sum[0], base[0]);
385
386 if ( IDX & LIGHT_TWOSIDE )
387 COPY_3V(sum[1], base[1]);
388
389 /* Add contribution from each enabled light source */
390 foreach (light, &ctx->Light.EnabledList) {
391
392 GLfloat n_dot_h;
393 GLfloat correction;
394 GLint side;
395 GLfloat contrib[3];
396 GLfloat attenuation = 1.0;
397 GLfloat VP[3]; /* unit vector from vertex to light */
398 GLfloat n_dot_VP; /* n dot VP */
399 GLfloat *h;
400
401 /* compute VP and attenuation */
402 if (!(light->_Flags & LIGHT_POSITIONAL)) {
403 /* directional light */
404 COPY_3V(VP, light->_VP_inf_norm);
405 attenuation = light->_VP_inf_spot_attenuation;
406 }
407 else {
408 GLfloat d; /* distance from vertex to light */
409
410
411 SUB_3V(VP, light->_Position, vertex);
412
413 d = (GLfloat) LEN_3FV( VP );
414
415 if ( d > 1e-6) {
416 GLfloat invd = 1.0F / d;
417 SELF_SCALE_SCALAR_3V(VP, invd);
418 }
419
420 attenuation = 1.0F / (light->ConstantAttenuation + d *
421 (light->LinearAttenuation + d *
422 light->QuadraticAttenuation));
423
424 /* spotlight attenuation */
425 if (light->_Flags & LIGHT_SPOT) {
426 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
427
428 if (PV_dot_dir<light->_CosCutoff) {
429 continue; /* this light makes no contribution */
430 }
431 else {
432 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
433 GLint k = (GLint) x;
434 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
435 + (x-k)*light->_SpotExpTable[k][1]);
436 attenuation *= spot;
437 }
438 }
439 }
440
441 if (attenuation < 1e-3)
442 continue; /* this light makes no contribution */
443
444 /* Compute dot product or normal and vector from V to light pos */
445 n_dot_VP = DOT3( normal, VP );
446
447 /* which side are we lighting? */
448 if (n_dot_VP < 0.0F) {
449 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
450
451 if (!(IDX & LIGHT_TWOSIDE))
452 continue;
453
454 side = 1;
455 correction = -1;
456 n_dot_VP = -n_dot_VP;
457 }
458 else {
459 if (IDX & LIGHT_TWOSIDE) {
460 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
461 }
462 side = 0;
463 correction = 1;
464 }
465
466 COPY_3V(contrib, light->_MatAmbient[side]);
467
468 /* diffuse term */
469 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
470
471 /* specular term - cannibalize VP... */
472 {
473 if (ctx->Light.Model.LocalViewer) {
474 GLfloat v[3];
475 COPY_3V(v, vertex);
476 NORMALIZE_3FV(v);
477 SUB_3V(VP, VP, v); /* h = VP + VPe */
478 h = VP;
479 NORMALIZE_3FV(h);
480 }
481 else if (light->_Flags & LIGHT_POSITIONAL) {
482 h = VP;
483 ACC_3V(h, ctx->_EyeZDir);
484 NORMALIZE_3FV(h);
485 }
486 else {
487 h = light->_h_inf_norm;
488 }
489
490 n_dot_h = correction * DOT3(normal, h);
491
492 if (n_dot_h > 0.0F)
493 {
494 GLfloat spec_coef;
495 struct gl_shine_tab *tab = ctx->_ShineTable[side];
496
497 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
498
499 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
500 light->_MatSpecular[side]);
501 }
502 }
503
504 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
505 }
506
507 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
508 Fcolor[j][3] = sumA[0];
509
510 if (IDX & LIGHT_TWOSIDE) {
511 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
512 Bcolor[j][3] = sumA[1];
513 }
514 }
515 }
516
517
518
519
520 /* As below, but with just a single light.
521 */
522 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
523 struct vertex_buffer *VB,
524 struct gl_pipeline_stage *stage,
525 GLvector4f *input )
526
527 {
528 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
529 const GLuint nstride = VB->NormalPtr->stride;
530 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
531 GLfloat *CMcolor;
532 GLuint CMstride;
533 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
534 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
535 const struct gl_light *light = ctx->Light.EnabledList.next;
536 const GLuint *flags = VB->Flag;
537 GLchan basechan[2][4];
538 GLuint j = 0;
539 struct gl_material (*new_material)[2] = VB->Material;
540 const GLuint *new_material_mask = VB->MaterialMask;
541 GLfloat base[2][3];
542 const GLuint nr = VB->Count;
543
544 #ifdef TRACE
545 fprintf(stderr, "%s\n", __FUNCTION__ );
546 #endif
547
548 (void) input; /* doesn't refer to Eye or Obj */
549 (void) flags;
550 (void) nr;
551 (void) nstride;
552
553 if (IDX & LIGHT_COLORMATERIAL) {
554 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
555 VB->ColorPtr[0]->Size != 4)
556 import_color_material( ctx, stage );
557
558 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
559 CMstride = VB->ColorPtr[0]->StrideB;
560 }
561
562 VB->ColorPtr[0] = &store->LitColor[0];
563 if (IDX & LIGHT_TWOSIDE)
564 VB->ColorPtr[1] = &store->LitColor[1];
565
566 if (stage->changed_inputs == 0)
567 return;
568
569 do {
570
571 if ( CHECK_COLOR_MATERIAL(j) ) {
572 _mesa_update_color_material( ctx, CMcolor );
573 }
574
575 if ( CHECK_MATERIAL(j) )
576 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
577
578 if ( CHECK_VALIDATE(j) )
579 _mesa_validate_all_lighting_tables( ctx );
580
581
582 /* No attenuation, so incoporate _MatAmbient into base color.
583 */
584 COPY_3V(base[0], light->_MatAmbient[0]);
585 ACC_3V(base[0], ctx->Light._BaseColor[0] );
586 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
587 UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3],
588 ctx->Light.Material[0].Diffuse[3]);
589
590 if (IDX & LIGHT_TWOSIDE) {
591 COPY_3V(base[1], light->_MatAmbient[1]);
592 ACC_3V(base[1], ctx->Light._BaseColor[1]);
593 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
594 UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3],
595 ctx->Light.Material[1].Diffuse[3]);
596 }
597
598 do {
599 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
600
601 if (n_dot_VP < 0.0F) {
602 if (IDX & LIGHT_TWOSIDE) {
603 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
604 GLfloat sum[3];
605 COPY_3V(sum, base[1]);
606 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
607 if (n_dot_h > 0.0F) {
608 GLfloat spec;
609 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
610 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
611 }
612 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
613 Bcolor[j][3] = basechan[1][3];
614 }
615 COPY_CHAN4(Fcolor[j], basechan[0]);
616 }
617 else {
618 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
619 GLfloat sum[3];
620 COPY_3V(sum, base[0]);
621 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
622 if (n_dot_h > 0.0F) {
623 GLfloat spec;
624 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
625 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
626
627 }
628 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
629 Fcolor[j][3] = basechan[0][3];
630 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
631 }
632
633 j++;
634 CMSTRIDE;
635 STRIDE_F(normal, NSTRIDE);
636 } while (DO_ANOTHER_NORMAL(j));
637
638
639 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
640 {
641 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
642 if (IDX & LIGHT_TWOSIDE)
643 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
644 }
645
646 } while (!CHECK_END_VB(j));
647 }
648
649
650 /* Light infinite lights
651 */
652 static void TAG(light_fast_rgba)( GLcontext *ctx,
653 struct vertex_buffer *VB,
654 struct gl_pipeline_stage *stage,
655 GLvector4f *input )
656 {
657 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
658 GLchan sumA[2];
659 const GLuint nstride = VB->NormalPtr->stride;
660 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
661 GLfloat *CMcolor;
662 GLuint CMstride;
663 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
664 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
665 const GLuint *flags = VB->Flag;
666 GLuint j = 0;
667 struct gl_material (*new_material)[2] = VB->Material;
668 GLuint *new_material_mask = VB->MaterialMask;
669 const GLuint nr = VB->Count;
670 const struct gl_light *light;
671
672 #ifdef TRACE
673 fprintf(stderr, "%s\n", __FUNCTION__ );
674 #endif
675
676 (void) flags;
677 (void) input;
678 (void) nr;
679 (void) nstride;
680
681 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
682 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
683
684 if (IDX & LIGHT_COLORMATERIAL) {
685 if (VB->ColorPtr[0]->Type != GL_FLOAT ||
686 VB->ColorPtr[0]->Size != 4)
687 import_color_material( ctx, stage );
688
689 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
690 CMstride = VB->ColorPtr[0]->StrideB;
691 }
692
693 VB->ColorPtr[0] = &store->LitColor[0];
694 if (IDX & LIGHT_TWOSIDE)
695 VB->ColorPtr[1] = &store->LitColor[1];
696
697 if (stage->changed_inputs == 0)
698 return;
699
700 do {
701 do {
702 GLfloat sum[2][3];
703
704 if ( CHECK_COLOR_MATERIAL(j) )
705 _mesa_update_color_material( ctx, CMcolor );
706
707 if ( CHECK_MATERIAL(j) )
708 _mesa_update_material( ctx, new_material[j], new_material_mask[j] );
709
710 if ( CHECK_VALIDATE(j) ) {
711 _mesa_validate_all_lighting_tables( ctx );
712 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
713 if (IDX & LIGHT_TWOSIDE)
714 UNCLAMPED_FLOAT_TO_CHAN(sumA[1],
715 ctx->Light.Material[1].Diffuse[3]);
716 }
717
718
719 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
720 if (IDX & LIGHT_TWOSIDE)
721 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
722
723 foreach (light, &ctx->Light.EnabledList) {
724 GLfloat n_dot_h, n_dot_VP, spec;
725
726 ACC_3V(sum[0], light->_MatAmbient[0]);
727 if (IDX & LIGHT_TWOSIDE)
728 ACC_3V(sum[1], light->_MatAmbient[1]);
729
730 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
731
732 if (n_dot_VP > 0.0F) {
733 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
734 n_dot_h = DOT3(normal, light->_h_inf_norm);
735 if (n_dot_h > 0.0F) {
736 struct gl_shine_tab *tab = ctx->_ShineTable[0];
737 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
738 ACC_SCALE_SCALAR_3V( sum[0], spec,
739 light->_MatSpecular[0]);
740 }
741 }
742 else if (IDX & LIGHT_TWOSIDE) {
743 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
744 n_dot_h = -DOT3(normal, light->_h_inf_norm);
745 if (n_dot_h > 0.0F) {
746 struct gl_shine_tab *tab = ctx->_ShineTable[1];
747 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
748 ACC_SCALE_SCALAR_3V( sum[1], spec,
749 light->_MatSpecular[1]);
750 }
751 }
752 }
753
754 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
755 Fcolor[j][3] = sumA[0];
756
757 if (IDX & LIGHT_TWOSIDE) {
758 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
759 Bcolor[j][3] = sumA[1];
760 }
761
762 j++;
763 CMSTRIDE;
764 STRIDE_F(normal, NSTRIDE);
765 } while (DO_ANOTHER_NORMAL(j));
766
767 /* Reuse the shading results while there is no change to
768 * normal or material values.
769 */
770 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
771 {
772 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
773 if (IDX & LIGHT_TWOSIDE)
774 COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
775 }
776
777 } while (!CHECK_END_VB(j));
778 }
779
780
781
782
783
784 /*
785 * Use current lighting/material settings to compute the color indexes
786 * for an array of vertices.
787 * Input: n - number of vertices to light
788 * side - 0=use front material, 1=use back material
789 * vertex - array of [n] vertex position in eye coordinates
790 * normal - array of [n] surface normal vector
791 * Output: indexResult - resulting array of [n] color indexes
792 */
793 static void TAG(light_ci)( GLcontext *ctx,
794 struct vertex_buffer *VB,
795 struct gl_pipeline_stage *stage,
796 GLvector4f *input )
797 {
798 struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
799 GLuint j;
800 const GLuint vstride = input->stride;
801 const GLfloat *vertex = (GLfloat *) input->data;
802 const GLuint nstride = VB->NormalPtr->stride;
803 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
804 GLfloat *CMcolor;
805 GLuint CMstride;
806 const GLuint *flags = VB->Flag;
807 GLuint *indexResult[2];
808 struct gl_material (*new_material)[2] = VB->Material;
809 GLuint *new_material_mask = VB->MaterialMask;
810 const GLuint nr = VB->Count;
811
812 #ifdef TRACE
813 fprintf(stderr, "%s\n", __FUNCTION__ );
814 #endif
815
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