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