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