Basic work to support deep color channels:
[mesa.git] / src / mesa / main / light.c
1 /* $Id: light.c,v 1.19 2000/10/28 18:34:48 brianp 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 "context.h"
33 #include "enums.h"
34 #include "light.h"
35 #include "macros.h"
36 #include "matrix.h"
37 #include "mem.h"
38 #include "mmath.h"
39 #include "simple_list.h"
40 #include "types.h"
41 #include "vb.h"
42 #include "xform.h"
43 #endif
44
45
46 /* XXX this is a bit of a hack needed for compilation within XFree86 */
47 #ifndef FLT_MIN
48 #define FLT_MIN 1e-37
49 #endif
50
51
52 void
53 _mesa_ShadeModel( GLenum mode )
54 {
55 GET_CURRENT_CONTEXT(ctx);
56 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel");
57
58 if (MESA_VERBOSE & VERBOSE_API)
59 fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode));
60
61 if (mode == GL_FLAT || mode == GL_SMOOTH) {
62 if (ctx->Light.ShadeModel != mode) {
63 ctx->Light.ShadeModel = mode;
64 if (ctx->Light.ShadeModel == GL_FLAT)
65 SET_BITS(ctx->TriangleCaps, DD_FLATSHADE);
66 else
67 CLEAR_BITS(ctx->TriangleCaps, DD_FLATSHADE);
68 ctx->NewState |= NEW_RASTER_OPS;
69 if (ctx->Driver.ShadeModel)
70 (*ctx->Driver.ShadeModel)( ctx, mode );
71 }
72 }
73 else {
74 gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
75 }
76 }
77
78
79
80 void
81 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
82 {
83 _mesa_Lightfv( light, pname, &param );
84 }
85
86
87 void
88 _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
89 {
90 GET_CURRENT_CONTEXT(ctx);
91 GLint l;
92 GLint nParams;
93
94 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight");
95
96 l = (GLint) (light - GL_LIGHT0);
97
98 if (l < 0 || l >= MAX_LIGHTS) {
99 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
100 return;
101 }
102
103 switch (pname) {
104 case GL_AMBIENT:
105 COPY_4V( ctx->Light.Light[l].Ambient, params );
106 nParams = 4;
107 break;
108 case GL_DIFFUSE:
109 COPY_4V( ctx->Light.Light[l].Diffuse, params );
110 nParams = 4;
111 break;
112 case GL_SPECULAR:
113 COPY_4V( ctx->Light.Light[l].Specular, params );
114 nParams = 4;
115 break;
116 case GL_POSITION:
117 /* transform position by ModelView matrix */
118 TRANSFORM_POINT( ctx->Light.Light[l].EyePosition,
119 ctx->ModelView.m,
120 params );
121 nParams = 4;
122 break;
123 case GL_SPOT_DIRECTION:
124 /* transform direction by inverse modelview */
125 if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
126 gl_matrix_analyze( &ctx->ModelView );
127 }
128 TRANSFORM_NORMAL( ctx->Light.Light[l].EyeDirection,
129 params,
130 ctx->ModelView.inv );
131 nParams = 3;
132 break;
133 case GL_SPOT_EXPONENT:
134 if (params[0]<0.0 || params[0]>128.0) {
135 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
136 return;
137 }
138 if (ctx->Light.Light[l].SpotExponent != params[0]) {
139 ctx->Light.Light[l].SpotExponent = params[0];
140 gl_compute_spot_exp_table( &ctx->Light.Light[l] );
141 }
142 nParams = 1;
143 break;
144 case GL_SPOT_CUTOFF:
145 if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
146 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
147 return;
148 }
149 ctx->Light.Light[l].SpotCutoff = params[0];
150 ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
151 if (ctx->Light.Light[l].CosCutoff < 0)
152 ctx->Light.Light[l].CosCutoff = 0;
153 nParams = 1;
154 break;
155 case GL_CONSTANT_ATTENUATION:
156 if (params[0]<0.0) {
157 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
158 return;
159 }
160 ctx->Light.Light[l].ConstantAttenuation = params[0];
161 nParams = 1;
162 break;
163 case GL_LINEAR_ATTENUATION:
164 if (params[0]<0.0) {
165 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
166 return;
167 }
168 ctx->Light.Light[l].LinearAttenuation = params[0];
169 nParams = 1;
170 break;
171 case GL_QUADRATIC_ATTENUATION:
172 if (params[0]<0.0) {
173 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
174 return;
175 }
176 ctx->Light.Light[l].QuadraticAttenuation = params[0];
177 nParams = 1;
178 break;
179 default:
180 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
181 return;
182 }
183
184 if (ctx->Driver.Lightfv)
185 ctx->Driver.Lightfv( ctx, light, pname, params, nParams );
186
187 ctx->NewState |= NEW_LIGHTING;
188 }
189
190
191 void
192 _mesa_Lighti( GLenum light, GLenum pname, GLint param )
193 {
194 _mesa_Lightiv( light, pname, &param );
195 }
196
197
198 void
199 _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
200 {
201 GLfloat fparam[4];
202
203 switch (pname) {
204 case GL_AMBIENT:
205 case GL_DIFFUSE:
206 case GL_SPECULAR:
207 fparam[0] = INT_TO_FLOAT( params[0] );
208 fparam[1] = INT_TO_FLOAT( params[1] );
209 fparam[2] = INT_TO_FLOAT( params[2] );
210 fparam[3] = INT_TO_FLOAT( params[3] );
211 break;
212 case GL_POSITION:
213 fparam[0] = (GLfloat) params[0];
214 fparam[1] = (GLfloat) params[1];
215 fparam[2] = (GLfloat) params[2];
216 fparam[3] = (GLfloat) params[3];
217 break;
218 case GL_SPOT_DIRECTION:
219 fparam[0] = (GLfloat) params[0];
220 fparam[1] = (GLfloat) params[1];
221 fparam[2] = (GLfloat) params[2];
222 break;
223 case GL_SPOT_EXPONENT:
224 case GL_SPOT_CUTOFF:
225 case GL_CONSTANT_ATTENUATION:
226 case GL_LINEAR_ATTENUATION:
227 case GL_QUADRATIC_ATTENUATION:
228 fparam[0] = (GLfloat) params[0];
229 break;
230 default:
231 /* error will be caught later in gl_Lightfv */
232 ;
233 }
234
235 _mesa_Lightfv( light, pname, fparam );
236 }
237
238
239
240 void
241 _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
242 {
243 GET_CURRENT_CONTEXT(ctx);
244 GLint l = (GLint) (light - GL_LIGHT0);
245
246 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
247
248 if (l<0 || l>=MAX_LIGHTS) {
249 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
250 return;
251 }
252
253 switch (pname) {
254 case GL_AMBIENT:
255 COPY_4V( params, ctx->Light.Light[l].Ambient );
256 break;
257 case GL_DIFFUSE:
258 COPY_4V( params, ctx->Light.Light[l].Diffuse );
259 break;
260 case GL_SPECULAR:
261 COPY_4V( params, ctx->Light.Light[l].Specular );
262 break;
263 case GL_POSITION:
264 COPY_4V( params, ctx->Light.Light[l].EyePosition );
265 break;
266 case GL_SPOT_DIRECTION:
267 COPY_3V( params, ctx->Light.Light[l].EyeDirection );
268 break;
269 case GL_SPOT_EXPONENT:
270 params[0] = ctx->Light.Light[l].SpotExponent;
271 break;
272 case GL_SPOT_CUTOFF:
273 params[0] = ctx->Light.Light[l].SpotCutoff;
274 break;
275 case GL_CONSTANT_ATTENUATION:
276 params[0] = ctx->Light.Light[l].ConstantAttenuation;
277 break;
278 case GL_LINEAR_ATTENUATION:
279 params[0] = ctx->Light.Light[l].LinearAttenuation;
280 break;
281 case GL_QUADRATIC_ATTENUATION:
282 params[0] = ctx->Light.Light[l].QuadraticAttenuation;
283 break;
284 default:
285 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
286 break;
287 }
288 }
289
290
291
292 void
293 _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
294 {
295 GET_CURRENT_CONTEXT(ctx);
296 GLint l = (GLint) (light - GL_LIGHT0);
297
298 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
299
300 if (l<0 || l>=MAX_LIGHTS) {
301 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
302 return;
303 }
304
305 switch (pname) {
306 case GL_AMBIENT:
307 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
308 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
309 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
310 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
311 break;
312 case GL_DIFFUSE:
313 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
314 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
315 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
316 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
317 break;
318 case GL_SPECULAR:
319 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
320 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
321 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
322 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
323 break;
324 case GL_POSITION:
325 params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
326 params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
327 params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
328 params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
329 break;
330 case GL_SPOT_DIRECTION:
331 params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
332 params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
333 params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
334 break;
335 case GL_SPOT_EXPONENT:
336 params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
337 break;
338 case GL_SPOT_CUTOFF:
339 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
340 break;
341 case GL_CONSTANT_ATTENUATION:
342 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
343 break;
344 case GL_LINEAR_ATTENUATION:
345 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
346 break;
347 case GL_QUADRATIC_ATTENUATION:
348 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
349 break;
350 default:
351 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
352 break;
353 }
354 }
355
356
357
358 /**********************************************************************/
359 /*** Light Model ***/
360 /**********************************************************************/
361
362
363 void
364 _mesa_LightModelfv( GLenum pname, const GLfloat *params )
365 {
366 GET_CURRENT_CONTEXT(ctx);
367 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModelfv");
368
369 switch (pname) {
370 case GL_LIGHT_MODEL_AMBIENT:
371 COPY_4V( ctx->Light.Model.Ambient, params );
372 break;
373 case GL_LIGHT_MODEL_LOCAL_VIEWER:
374 if (params[0]==0.0)
375 ctx->Light.Model.LocalViewer = GL_FALSE;
376 else
377 ctx->Light.Model.LocalViewer = GL_TRUE;
378 break;
379 case GL_LIGHT_MODEL_TWO_SIDE:
380 if (params[0]==0.0)
381 ctx->Light.Model.TwoSide = GL_FALSE;
382 else
383 ctx->Light.Model.TwoSide = GL_TRUE;
384 break;
385 case GL_LIGHT_MODEL_COLOR_CONTROL:
386 if (params[0] == (GLfloat) GL_SINGLE_COLOR) {
387 ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
388 if (!ctx->Fog.ColorSumEnabled)
389 CLEAR_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
390 }
391 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
392 ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
393 SET_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
394 }
395 else {
396 gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
397 }
398 ctx->NewState |= NEW_RASTER_OPS;
399 break;
400 default:
401 gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
402 break;
403 }
404
405 if (ctx->Driver.LightModelfv)
406 ctx->Driver.LightModelfv( ctx, pname, params );
407
408 ctx->NewState |= NEW_LIGHTING;
409 }
410
411
412 void
413 _mesa_LightModeliv( GLenum pname, const GLint *params )
414 {
415 GLfloat fparam[4];
416 GET_CURRENT_CONTEXT(ctx);
417 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModeliv");
418
419 switch (pname) {
420 case GL_LIGHT_MODEL_AMBIENT:
421 fparam[0] = INT_TO_FLOAT( params[0] );
422 fparam[1] = INT_TO_FLOAT( params[1] );
423 fparam[2] = INT_TO_FLOAT( params[2] );
424 fparam[3] = INT_TO_FLOAT( params[3] );
425 break;
426 case GL_LIGHT_MODEL_LOCAL_VIEWER:
427 case GL_LIGHT_MODEL_TWO_SIDE:
428 case GL_LIGHT_MODEL_COLOR_CONTROL:
429 fparam[0] = (GLfloat) params[0];
430 break;
431 default:
432 /* Error will be caught later in gl_LightModelfv */
433 ;
434 }
435 _mesa_LightModelfv( pname, fparam );
436 }
437
438
439 void
440 _mesa_LightModeli( GLenum pname, GLint param )
441 {
442 _mesa_LightModeliv( pname, &param );
443 }
444
445
446 void
447 _mesa_LightModelf( GLenum pname, GLfloat param )
448 {
449 _mesa_LightModelfv( pname, &param );
450 }
451
452
453
454 /********** MATERIAL **********/
455
456
457 /*
458 * Given a face and pname value (ala glColorMaterial), compute a bitmask
459 * of the targeted material values.
460 */
461 GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
462 GLuint legal,
463 const char *where )
464 {
465 GLuint bitmask = 0;
466
467 /* Make a bitmask indicating what material attribute(s) we're updating */
468 switch (pname) {
469 case GL_EMISSION:
470 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
471 break;
472 case GL_AMBIENT:
473 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
474 break;
475 case GL_DIFFUSE:
476 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
477 break;
478 case GL_SPECULAR:
479 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
480 break;
481 case GL_SHININESS:
482 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
483 break;
484 case GL_AMBIENT_AND_DIFFUSE:
485 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
486 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
487 break;
488 case GL_COLOR_INDEXES:
489 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
490 break;
491 default:
492 gl_error( ctx, GL_INVALID_ENUM, where );
493 return 0;
494 }
495
496 if (face==GL_FRONT) {
497 bitmask &= FRONT_MATERIAL_BITS;
498 }
499 else if (face==GL_BACK) {
500 bitmask &= BACK_MATERIAL_BITS;
501 }
502 else if (face != GL_FRONT_AND_BACK) {
503 gl_error( ctx, GL_INVALID_ENUM, where );
504 return 0;
505 }
506
507 if (bitmask & ~legal) {
508 gl_error( ctx, GL_INVALID_ENUM, where );
509 return 0;
510 }
511
512 return bitmask;
513 }
514
515
516
517 /*
518 * Check if the global material has to be updated with info that was
519 * associated with a vertex via glMaterial.
520 * This function is used when any material values get changed between
521 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
522 * when GL_COLOR_MATERIAL is enabled.
523 *
524 * src[0] is front material, src[1] is back material
525 *
526 * KW: Added code here to keep the precomputed variables uptodate.
527 * This means we can use the faster shade functions when using
528 * GL_COLOR_MATERIAL, and we can also now use the precomputed
529 * values in the slower shading functions, which further offsets
530 * the cost of doing this here.
531 */
532 void gl_update_material( GLcontext *ctx,
533 const struct gl_material src[2],
534 GLuint bitmask )
535 {
536 struct gl_light *light, *list = &ctx->Light.EnabledList;
537
538 if (ctx->Light.ColorMaterialEnabled)
539 bitmask &= ~ctx->Light.ColorMaterialBitmask;
540
541 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
542 fprintf(stderr, "gl_update_material, mask 0x%x\n", bitmask);
543
544 if (!bitmask)
545 return;
546
547 /* update material emission */
548 if (bitmask & FRONT_EMISSION_BIT) {
549 struct gl_material *mat = &ctx->Light.Material[0];
550 COPY_4FV( mat->Emission, src[0].Emission );
551 }
552 if (bitmask & BACK_EMISSION_BIT) {
553 struct gl_material *mat = &ctx->Light.Material[1];
554 COPY_4FV( mat->Emission, src[1].Emission );
555 }
556
557 /* update material ambience */
558 if (bitmask & FRONT_AMBIENT_BIT) {
559 struct gl_material *mat = &ctx->Light.Material[0];
560 COPY_4FV( mat->Ambient, src[0].Ambient );
561 foreach (light, list) {
562 SCALE_3V( light->MatAmbient[0], light->Ambient, src[0].Ambient);
563 }
564 }
565 if (bitmask & BACK_AMBIENT_BIT) {
566 struct gl_material *mat = &ctx->Light.Material[1];
567 COPY_4FV( mat->Ambient, src[1].Ambient );
568 foreach (light, list) {
569 SCALE_3V( light->MatAmbient[1], light->Ambient, src[1].Ambient);
570 }
571 }
572
573 /* update BaseColor = emission + scene's ambience * material's ambience */
574 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
575 struct gl_material *mat = &ctx->Light.Material[0];
576 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
577 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
578 }
579 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
580 struct gl_material *mat = &ctx->Light.Material[1];
581 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
582 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
583 }
584
585 /* update material diffuse values */
586 if (bitmask & FRONT_DIFFUSE_BIT) {
587 struct gl_material *mat = &ctx->Light.Material[0];
588 GLfloat tmp[4];
589 SUB_3V( tmp, src[0].Diffuse, mat->Diffuse );
590 foreach (light, list) {
591 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
592 }
593 COPY_4FV( mat->Diffuse, src[0].Diffuse );
594 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
595 }
596 if (bitmask & BACK_DIFFUSE_BIT) {
597 struct gl_material *mat = &ctx->Light.Material[1];
598 GLfloat tmp[4];
599 SUB_3V( tmp, src[1].Diffuse, mat->Diffuse );
600 foreach (light, list) {
601 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
602 }
603 COPY_4FV( mat->Diffuse, src[1].Diffuse );
604 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
605 }
606
607 /* update material specular values */
608 if (bitmask & FRONT_SPECULAR_BIT) {
609 struct gl_material *mat = &ctx->Light.Material[0];
610 GLfloat tmp[4];
611 SUB_3V( tmp, src[0].Specular, mat->Specular );
612 foreach (light, list) {
613 if (light->Flags & LIGHT_SPECULAR) {
614 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
615 light->IsMatSpecular[0] =
616 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
617 }
618 }
619 COPY_4FV( mat->Specular, src[0].Specular );
620 }
621 if (bitmask & BACK_SPECULAR_BIT) {
622 struct gl_material *mat = &ctx->Light.Material[1];
623 GLfloat tmp[4];
624 SUB_3V( tmp, src[1].Specular, mat->Specular );
625 foreach (light, list) {
626 if (light->Flags & LIGHT_SPECULAR) {
627 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
628 light->IsMatSpecular[1] =
629 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
630 }
631 }
632 COPY_4FV( mat->Specular, src[1].Specular );
633 }
634
635 if (bitmask & FRONT_SHININESS_BIT) {
636 GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess;
637 gl_compute_shine_table( ctx, 0, shininess );
638 gl_compute_shine_table( ctx, 2, shininess * .5 );
639 }
640 if (bitmask & BACK_SHININESS_BIT) {
641 GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess;
642 gl_compute_shine_table( ctx, 1, shininess );
643 gl_compute_shine_table( ctx, 3, shininess * .5 );
644 }
645
646 if (bitmask & FRONT_INDEXES_BIT) {
647 ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
648 ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
649 ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
650 }
651 if (bitmask & BACK_INDEXES_BIT) {
652 ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
653 ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
654 ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
655 }
656
657 if (0)
658 {
659 struct gl_material *mat = &ctx->Light.Material[0];
660 fprintf(stderr, "update_mat emission : %f %f %f\n",
661 mat->Emission[0],
662 mat->Emission[1],
663 mat->Emission[2]);
664 fprintf(stderr, "update_mat specular : %f %f %f\n",
665 mat->Specular[0],
666 mat->Specular[1],
667 mat->Specular[2]);
668 fprintf(stderr, "update_mat diffuse : %f %f %f\n",
669 mat->Diffuse[0],
670 mat->Diffuse[1],
671 mat->Diffuse[2]);
672 fprintf(stderr, "update_mat ambient : %f %f %f\n",
673 mat->Ambient[0],
674 mat->Ambient[1],
675 mat->Ambient[2]);
676 }
677 }
678
679
680
681
682 /*
683 * Update the current materials from the given rgba color
684 * according to the bitmask in ColorMaterialBitmask, which is
685 * set by glColorMaterial().
686 */
687 void gl_update_color_material( GLcontext *ctx,
688 const GLchan rgba[4] )
689 {
690 struct gl_light *light, *list = &ctx->Light.EnabledList;
691 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
692 GLfloat color[4];
693
694 UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
695
696 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
697 fprintf(stderr, "gl_update_color_material, mask 0x%x\n", bitmask);
698
699 /* update emissive colors */
700 if (bitmask & FRONT_EMISSION_BIT) {
701 struct gl_material *mat = &ctx->Light.Material[0];
702 COPY_4FV( mat->Emission, color );
703 }
704
705 if (bitmask & BACK_EMISSION_BIT) {
706 struct gl_material *mat = &ctx->Light.Material[1];
707 COPY_4FV( mat->Emission, color );
708 }
709
710 /* update light->MatAmbient = light's ambient * material's ambient */
711 if (bitmask & FRONT_AMBIENT_BIT) {
712 struct gl_material *mat = &ctx->Light.Material[0];
713 foreach (light, list) {
714 SCALE_3V( light->MatAmbient[0], light->Ambient, color);
715 }
716 COPY_4FV( mat->Ambient, color );
717 }
718
719 if (bitmask & BACK_AMBIENT_BIT) {
720 struct gl_material *mat = &ctx->Light.Material[1];
721 foreach (light, list) {
722 SCALE_3V( light->MatAmbient[1], light->Ambient, color);
723 }
724 COPY_4FV( mat->Ambient, color );
725 }
726
727 /* update BaseColor = emission + scene's ambience * material's ambience */
728 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
729 struct gl_material *mat = &ctx->Light.Material[0];
730 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
731 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
732 }
733
734 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
735 struct gl_material *mat = &ctx->Light.Material[1];
736 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
737 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
738 }
739
740 /* update light->MatDiffuse = light's diffuse * material's diffuse */
741 if (bitmask & FRONT_DIFFUSE_BIT) {
742 struct gl_material *mat = &ctx->Light.Material[0];
743 GLfloat tmp[4];
744 SUB_3V( tmp, color, mat->Diffuse );
745 foreach (light, list) {
746 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
747 }
748 COPY_4FV( mat->Diffuse, color );
749 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
750 }
751
752 if (bitmask & BACK_DIFFUSE_BIT) {
753 struct gl_material *mat = &ctx->Light.Material[1];
754 GLfloat tmp[4];
755 SUB_3V( tmp, color, mat->Diffuse );
756 foreach (light, list) {
757 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
758 }
759 COPY_4FV( mat->Diffuse, color );
760 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
761 }
762
763 /* update light->MatSpecular = light's specular * material's specular */
764 if (bitmask & FRONT_SPECULAR_BIT) {
765 struct gl_material *mat = &ctx->Light.Material[0];
766 GLfloat tmp[4];
767 SUB_3V( tmp, color, mat->Specular );
768 foreach (light, list) {
769 if (light->Flags & LIGHT_SPECULAR) {
770 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
771 light->IsMatSpecular[0] =
772 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
773 }
774 }
775 COPY_4FV( mat->Specular, color );
776 }
777
778 if (bitmask & BACK_SPECULAR_BIT) {
779 struct gl_material *mat = &ctx->Light.Material[1];
780 GLfloat tmp[4];
781 SUB_3V( tmp, color, mat->Specular );
782 foreach (light, list) {
783 if (light->Flags & LIGHT_SPECULAR) {
784 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
785 light->IsMatSpecular[1] =
786 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
787 }
788 }
789 COPY_4FV( mat->Specular, color );
790 }
791
792 if (0)
793 {
794 struct gl_material *mat = &ctx->Light.Material[0];
795 fprintf(stderr, "update_color_mat emission : %f %f %f\n",
796 mat->Emission[0],
797 mat->Emission[1],
798 mat->Emission[2]);
799 fprintf(stderr, "update_color_mat specular : %f %f %f\n",
800 mat->Specular[0],
801 mat->Specular[1],
802 mat->Specular[2]);
803 fprintf(stderr, "update_color_mat diffuse : %f %f %f\n",
804 mat->Diffuse[0],
805 mat->Diffuse[1],
806 mat->Diffuse[2]);
807 fprintf(stderr, "update_color_mat ambient : %f %f %f\n",
808 mat->Ambient[0],
809 mat->Ambient[1],
810 mat->Ambient[2]);
811 }
812 }
813
814
815
816
817 void
818 _mesa_ColorMaterial( GLenum face, GLenum mode )
819 {
820 GET_CURRENT_CONTEXT(ctx);
821 GLuint bitmask;
822 GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
823 FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
824 FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
825 FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
826
827 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
828
829 if (MESA_VERBOSE&VERBOSE_API)
830 fprintf(stderr, "glColorMaterial %s %s\n",
831 gl_lookup_enum_by_nr(face),
832 gl_lookup_enum_by_nr(mode));
833
834 bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
835
836 if (bitmask != 0) {
837 ctx->Light.ColorMaterialBitmask = bitmask;
838 ctx->Light.ColorMaterialFace = face;
839 ctx->Light.ColorMaterialMode = mode;
840 }
841
842 if (ctx->Light.ColorMaterialEnabled)
843 gl_update_color_material( ctx, ctx->Current.ByteColor );
844 }
845
846
847
848
849 void
850 _mesa_Materialf( GLenum face, GLenum pname, GLfloat param )
851 {
852 _mesa_Materialfv( face, pname, &param );
853 }
854
855
856 /* KW: This is now called directly (ie by name) from the glMaterial*
857 * API functions.
858 */
859 void
860 _mesa_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
861 {
862 GET_CURRENT_CONTEXT(ctx);
863 struct immediate *IM;
864 struct gl_material *mat;
865 GLuint bitmask;
866 GLuint count;
867
868 bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" );
869 if (bitmask == 0)
870 return;
871
872 IM = ctx->input;
873 count = IM->Count;
874
875 if (!IM->Material) {
876 IM->Material =
877 (struct gl_material (*)[2]) MALLOC( sizeof(struct gl_material) *
878 VB_SIZE * 2 );
879 IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * VB_SIZE );
880 }
881
882
883 if (!(IM->Flag[count] & VERT_MATERIAL)) {
884 IM->Flag[count] |= VERT_MATERIAL;
885 IM->MaterialMask[count] = 0;
886 }
887
888
889 IM->MaterialMask[count] |= bitmask;
890 mat = IM->Material[count];
891
892 if (bitmask & FRONT_AMBIENT_BIT) {
893 COPY_4FV( mat[0].Ambient, params );
894 }
895 if (bitmask & BACK_AMBIENT_BIT) {
896 COPY_4FV( mat[1].Ambient, params );
897 }
898 if (bitmask & FRONT_DIFFUSE_BIT) {
899 COPY_4FV( mat[0].Diffuse, params );
900 }
901 if (bitmask & BACK_DIFFUSE_BIT) {
902 COPY_4FV( mat[1].Diffuse, params );
903 }
904 if (bitmask & FRONT_SPECULAR_BIT) {
905 COPY_4FV( mat[0].Specular, params );
906 }
907 if (bitmask & BACK_SPECULAR_BIT) {
908 COPY_4FV( mat[1].Specular, params );
909 }
910 if (bitmask & FRONT_EMISSION_BIT) {
911 COPY_4FV( mat[0].Emission, params );
912 }
913 if (bitmask & BACK_EMISSION_BIT) {
914 COPY_4FV( mat[1].Emission, params );
915 }
916 if (bitmask & FRONT_SHININESS_BIT) {
917 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
918 mat[0].Shininess = shininess;
919 }
920 if (bitmask & BACK_SHININESS_BIT) {
921 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
922 mat[1].Shininess = shininess;
923 }
924 if (bitmask & FRONT_INDEXES_BIT) {
925 mat[0].AmbientIndex = params[0];
926 mat[0].DiffuseIndex = params[1];
927 mat[0].SpecularIndex = params[2];
928 }
929 if (bitmask & BACK_INDEXES_BIT) {
930 mat[1].AmbientIndex = params[0];
931 mat[1].DiffuseIndex = params[1];
932 mat[1].SpecularIndex = params[2];
933 }
934 }
935
936
937 void
938 _mesa_Materiali(GLenum face, GLenum pname, GLint param )
939 {
940 _mesa_Materialiv(face, pname, &param);
941 }
942
943
944 void
945 _mesa_Materialiv(GLenum face, GLenum pname, const GLint *params )
946 {
947 GLfloat fparam[4];
948 switch (pname) {
949 case GL_AMBIENT:
950 case GL_DIFFUSE:
951 case GL_SPECULAR:
952 case GL_EMISSION:
953 case GL_AMBIENT_AND_DIFFUSE:
954 fparam[0] = INT_TO_FLOAT( params[0] );
955 fparam[1] = INT_TO_FLOAT( params[1] );
956 fparam[2] = INT_TO_FLOAT( params[2] );
957 fparam[3] = INT_TO_FLOAT( params[3] );
958 break;
959 case GL_SHININESS:
960 fparam[0] = (GLfloat) params[0];
961 break;
962 case GL_COLOR_INDEXES:
963 fparam[0] = (GLfloat) params[0];
964 fparam[1] = (GLfloat) params[1];
965 fparam[2] = (GLfloat) params[2];
966 break;
967 default:
968 /* Error will be caught later in gl_Materialfv */
969 ;
970 }
971 _mesa_Materialfv(face, pname, fparam);
972 }
973
974
975 void
976 _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
977 {
978 GET_CURRENT_CONTEXT(ctx);
979 GLuint f;
980
981 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
982
983 if (face==GL_FRONT) {
984 f = 0;
985 }
986 else if (face==GL_BACK) {
987 f = 1;
988 }
989 else {
990 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
991 return;
992 }
993 switch (pname) {
994 case GL_AMBIENT:
995 COPY_4FV( params, ctx->Light.Material[f].Ambient );
996 break;
997 case GL_DIFFUSE:
998 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
999 break;
1000 case GL_SPECULAR:
1001 COPY_4FV( params, ctx->Light.Material[f].Specular );
1002 break;
1003 case GL_EMISSION:
1004 COPY_4FV( params, ctx->Light.Material[f].Emission );
1005 break;
1006 case GL_SHININESS:
1007 *params = ctx->Light.Material[f].Shininess;
1008 break;
1009 case GL_COLOR_INDEXES:
1010 params[0] = ctx->Light.Material[f].AmbientIndex;
1011 params[1] = ctx->Light.Material[f].DiffuseIndex;
1012 params[2] = ctx->Light.Material[f].SpecularIndex;
1013 break;
1014 default:
1015 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1016 }
1017 }
1018
1019
1020
1021 void
1022 _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
1023 {
1024 GET_CURRENT_CONTEXT(ctx);
1025 GLuint f;
1026
1027 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
1028
1029 if (face==GL_FRONT) {
1030 f = 0;
1031 }
1032 else if (face==GL_BACK) {
1033 f = 1;
1034 }
1035 else {
1036 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
1037 return;
1038 }
1039 switch (pname) {
1040 case GL_AMBIENT:
1041 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
1042 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
1043 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
1044 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
1045 break;
1046 case GL_DIFFUSE:
1047 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
1048 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
1049 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
1050 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
1051 break;
1052 case GL_SPECULAR:
1053 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
1054 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
1055 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
1056 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
1057 break;
1058 case GL_EMISSION:
1059 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
1060 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
1061 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
1062 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
1063 break;
1064 case GL_SHININESS:
1065 *params = ROUNDF( ctx->Light.Material[f].Shininess );
1066 break;
1067 case GL_COLOR_INDEXES:
1068 params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
1069 params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
1070 params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
1071 break;
1072 default:
1073 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1074 }
1075 }
1076
1077
1078
1079
1080 /**********************************************************************/
1081 /***** Lighting computation *****/
1082 /**********************************************************************/
1083
1084
1085 /*
1086 * Notes:
1087 * When two-sided lighting is enabled we compute the color (or index)
1088 * for both the front and back side of the primitive. Then, when the
1089 * orientation of the facet is later learned, we can determine which
1090 * color (or index) to use for rendering.
1091 *
1092 * KW: We now know orientation in advance and only shade for
1093 * the side or sides which are actually required.
1094 *
1095 * Variables:
1096 * n = normal vector
1097 * V = vertex position
1098 * P = light source position
1099 * Pe = (0,0,0,1)
1100 *
1101 * Precomputed:
1102 * IF P[3]==0 THEN
1103 * // light at infinity
1104 * IF local_viewer THEN
1105 * VP_inf_norm = unit vector from V to P // Precompute
1106 * ELSE
1107 * // eye at infinity
1108 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1109 * ENDIF
1110 * ENDIF
1111 *
1112 * Functions:
1113 * Normalize( v ) = normalized vector v
1114 * Magnitude( v ) = length of vector v
1115 */
1116
1117
1118
1119 /*
1120 * Whenever the spotlight exponent for a light changes we must call
1121 * this function to recompute the exponent lookup table.
1122 */
1123 void
1124 gl_compute_spot_exp_table( struct gl_light *l )
1125 {
1126 GLint i;
1127 GLdouble exponent = l->SpotExponent;
1128 GLdouble tmp = 0;
1129 GLint clamp = 0;
1130
1131 l->SpotExpTable[0][0] = 0.0;
1132
1133 for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
1134 if (clamp == 0) {
1135 tmp = pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
1136 if (tmp < FLT_MIN * 100.0) {
1137 tmp = 0.0;
1138 clamp = 1;
1139 }
1140 }
1141 l->SpotExpTable[i][0] = tmp;
1142 }
1143 for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
1144 l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
1145 }
1146 l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
1147 }
1148
1149
1150
1151
1152 /* Calculate a new shine table. Doing this here saves a branch in
1153 * lighting, and the cost of doing it early may be partially offset
1154 * by keeping a MRU cache of shine tables for various shine values.
1155 */
1156 static void
1157 compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
1158 {
1159 GLint i;
1160 GLfloat *m = tab->tab;
1161
1162 m[0] = 0.0;
1163 if (shininess == 0.0) {
1164 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
1165 m[i] = 1.0;
1166 }
1167 else {
1168 for (i = 1 ; i < SHINE_TABLE_SIZE ; i++) {
1169 GLdouble t = pow(i / (GLfloat) (SHINE_TABLE_SIZE - 1), shininess);
1170 if (t > 1e-20)
1171 m[i] = t;
1172 else
1173 m[i] = 0.0;
1174 }
1175 m[SHINE_TABLE_SIZE] = 1.0;
1176 }
1177
1178 tab->shininess = shininess;
1179 }
1180
1181
1182 void
1183 gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
1184 {
1185 #define DISTSQR(a,b) ((a-b)*(a-b))
1186 struct gl_shine_tab *list = ctx->ShineTabList;
1187 struct gl_shine_tab *s;
1188
1189 foreach(s, list)
1190 if ( DISTSQR(s->shininess, shininess) < 1e-4 )
1191 break;
1192
1193 if (s == list) {
1194 foreach(s, list)
1195 if (s->refcount == 0)
1196 break;
1197
1198 compute_shine_table( s, shininess );
1199 }
1200
1201 ctx->ShineTable[i]->refcount--;
1202 ctx->ShineTable[i] = s;
1203 move_to_tail( list, s );
1204 s->refcount++;
1205 #undef DISTSQR
1206 }
1207
1208
1209
1210 #if 0
1211 static void
1212 gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
1213 {
1214 GLuint i;
1215
1216 if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) {
1217 gl_compute_shine_table( ctx, 0, l->Material[0].Shininess );
1218 gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 );
1219 }
1220
1221 if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) {
1222 gl_compute_shine_table( ctx, 1, l->Material[1].Shininess );
1223 gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 );
1224 }
1225
1226 make_empty_list( &l->EnabledList );
1227 for (i = 0 ; i < MAX_LIGHTS ; i++) {
1228 if (l->Light[i].Enabled)
1229 insert_at_tail( &l->EnabledList, &l->Light[i] );
1230 }
1231 }
1232 #endif
1233
1234
1235 /*
1236 * Examine current lighting parameters to determine if the optimized lighting
1237 * function can be used.
1238 * Also, precompute some lighting values such as the products of light
1239 * source and material ambient, diffuse and specular coefficients.
1240 */
1241 void
1242 gl_update_lighting( GLcontext *ctx )
1243 {
1244 struct gl_light *light;
1245
1246 ctx->Light.Flags = 0;
1247
1248 foreach(light, &ctx->Light.EnabledList) {
1249
1250 light->Flags = 0;
1251
1252 if (light->EyePosition[3] != 0.0F)
1253 light->Flags |= LIGHT_POSITIONAL;
1254
1255 if (LEN_SQUARED_3FV(light->Specular) > 1e-16)
1256 light->Flags |= LIGHT_SPECULAR;
1257
1258 if (light->SpotCutoff != 180.0F)
1259 light->Flags |= LIGHT_SPOT;
1260
1261 ctx->Light.Flags |= light->Flags;
1262 }
1263
1264 ctx->Light.NeedVertices =
1265 ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
1266 (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) ||
1267 (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR)));
1268
1269
1270 /* Precompute some shading values.
1271 */
1272 if (ctx->Visual.RGBAflag) {
1273 GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1);
1274 GLuint side;
1275 for (side=0; side < sides; side++) {
1276 struct gl_material *mat = &ctx->Light.Material[side];
1277
1278 COPY_3V(ctx->Light.BaseColor[side], mat->Emission);
1279 ACC_SCALE_3V(ctx->Light.BaseColor[side],
1280 ctx->Light.Model.Ambient,
1281 mat->Ambient);
1282
1283 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side],
1284 ctx->Light.Material[side].Diffuse[3] );
1285 }
1286
1287 foreach (light, &ctx->Light.EnabledList) {
1288 for (side=0; side< sides; side++) {
1289 const struct gl_material *mat = &ctx->Light.Material[side];
1290 SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse );
1291 SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient );
1292 if (light->Flags & LIGHT_SPECULAR) {
1293 SCALE_3V( light->MatSpecular[side], light->Specular,
1294 mat->Specular);
1295 light->IsMatSpecular[side] =
1296 (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16);
1297 }
1298 else
1299 light->IsMatSpecular[side] = 0;
1300 }
1301 }
1302 }
1303 else {
1304 static const GLfloat ci[3] = { .30, .59, .11 };
1305 foreach(light, &ctx->Light.EnabledList) {
1306 light->dli = DOT3(ci, light->Diffuse);
1307 light->sli = DOT3(ci, light->Specular);
1308 }
1309 }
1310 }
1311
1312
1313
1314 /* Need to seriously restrict the circumstances under which these
1315 * calc's are performed.
1316 */
1317 void
1318 gl_compute_light_positions( GLcontext *ctx )
1319 {
1320 struct gl_light *light;
1321
1322 if (1 /*ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer*/) {
1323 static const GLfloat eye_z[3] = { 0, 0, 1 };
1324 if (ctx->NeedEyeCoords) {
1325 COPY_3V( ctx->EyeZDir, eye_z );
1326 }
1327 else {
1328 TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m );
1329 }
1330 }
1331
1332 foreach (light, &ctx->Light.EnabledList) {
1333
1334 if (ctx->NeedEyeCoords) {
1335 COPY_4FV( light->Position, light->EyePosition );
1336 }
1337 else {
1338 TRANSFORM_POINT( light->Position, ctx->ModelView.inv,
1339 light->EyePosition );
1340 }
1341
1342 if (!(light->Flags & LIGHT_POSITIONAL)) {
1343 /* VP (VP) = Normalize( Position ) */
1344 COPY_3V( light->VP_inf_norm, light->Position );
1345 NORMALIZE_3FV( light->VP_inf_norm );
1346
1347 if (!ctx->Light.Model.LocalViewer) {
1348 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1349 ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir);
1350 NORMALIZE_3FV( light->h_inf_norm );
1351 }
1352 light->VP_inf_spot_attenuation = 1.0;
1353 }
1354
1355 if (light->Flags & LIGHT_SPOT) {
1356 if (ctx->NeedEyeNormals) {
1357 COPY_3V( light->NormDirection, light->EyeDirection );
1358 }
1359 else {
1360 TRANSFORM_NORMAL( light->NormDirection,
1361 light->EyeDirection,
1362 ctx->ModelView.m);
1363 }
1364
1365 NORMALIZE_3FV( light->NormDirection );
1366
1367
1368 /* Unlikely occurrance?
1369 */
1370 if (!(light->Flags & LIGHT_POSITIONAL)) {
1371 GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm,
1372 light->NormDirection);
1373
1374 if (PV_dot_dir > light->CosCutoff) {
1375 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1376 int k = (int) x;
1377 light->VP_inf_spot_attenuation =
1378 (light->SpotExpTable[k][0] +
1379 (x-k)*light->SpotExpTable[k][1]);
1380 }
1381 else {
1382 light->VP_inf_spot_attenuation = 0;
1383 }
1384 }
1385 }
1386 }
1387 }
1388
1389
1390 void
1391 gl_update_normal_transform( GLcontext *ctx )
1392 {
1393 GLuint new_flag = 0;
1394 normal_func *last = ctx->NormalTransform;
1395
1396 ctx->vb_rescale_factor = 1.0;
1397
1398 if (ctx->NeedEyeCoords) {
1399 if (ctx->NeedNormals) {
1400 GLuint transform = NORM_TRANSFORM_NO_ROT;
1401
1402 if (ctx->ModelView.flags & (MAT_FLAG_GENERAL |
1403 MAT_FLAG_ROTATION |
1404 MAT_FLAG_GENERAL_3D |
1405 MAT_FLAG_PERSPECTIVE))
1406 transform = NORM_TRANSFORM;
1407
1408
1409 new_flag = ctx->NewState & NEW_MODELVIEW;
1410 ctx->vb_rescale_factor = ctx->rescale_factor;
1411
1412 if (ctx->Transform.Normalize) {
1413 ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE];
1414 }
1415 else if (ctx->Transform.RescaleNormals &&
1416 ctx->rescale_factor != 1.0) {
1417 ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE];
1418 }
1419 else {
1420 ctx->NormalTransform = gl_normal_tab[transform];
1421 }
1422 }
1423 else {
1424 ctx->NormalTransform = 0;
1425 }
1426 }
1427 else {
1428 if (ctx->NeedNormals) {
1429 ctx->vb_rescale_factor = 1.0/ctx->rescale_factor;
1430
1431 if (ctx->Transform.Normalize) {
1432 ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE];
1433 }
1434 else if (!ctx->Transform.RescaleNormals &&
1435 ctx->rescale_factor != 1.0) {
1436 ctx->NormalTransform = gl_normal_tab[NORM_RESCALE];
1437 }
1438 else {
1439 ctx->NormalTransform = 0;
1440 }
1441 }
1442 else {
1443 ctx->NormalTransform = 0;
1444 }
1445 }
1446
1447 if (last != ctx->NormalTransform || new_flag)
1448 ctx->NewState |= NEW_NORMAL_TRANSFORM;
1449 }