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