Killed mmath.[ch]. Moved low-level functions/assembly code into imports.[ch]
[mesa.git] / src / mesa / main / light.c
1 /* $Id: light.c,v 1.55 2003/03/01 01:50:21 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 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
28 #include "glheader.h"
29 #include "imports.h"
30 #include "colormac.h"
31 #include "context.h"
32 #include "enums.h"
33 #include "light.h"
34 #include "macros.h"
35 #include "simple_list.h"
36 #include "mtypes.h"
37 #include "math/m_xform.h"
38 #include "math/m_matrix.h"
39
40
41 /* XXX this is a bit of a hack needed for compilation within XFree86 */
42 #ifndef FLT_MIN
43 #define FLT_MIN 1e-37
44 #endif
45
46
47 void
48 _mesa_ShadeModel( GLenum mode )
49 {
50 GET_CURRENT_CONTEXT(ctx);
51 ASSERT_OUTSIDE_BEGIN_END(ctx);
52
53 if (MESA_VERBOSE & VERBOSE_API)
54 _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode));
55
56 if (mode != GL_FLAT && mode != GL_SMOOTH) {
57 _mesa_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
58 return;
59 }
60
61 if (ctx->Light.ShadeModel == mode)
62 return;
63
64 FLUSH_VERTICES(ctx, _NEW_LIGHT);
65 ctx->Light.ShadeModel = mode;
66 ctx->_TriangleCaps ^= DD_FLATSHADE;
67 if (ctx->Driver.ShadeModel)
68 (*ctx->Driver.ShadeModel)( ctx, mode );
69 }
70
71
72
73 void
74 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
75 {
76 _mesa_Lightfv( light, pname, &param );
77 }
78
79
80 void
81 _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
82 {
83 GET_CURRENT_CONTEXT(ctx);
84 GLint i = (GLint) (light - GL_LIGHT0);
85 struct gl_light *l = &ctx->Light.Light[i];
86
87 if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
88 _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
89 return;
90 }
91
92 switch (pname) {
93 case GL_AMBIENT:
94 if (TEST_EQ_4V(l->Ambient, params))
95 return;
96 FLUSH_VERTICES(ctx, _NEW_LIGHT);
97 COPY_4V( l->Ambient, params );
98 break;
99 case GL_DIFFUSE:
100 if (TEST_EQ_4V(l->Diffuse, params))
101 return;
102 FLUSH_VERTICES(ctx, _NEW_LIGHT);
103 COPY_4V( l->Diffuse, params );
104 break;
105 case GL_SPECULAR:
106 if (TEST_EQ_4V(l->Specular, params))
107 return;
108 FLUSH_VERTICES(ctx, _NEW_LIGHT);
109 COPY_4V( l->Specular, params );
110 break;
111 case GL_POSITION: {
112 GLfloat tmp[4];
113 /* transform position by ModelView matrix */
114 TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->m, params );
115 if (TEST_EQ_4V(l->EyePosition, tmp))
116 return;
117 FLUSH_VERTICES(ctx, _NEW_LIGHT);
118 COPY_4V(l->EyePosition, tmp);
119 if (l->EyePosition[3] != 0.0F)
120 l->_Flags |= LIGHT_POSITIONAL;
121 else
122 l->_Flags &= ~LIGHT_POSITIONAL;
123 break;
124 }
125 case GL_SPOT_DIRECTION: {
126 GLfloat tmp[4];
127 /* transform direction by inverse modelview */
128 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
129 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
130 }
131 TRANSFORM_NORMAL( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
132 if (TEST_EQ_3V(l->EyeDirection, tmp))
133 return;
134 FLUSH_VERTICES(ctx, _NEW_LIGHT);
135 COPY_3V(l->EyeDirection, tmp);
136 break;
137 }
138 case GL_SPOT_EXPONENT:
139 if (params[0]<0.0 || params[0]>128.0) {
140 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
141 return;
142 }
143 if (l->SpotExponent == params[0])
144 return;
145 FLUSH_VERTICES(ctx, _NEW_LIGHT);
146 l->SpotExponent = params[0];
147 _mesa_invalidate_spot_exp_table( l );
148 break;
149 case GL_SPOT_CUTOFF:
150 if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
151 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
152 return;
153 }
154 if (l->SpotCutoff == params[0])
155 return;
156 FLUSH_VERTICES(ctx, _NEW_LIGHT);
157 l->SpotCutoff = params[0];
158 l->_CosCutoff = (GLfloat) _mesa_cos(params[0]*DEG2RAD);
159 if (l->_CosCutoff < 0)
160 l->_CosCutoff = 0;
161 if (l->SpotCutoff != 180.0F)
162 l->_Flags |= LIGHT_SPOT;
163 else
164 l->_Flags &= ~LIGHT_SPOT;
165 break;
166 case GL_CONSTANT_ATTENUATION:
167 if (params[0]<0.0) {
168 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
169 return;
170 }
171 if (l->ConstantAttenuation == params[0])
172 return;
173 FLUSH_VERTICES(ctx, _NEW_LIGHT);
174 l->ConstantAttenuation = params[0];
175 break;
176 case GL_LINEAR_ATTENUATION:
177 if (params[0]<0.0) {
178 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
179 return;
180 }
181 if (l->LinearAttenuation == params[0])
182 return;
183 FLUSH_VERTICES(ctx, _NEW_LIGHT);
184 l->LinearAttenuation = params[0];
185 break;
186 case GL_QUADRATIC_ATTENUATION:
187 if (params[0]<0.0) {
188 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
189 return;
190 }
191 if (l->QuadraticAttenuation == params[0])
192 return;
193 FLUSH_VERTICES(ctx, _NEW_LIGHT);
194 l->QuadraticAttenuation = params[0];
195 break;
196 default:
197 _mesa_error( ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname );
198 return;
199 }
200
201 if (ctx->Driver.Lightfv)
202 ctx->Driver.Lightfv( ctx, light, pname, params );
203 }
204
205
206 void
207 _mesa_Lighti( GLenum light, GLenum pname, GLint param )
208 {
209 _mesa_Lightiv( light, pname, &param );
210 }
211
212
213 void
214 _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
215 {
216 GLfloat fparam[4];
217
218 switch (pname) {
219 case GL_AMBIENT:
220 case GL_DIFFUSE:
221 case GL_SPECULAR:
222 fparam[0] = INT_TO_FLOAT( params[0] );
223 fparam[1] = INT_TO_FLOAT( params[1] );
224 fparam[2] = INT_TO_FLOAT( params[2] );
225 fparam[3] = INT_TO_FLOAT( params[3] );
226 break;
227 case GL_POSITION:
228 fparam[0] = (GLfloat) params[0];
229 fparam[1] = (GLfloat) params[1];
230 fparam[2] = (GLfloat) params[2];
231 fparam[3] = (GLfloat) params[3];
232 break;
233 case GL_SPOT_DIRECTION:
234 fparam[0] = (GLfloat) params[0];
235 fparam[1] = (GLfloat) params[1];
236 fparam[2] = (GLfloat) params[2];
237 break;
238 case GL_SPOT_EXPONENT:
239 case GL_SPOT_CUTOFF:
240 case GL_CONSTANT_ATTENUATION:
241 case GL_LINEAR_ATTENUATION:
242 case GL_QUADRATIC_ATTENUATION:
243 fparam[0] = (GLfloat) params[0];
244 break;
245 default:
246 /* error will be caught later in gl_Lightfv */
247 ;
248 }
249
250 _mesa_Lightfv( light, pname, fparam );
251 }
252
253
254
255 void
256 _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
257 {
258 GET_CURRENT_CONTEXT(ctx);
259 GLint l = (GLint) (light - GL_LIGHT0);
260 ASSERT_OUTSIDE_BEGIN_END(ctx);
261
262 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
263 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
264 return;
265 }
266
267 switch (pname) {
268 case GL_AMBIENT:
269 COPY_4V( params, ctx->Light.Light[l].Ambient );
270 break;
271 case GL_DIFFUSE:
272 COPY_4V( params, ctx->Light.Light[l].Diffuse );
273 break;
274 case GL_SPECULAR:
275 COPY_4V( params, ctx->Light.Light[l].Specular );
276 break;
277 case GL_POSITION:
278 COPY_4V( params, ctx->Light.Light[l].EyePosition );
279 break;
280 case GL_SPOT_DIRECTION:
281 COPY_3V( params, ctx->Light.Light[l].EyeDirection );
282 break;
283 case GL_SPOT_EXPONENT:
284 params[0] = ctx->Light.Light[l].SpotExponent;
285 break;
286 case GL_SPOT_CUTOFF:
287 params[0] = ctx->Light.Light[l].SpotCutoff;
288 break;
289 case GL_CONSTANT_ATTENUATION:
290 params[0] = ctx->Light.Light[l].ConstantAttenuation;
291 break;
292 case GL_LINEAR_ATTENUATION:
293 params[0] = ctx->Light.Light[l].LinearAttenuation;
294 break;
295 case GL_QUADRATIC_ATTENUATION:
296 params[0] = ctx->Light.Light[l].QuadraticAttenuation;
297 break;
298 default:
299 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
300 break;
301 }
302 }
303
304
305
306 void
307 _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
308 {
309 GET_CURRENT_CONTEXT(ctx);
310 GLint l = (GLint) (light - GL_LIGHT0);
311 ASSERT_OUTSIDE_BEGIN_END(ctx);
312
313 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
314 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
315 return;
316 }
317
318 switch (pname) {
319 case GL_AMBIENT:
320 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
321 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
322 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
323 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
324 break;
325 case GL_DIFFUSE:
326 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
327 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
328 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
329 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
330 break;
331 case GL_SPECULAR:
332 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
333 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
334 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
335 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
336 break;
337 case GL_POSITION:
338 params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
339 params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
340 params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
341 params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
342 break;
343 case GL_SPOT_DIRECTION:
344 params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
345 params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
346 params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
347 break;
348 case GL_SPOT_EXPONENT:
349 params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
350 break;
351 case GL_SPOT_CUTOFF:
352 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
353 break;
354 case GL_CONSTANT_ATTENUATION:
355 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
356 break;
357 case GL_LINEAR_ATTENUATION:
358 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
359 break;
360 case GL_QUADRATIC_ATTENUATION:
361 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
362 break;
363 default:
364 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
365 break;
366 }
367 }
368
369
370
371 /**********************************************************************/
372 /*** Light Model ***/
373 /**********************************************************************/
374
375
376 void
377 _mesa_LightModelfv( GLenum pname, const GLfloat *params )
378 {
379 GLenum newenum;
380 GLboolean newbool;
381 GET_CURRENT_CONTEXT(ctx);
382 ASSERT_OUTSIDE_BEGIN_END(ctx);
383
384 switch (pname) {
385 case GL_LIGHT_MODEL_AMBIENT:
386 if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
387 return;
388 FLUSH_VERTICES(ctx, _NEW_LIGHT);
389 COPY_4V( ctx->Light.Model.Ambient, params );
390 break;
391 case GL_LIGHT_MODEL_LOCAL_VIEWER:
392 newbool = (params[0]!=0.0);
393 if (ctx->Light.Model.LocalViewer == newbool)
394 return;
395 FLUSH_VERTICES(ctx, _NEW_LIGHT);
396 ctx->Light.Model.LocalViewer = newbool;
397 break;
398 case GL_LIGHT_MODEL_TWO_SIDE:
399 newbool = (params[0]!=0.0);
400 if (ctx->Light.Model.TwoSide == newbool)
401 return;
402 FLUSH_VERTICES(ctx, _NEW_LIGHT);
403 ctx->Light.Model.TwoSide = newbool;
404
405 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
406 ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
407 else
408 ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
409 break;
410 case GL_LIGHT_MODEL_COLOR_CONTROL:
411 if (params[0] == (GLfloat) GL_SINGLE_COLOR)
412 newenum = GL_SINGLE_COLOR;
413 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
414 newenum = GL_SEPARATE_SPECULAR_COLOR;
415 else {
416 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
417 (GLint) params[0] );
418 return;
419 }
420 if (ctx->Light.Model.ColorControl == newenum)
421 return;
422 FLUSH_VERTICES(ctx, _NEW_LIGHT);
423 ctx->Light.Model.ColorControl = newenum;
424
425 if ((ctx->Light.Enabled &&
426 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
427 || ctx->Fog.ColorSumEnabled)
428 ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR;
429 else
430 ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR;
431
432 break;
433 default:
434 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
435 break;
436 }
437
438 if (ctx->Driver.LightModelfv)
439 ctx->Driver.LightModelfv( ctx, pname, params );
440 }
441
442
443 void
444 _mesa_LightModeliv( GLenum pname, const GLint *params )
445 {
446 GLfloat fparam[4];
447
448 switch (pname) {
449 case GL_LIGHT_MODEL_AMBIENT:
450 fparam[0] = INT_TO_FLOAT( params[0] );
451 fparam[1] = INT_TO_FLOAT( params[1] );
452 fparam[2] = INT_TO_FLOAT( params[2] );
453 fparam[3] = INT_TO_FLOAT( params[3] );
454 break;
455 case GL_LIGHT_MODEL_LOCAL_VIEWER:
456 case GL_LIGHT_MODEL_TWO_SIDE:
457 case GL_LIGHT_MODEL_COLOR_CONTROL:
458 fparam[0] = (GLfloat) params[0];
459 break;
460 default:
461 /* Error will be caught later in gl_LightModelfv */
462 ;
463 }
464 _mesa_LightModelfv( pname, fparam );
465 }
466
467
468 void
469 _mesa_LightModeli( GLenum pname, GLint param )
470 {
471 _mesa_LightModeliv( pname, &param );
472 }
473
474
475 void
476 _mesa_LightModelf( GLenum pname, GLfloat param )
477 {
478 _mesa_LightModelfv( pname, &param );
479 }
480
481
482
483 /********** MATERIAL **********/
484
485
486 /*
487 * Given a face and pname value (ala glColorMaterial), compute a bitmask
488 * of the targeted material values.
489 */
490 GLuint
491 _mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
492 GLuint legal, const char *where )
493 {
494 GLuint bitmask = 0;
495
496 /* Make a bitmask indicating what material attribute(s) we're updating */
497 switch (pname) {
498 case GL_EMISSION:
499 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
500 break;
501 case GL_AMBIENT:
502 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
503 break;
504 case GL_DIFFUSE:
505 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
506 break;
507 case GL_SPECULAR:
508 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
509 break;
510 case GL_SHININESS:
511 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
512 break;
513 case GL_AMBIENT_AND_DIFFUSE:
514 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
515 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
516 break;
517 case GL_COLOR_INDEXES:
518 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
519 break;
520 default:
521 _mesa_error( ctx, GL_INVALID_ENUM, where );
522 return 0;
523 }
524
525 if (face==GL_FRONT) {
526 bitmask &= FRONT_MATERIAL_BITS;
527 }
528 else if (face==GL_BACK) {
529 bitmask &= BACK_MATERIAL_BITS;
530 }
531 else if (face != GL_FRONT_AND_BACK) {
532 _mesa_error( ctx, GL_INVALID_ENUM, where );
533 return 0;
534 }
535
536 if (bitmask & ~legal) {
537 _mesa_error( ctx, GL_INVALID_ENUM, where );
538 return 0;
539 }
540
541 return bitmask;
542 }
543
544
545 /* Perform a straight copy between pairs of materials.
546 */
547 void _mesa_copy_material_pairs( struct gl_material dst[2],
548 const struct gl_material src[2],
549 GLuint bitmask )
550 {
551 if (bitmask & FRONT_EMISSION_BIT) {
552 COPY_4FV( dst[0].Emission, src[0].Emission );
553 }
554 if (bitmask & BACK_EMISSION_BIT) {
555 COPY_4FV( dst[1].Emission, src[1].Emission );
556 }
557 if (bitmask & FRONT_AMBIENT_BIT) {
558 COPY_4FV( dst[0].Ambient, src[0].Ambient );
559 }
560 if (bitmask & BACK_AMBIENT_BIT) {
561 COPY_4FV( dst[1].Ambient, src[1].Ambient );
562 }
563 if (bitmask & FRONT_DIFFUSE_BIT) {
564 COPY_4FV( dst[0].Diffuse, src[0].Diffuse );
565 }
566 if (bitmask & BACK_DIFFUSE_BIT) {
567 COPY_4FV( dst[1].Diffuse, src[1].Diffuse );
568 }
569 if (bitmask & FRONT_SPECULAR_BIT) {
570 COPY_4FV( dst[0].Specular, src[0].Specular );
571 }
572 if (bitmask & BACK_SPECULAR_BIT) {
573 COPY_4FV( dst[1].Specular, src[1].Specular );
574 }
575 if (bitmask & FRONT_SHININESS_BIT) {
576 dst[0].Shininess = src[0].Shininess;
577 }
578 if (bitmask & BACK_SHININESS_BIT) {
579 dst[1].Shininess = src[1].Shininess;
580 }
581 if (bitmask & FRONT_INDEXES_BIT) {
582 dst[0].AmbientIndex = src[0].AmbientIndex;
583 dst[0].DiffuseIndex = src[0].DiffuseIndex;
584 dst[0].SpecularIndex = src[0].SpecularIndex;
585 }
586 if (bitmask & BACK_INDEXES_BIT) {
587 dst[1].AmbientIndex = src[1].AmbientIndex;
588 dst[1].DiffuseIndex = src[1].DiffuseIndex;
589 dst[1].SpecularIndex = src[1].SpecularIndex;
590 }
591 }
592
593
594 /*
595 * Check if the global material has to be updated with info that was
596 * associated with a vertex via glMaterial.
597 * This function is used when any material values get changed between
598 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
599 * when GL_COLOR_MATERIAL is enabled.
600 *
601 * src[0] is front material, src[1] is back material
602 *
603 * Additionally keeps the precomputed lighting state uptodate.
604 */
605 void _mesa_update_material( GLcontext *ctx,
606 const struct gl_material src[2],
607 GLuint bitmask )
608 {
609 struct gl_light *light, *list = &ctx->Light.EnabledList;
610
611 if (ctx->Light.ColorMaterialEnabled)
612 bitmask &= ~ctx->Light.ColorMaterialBitmask;
613
614 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
615 _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
616
617 if (!bitmask)
618 return;
619
620 /* update material emission */
621 if (bitmask & FRONT_EMISSION_BIT) {
622 struct gl_material *mat = &ctx->Light.Material[0];
623 COPY_4FV( mat->Emission, src[0].Emission );
624 }
625 if (bitmask & BACK_EMISSION_BIT) {
626 struct gl_material *mat = &ctx->Light.Material[1];
627 COPY_4FV( mat->Emission, src[1].Emission );
628 }
629
630 /* update material ambience */
631 if (bitmask & FRONT_AMBIENT_BIT) {
632 struct gl_material *mat = &ctx->Light.Material[0];
633 COPY_4FV( mat->Ambient, src[0].Ambient );
634 foreach (light, list) {
635 SCALE_3V( light->_MatAmbient[0], light->Ambient, src[0].Ambient);
636 }
637 }
638 if (bitmask & BACK_AMBIENT_BIT) {
639 struct gl_material *mat = &ctx->Light.Material[1];
640 COPY_4FV( mat->Ambient, src[1].Ambient );
641 foreach (light, list) {
642 SCALE_3V( light->_MatAmbient[1], light->Ambient, src[1].Ambient);
643 }
644 }
645
646 /* update BaseColor = emission + scene's ambience * material's ambience */
647 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
648 struct gl_material *mat = &ctx->Light.Material[0];
649 COPY_3V( ctx->Light._BaseColor[0], mat->Emission );
650 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat->Ambient,
651 ctx->Light.Model.Ambient );
652 }
653 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
654 struct gl_material *mat = &ctx->Light.Material[1];
655 COPY_3V( ctx->Light._BaseColor[1], mat->Emission );
656 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat->Ambient,
657 ctx->Light.Model.Ambient );
658 }
659
660 /* update material diffuse values */
661 if (bitmask & FRONT_DIFFUSE_BIT) {
662 struct gl_material *mat = &ctx->Light.Material[0];
663 COPY_4FV( mat->Diffuse, src[0].Diffuse );
664 foreach (light, list) {
665 SCALE_3V( light->_MatDiffuse[0], light->Diffuse, mat->Diffuse );
666 }
667 }
668 if (bitmask & BACK_DIFFUSE_BIT) {
669 struct gl_material *mat = &ctx->Light.Material[1];
670 COPY_4FV( mat->Diffuse, src[1].Diffuse );
671 foreach (light, list) {
672 SCALE_3V( light->_MatDiffuse[1], light->Diffuse, mat->Diffuse );
673 }
674 }
675
676 /* update material specular values */
677 if (bitmask & FRONT_SPECULAR_BIT) {
678 struct gl_material *mat = &ctx->Light.Material[0];
679 COPY_4FV( mat->Specular, src[0].Specular );
680 foreach (light, list) {
681 SCALE_3V( light->_MatSpecular[0], light->Specular, mat->Specular);
682 }
683 }
684 if (bitmask & BACK_SPECULAR_BIT) {
685 struct gl_material *mat = &ctx->Light.Material[1];
686 COPY_4FV( mat->Specular, src[1].Specular );
687 foreach (light, list) {
688 SCALE_3V( light->_MatSpecular[1], light->Specular, mat->Specular);
689 }
690 }
691
692 if (bitmask & FRONT_SHININESS_BIT) {
693 ctx->Light.Material[0].Shininess = src[0].Shininess;
694 _mesa_invalidate_shine_table( ctx, 0 );
695 }
696 if (bitmask & BACK_SHININESS_BIT) {
697 ctx->Light.Material[1].Shininess = src[1].Shininess;
698 _mesa_invalidate_shine_table( ctx, 1 );
699 }
700
701 if (bitmask & FRONT_INDEXES_BIT) {
702 ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
703 ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
704 ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
705 }
706 if (bitmask & BACK_INDEXES_BIT) {
707 ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
708 ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
709 ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
710 }
711
712 if (0) {
713 struct gl_material *mat = &ctx->Light.Material[0];
714 _mesa_debug(ctx, "update_mat emission : %f %f %f\n",
715 mat->Emission[0], mat->Emission[1], mat->Emission[2]);
716 _mesa_debug(ctx, "update_mat specular : %f %f %f\n",
717 mat->Specular[0], mat->Specular[1], mat->Specular[2]);
718 _mesa_debug(ctx, "update_mat diffuse : %f %f %f\n",
719 mat->Diffuse[0], mat->Diffuse[1], mat->Diffuse[2]);
720 _mesa_debug(ctx, "update_mat ambient : %f %f %f\n",
721 mat->Ambient[0], mat->Ambient[1], mat->Ambient[2]);
722 }
723 }
724
725
726
727
728
729
730
731 /*
732 * Update the current materials from the given rgba color
733 * according to the bitmask in ColorMaterialBitmask, which is
734 * set by glColorMaterial().
735 */
736 void _mesa_update_color_material( GLcontext *ctx,
737 const GLfloat color[4] )
738 {
739 struct gl_light *light, *list = &ctx->Light.EnabledList;
740 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
741
742 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
743 _mesa_debug(ctx, "_mesa_update_color_material, mask 0x%x\n", bitmask);
744
745 /* update emissive colors */
746 if (bitmask & FRONT_EMISSION_BIT) {
747 struct gl_material *mat = &ctx->Light.Material[0];
748 COPY_4FV( mat->Emission, color );
749 }
750
751 if (bitmask & BACK_EMISSION_BIT) {
752 struct gl_material *mat = &ctx->Light.Material[1];
753 COPY_4FV( mat->Emission, color );
754 }
755
756 /* update light->_MatAmbient = light's ambient * material's ambient */
757 if (bitmask & FRONT_AMBIENT_BIT) {
758 struct gl_material *mat = &ctx->Light.Material[0];
759 foreach (light, list) {
760 SCALE_3V( light->_MatAmbient[0], light->Ambient, color);
761 }
762 COPY_4FV( mat->Ambient, color );
763 }
764
765 if (bitmask & BACK_AMBIENT_BIT) {
766 struct gl_material *mat = &ctx->Light.Material[1];
767 foreach (light, list) {
768 SCALE_3V( light->_MatAmbient[1], light->Ambient, color);
769 }
770 COPY_4FV( mat->Ambient, color );
771 }
772
773 /* update BaseColor = emission + scene's ambience * material's ambience */
774 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
775 struct gl_material *mat = &ctx->Light.Material[0];
776 COPY_3V( ctx->Light._BaseColor[0], mat->Emission );
777 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
778 }
779
780 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
781 struct gl_material *mat = &ctx->Light.Material[1];
782 COPY_3V( ctx->Light._BaseColor[1], mat->Emission );
783 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
784 }
785
786 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
787 if (bitmask & FRONT_DIFFUSE_BIT) {
788 struct gl_material *mat = &ctx->Light.Material[0];
789 COPY_4FV( mat->Diffuse, color );
790 foreach (light, list) {
791 SCALE_3V( light->_MatDiffuse[0], light->Diffuse, mat->Diffuse );
792 }
793 }
794
795 if (bitmask & BACK_DIFFUSE_BIT) {
796 struct gl_material *mat = &ctx->Light.Material[1];
797 COPY_4FV( mat->Diffuse, color );
798 foreach (light, list) {
799 SCALE_3V( light->_MatDiffuse[1], light->Diffuse, mat->Diffuse );
800 }
801 }
802
803 /* update light->_MatSpecular = light's specular * material's specular */
804 if (bitmask & FRONT_SPECULAR_BIT) {
805 struct gl_material *mat = &ctx->Light.Material[0];
806 COPY_4FV( mat->Specular, color );
807 foreach (light, list) {
808 ACC_SCALE_3V( light->_MatSpecular[0], light->Specular, mat->Specular);
809 }
810 }
811
812 if (bitmask & BACK_SPECULAR_BIT) {
813 struct gl_material *mat = &ctx->Light.Material[1];
814 COPY_4FV( mat->Specular, color );
815 foreach (light, list) {
816 ACC_SCALE_3V( light->_MatSpecular[1], light->Specular, mat->Specular);
817 }
818 }
819
820 if (0) {
821 struct gl_material *mat = &ctx->Light.Material[0];
822 _mesa_debug(ctx, "update_color_mat emission : %f %f %f\n",
823 mat->Emission[0], mat->Emission[1], mat->Emission[2]);
824 _mesa_debug(ctx, "update_color_mat specular : %f %f %f\n",
825 mat->Specular[0], mat->Specular[1], mat->Specular[2]);
826 _mesa_debug(ctx, "update_color_mat diffuse : %f %f %f\n",
827 mat->Diffuse[0], mat->Diffuse[1], mat->Diffuse[2]);
828 _mesa_debug(ctx, "update_color_mat ambient : %f %f %f\n",
829 mat->Ambient[0], mat->Ambient[1], mat->Ambient[2]);
830 }
831 }
832
833
834
835
836 void
837 _mesa_ColorMaterial( GLenum face, GLenum mode )
838 {
839 GET_CURRENT_CONTEXT(ctx);
840 GLuint bitmask;
841 GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
842 FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
843 FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
844 FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
845 ASSERT_OUTSIDE_BEGIN_END(ctx);
846
847 if (MESA_VERBOSE&VERBOSE_API)
848 _mesa_debug(ctx, "glColorMaterial %s %s\n",
849 _mesa_lookup_enum_by_nr(face),
850 _mesa_lookup_enum_by_nr(mode));
851
852 bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
853
854 if (ctx->Light.ColorMaterialBitmask == bitmask &&
855 ctx->Light.ColorMaterialFace == face &&
856 ctx->Light.ColorMaterialMode == mode)
857 return;
858
859 FLUSH_VERTICES(ctx, _NEW_LIGHT);
860 ctx->Light.ColorMaterialBitmask = bitmask;
861 ctx->Light.ColorMaterialFace = face;
862 ctx->Light.ColorMaterialMode = mode;
863
864 if (ctx->Light.ColorMaterialEnabled) {
865 FLUSH_CURRENT( ctx, 0 );
866 _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
867 }
868
869 if (ctx->Driver.ColorMaterial)
870 (*ctx->Driver.ColorMaterial)( ctx, face, mode );
871 }
872
873
874
875
876
877 void
878 _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
879 {
880 GET_CURRENT_CONTEXT(ctx);
881 GLuint f;
882 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
883
884 if (face==GL_FRONT) {
885 f = 0;
886 }
887 else if (face==GL_BACK) {
888 f = 1;
889 }
890 else {
891 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
892 return;
893 }
894 switch (pname) {
895 case GL_AMBIENT:
896 COPY_4FV( params, ctx->Light.Material[f].Ambient );
897 break;
898 case GL_DIFFUSE:
899 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
900 break;
901 case GL_SPECULAR:
902 COPY_4FV( params, ctx->Light.Material[f].Specular );
903 break;
904 case GL_EMISSION:
905 COPY_4FV( params, ctx->Light.Material[f].Emission );
906 break;
907 case GL_SHININESS:
908 *params = ctx->Light.Material[f].Shininess;
909 break;
910 case GL_COLOR_INDEXES:
911 params[0] = ctx->Light.Material[f].AmbientIndex;
912 params[1] = ctx->Light.Material[f].DiffuseIndex;
913 params[2] = ctx->Light.Material[f].SpecularIndex;
914 break;
915 default:
916 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
917 }
918 }
919
920
921
922 void
923 _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
924 {
925 GET_CURRENT_CONTEXT(ctx);
926 GLuint f;
927 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
928
929 if (face==GL_FRONT) {
930 f = 0;
931 }
932 else if (face==GL_BACK) {
933 f = 1;
934 }
935 else {
936 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
937 return;
938 }
939 switch (pname) {
940 case GL_AMBIENT:
941 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
942 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
943 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
944 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
945 break;
946 case GL_DIFFUSE:
947 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
948 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
949 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
950 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
951 break;
952 case GL_SPECULAR:
953 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
954 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
955 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
956 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
957 break;
958 case GL_EMISSION:
959 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
960 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
961 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
962 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
963 break;
964 case GL_SHININESS:
965 *params = IROUND( ctx->Light.Material[f].Shininess );
966 break;
967 case GL_COLOR_INDEXES:
968 params[0] = IROUND( ctx->Light.Material[f].AmbientIndex );
969 params[1] = IROUND( ctx->Light.Material[f].DiffuseIndex );
970 params[2] = IROUND( ctx->Light.Material[f].SpecularIndex );
971 break;
972 default:
973 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
974 }
975 }
976
977
978
979
980 /**********************************************************************/
981 /***** Lighting computation *****/
982 /**********************************************************************/
983
984
985 /*
986 * Notes:
987 * When two-sided lighting is enabled we compute the color (or index)
988 * for both the front and back side of the primitive. Then, when the
989 * orientation of the facet is later learned, we can determine which
990 * color (or index) to use for rendering.
991 *
992 * KW: We now know orientation in advance and only shade for
993 * the side or sides which are actually required.
994 *
995 * Variables:
996 * n = normal vector
997 * V = vertex position
998 * P = light source position
999 * Pe = (0,0,0,1)
1000 *
1001 * Precomputed:
1002 * IF P[3]==0 THEN
1003 * // light at infinity
1004 * IF local_viewer THEN
1005 * _VP_inf_norm = unit vector from V to P // Precompute
1006 * ELSE
1007 * // eye at infinity
1008 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1009 * ENDIF
1010 * ENDIF
1011 *
1012 * Functions:
1013 * Normalize( v ) = normalized vector v
1014 * Magnitude( v ) = length of vector v
1015 */
1016
1017
1018
1019 /*
1020 * Whenever the spotlight exponent for a light changes we must call
1021 * this function to recompute the exponent lookup table.
1022 */
1023 void
1024 _mesa_invalidate_spot_exp_table( struct gl_light *l )
1025 {
1026 l->_SpotExpTable[0][0] = -1;
1027 }
1028
1029 static void validate_spot_exp_table( struct gl_light *l )
1030 {
1031 GLint i;
1032 GLdouble exponent = l->SpotExponent;
1033 GLdouble tmp = 0;
1034 GLint clamp = 0;
1035
1036 l->_SpotExpTable[0][0] = 0.0;
1037
1038 for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
1039 if (clamp == 0) {
1040 tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
1041 if (tmp < FLT_MIN * 100.0) {
1042 tmp = 0.0;
1043 clamp = 1;
1044 }
1045 }
1046 l->_SpotExpTable[i][0] = (GLfloat) tmp;
1047 }
1048 for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
1049 l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] -
1050 l->_SpotExpTable[i][0]);
1051 }
1052 l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
1053 }
1054
1055
1056
1057
1058 /* Calculate a new shine table. Doing this here saves a branch in
1059 * lighting, and the cost of doing it early may be partially offset
1060 * by keeping a MRU cache of shine tables for various shine values.
1061 */
1062 void
1063 _mesa_invalidate_shine_table( GLcontext *ctx, GLuint i )
1064 {
1065 if (ctx->_ShineTable[i])
1066 ctx->_ShineTable[i]->refcount--;
1067 ctx->_ShineTable[i] = 0;
1068 }
1069
1070 static void validate_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
1071 {
1072 struct gl_shine_tab *list = ctx->_ShineTabList;
1073 struct gl_shine_tab *s;
1074
1075 foreach(s, list)
1076 if ( s->shininess == shininess )
1077 break;
1078
1079 if (s == list) {
1080 GLint j;
1081 GLfloat *m;
1082
1083 foreach(s, list)
1084 if (s->refcount == 0)
1085 break;
1086
1087 m = s->tab;
1088 m[0] = 0.0;
1089 if (shininess == 0.0) {
1090 for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
1091 m[j] = 1.0;
1092 }
1093 else {
1094 for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
1095 GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
1096 if (x < 0.005) /* underflow check */
1097 x = 0.005;
1098 t = _mesa_pow(x, shininess);
1099 if (t > 1e-20)
1100 m[j] = (GLfloat) t;
1101 else
1102 m[j] = 0.0;
1103 }
1104 m[SHINE_TABLE_SIZE] = 1.0;
1105 }
1106
1107 s->shininess = shininess;
1108 }
1109
1110 if (ctx->_ShineTable[i])
1111 ctx->_ShineTable[i]->refcount--;
1112
1113 ctx->_ShineTable[i] = s;
1114 move_to_tail( list, s );
1115 s->refcount++;
1116 }
1117
1118 void
1119 _mesa_validate_all_lighting_tables( GLcontext *ctx )
1120 {
1121 GLint i;
1122 GLfloat shininess;
1123
1124 shininess = ctx->Light.Material[0].Shininess;
1125 if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess)
1126 validate_shine_table( ctx, 0, shininess );
1127
1128 shininess = ctx->Light.Material[1].Shininess;
1129 if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess)
1130 validate_shine_table( ctx, 1, shininess );
1131
1132 for (i = 0 ; i < MAX_LIGHTS ; i++)
1133 if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1)
1134 validate_spot_exp_table( &ctx->Light.Light[i] );
1135 }
1136
1137
1138
1139
1140 /*
1141 * Examine current lighting parameters to determine if the optimized lighting
1142 * function can be used.
1143 * Also, precompute some lighting values such as the products of light
1144 * source and material ambient, diffuse and specular coefficients.
1145 */
1146 void
1147 _mesa_update_lighting( GLcontext *ctx )
1148 {
1149 struct gl_light *light;
1150 ctx->_NeedEyeCoords &= ~NEED_EYE_LIGHT;
1151 ctx->_NeedNormals &= ~NEED_NORMALS_LIGHT;
1152 ctx->Light._Flags = 0;
1153
1154 if (!ctx->Light.Enabled)
1155 return;
1156
1157 ctx->_NeedNormals |= NEED_NORMALS_LIGHT;
1158
1159 foreach(light, &ctx->Light.EnabledList) {
1160 ctx->Light._Flags |= light->_Flags;
1161 }
1162
1163 ctx->Light._NeedVertices =
1164 ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
1165 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
1166 ctx->Light.Model.LocalViewer);
1167
1168 if ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
1169 ctx->Light.Model.LocalViewer)
1170 ctx->_NeedEyeCoords |= NEED_EYE_LIGHT;
1171
1172
1173 /* XXX: This test is overkill & needs to be fixed both for software and
1174 * hardware t&l drivers. The above should be sufficient & should
1175 * be tested to verify this.
1176 */
1177 if (ctx->Light._NeedVertices)
1178 ctx->_NeedEyeCoords |= NEED_EYE_LIGHT;
1179
1180
1181 /* Precompute some shading values. Although we reference
1182 * Light.Material here, we can get away without flushing
1183 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
1184 * are flushed, they will update the derived state at that time.
1185 */
1186 if (ctx->Visual.rgbMode) {
1187 GLuint sides = ctx->Light.Model.TwoSide ? 2 : 1;
1188 GLuint side;
1189 for (side=0; side < sides; side++) {
1190 struct gl_material *mat = &ctx->Light.Material[side];
1191
1192 COPY_3V(ctx->Light._BaseColor[side], mat->Emission);
1193 ACC_SCALE_3V(ctx->Light._BaseColor[side],
1194 ctx->Light.Model.Ambient,
1195 mat->Ambient);
1196 }
1197
1198 foreach (light, &ctx->Light.EnabledList) {
1199 for (side=0; side< sides; side++) {
1200 const struct gl_material *mat = &ctx->Light.Material[side];
1201 SCALE_3V( light->_MatDiffuse[side], light->Diffuse, mat->Diffuse );
1202 SCALE_3V( light->_MatAmbient[side], light->Ambient, mat->Ambient );
1203 SCALE_3V( light->_MatSpecular[side], light->Specular,
1204 mat->Specular);
1205 }
1206 }
1207 }
1208 else {
1209 static const GLfloat ci[3] = { .30F, .59F, .11F };
1210 foreach(light, &ctx->Light.EnabledList) {
1211 light->_dli = DOT3(ci, light->Diffuse);
1212 light->_sli = DOT3(ci, light->Specular);
1213 }
1214 }
1215 }
1216
1217
1218 /* _NEW_MODELVIEW
1219 * _NEW_LIGHT
1220 * _TNL_NEW_NEED_EYE_COORDS
1221 *
1222 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1223 * Also update on lighting space changes.
1224 */
1225 void
1226 _mesa_compute_light_positions( GLcontext *ctx )
1227 {
1228 struct gl_light *light;
1229 static const GLfloat eye_z[3] = { 0, 0, 1 };
1230
1231 if (!ctx->Light.Enabled)
1232 return;
1233
1234 if (ctx->_NeedEyeCoords) {
1235 COPY_3V( ctx->_EyeZDir, eye_z );
1236 }
1237 else {
1238 TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
1239 }
1240
1241 foreach (light, &ctx->Light.EnabledList) {
1242
1243 if (ctx->_NeedEyeCoords) {
1244 COPY_4FV( light->_Position, light->EyePosition );
1245 }
1246 else {
1247 TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
1248 light->EyePosition );
1249 }
1250
1251 if (!(light->_Flags & LIGHT_POSITIONAL)) {
1252 /* VP (VP) = Normalize( Position ) */
1253 COPY_3V( light->_VP_inf_norm, light->_Position );
1254 NORMALIZE_3FV( light->_VP_inf_norm );
1255
1256 if (!ctx->Light.Model.LocalViewer) {
1257 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1258 ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir);
1259 NORMALIZE_3FV( light->_h_inf_norm );
1260 }
1261 light->_VP_inf_spot_attenuation = 1.0;
1262 }
1263
1264 if (light->_Flags & LIGHT_SPOT) {
1265 if (ctx->_NeedEyeCoords) {
1266 COPY_3V( light->_NormDirection, light->EyeDirection );
1267 }
1268 else {
1269 TRANSFORM_NORMAL( light->_NormDirection,
1270 light->EyeDirection,
1271 ctx->ModelviewMatrixStack.Top->m);
1272 }
1273
1274 NORMALIZE_3FV( light->_NormDirection );
1275
1276 if (!(light->_Flags & LIGHT_POSITIONAL)) {
1277 GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
1278 light->_NormDirection);
1279
1280 if (PV_dot_dir > light->_CosCutoff) {
1281 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1282 int k = (int) x;
1283 light->_VP_inf_spot_attenuation =
1284 (GLfloat) (light->_SpotExpTable[k][0] +
1285 (x-k)*light->_SpotExpTable[k][1]);
1286 }
1287 else {
1288 light->_VP_inf_spot_attenuation = 0;
1289 }
1290 }
1291 }
1292 }
1293 }