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