added memory macros
[mesa.git] / src / mesa / main / light.c
1 /* $Id: light.c,v 1.4 1999/10/08 09:27:11 keithw 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 ctx->TriangleCaps &= ~DD_SEPERATE_SPECULAR;
323 ctx->NewState |= NEW_RASTER_OPS;
324 if (params[0] == (GLfloat) GL_SINGLE_COLOR)
325 ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
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 } else
330 gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
331 break;
332 default:
333 gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
334 break;
335 }
336
337 if (ctx->Driver.LightModelfv)
338 ctx->Driver.LightModelfv( ctx, pname, params );
339
340 ctx->NewState |= NEW_LIGHTING;
341 }
342
343
344
345
346 /********** MATERIAL **********/
347
348
349 /*
350 * Given a face and pname value (ala glColorMaterial), compute a bitmask
351 * of the targeted material values.
352 */
353 GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
354 GLuint legal,
355 const char *where )
356 {
357 GLuint bitmask = 0;
358
359 /* Make a bitmask indicating what material attribute(s) we're updating */
360 switch (pname) {
361 case GL_EMISSION:
362 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
363 break;
364 case GL_AMBIENT:
365 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
366 break;
367 case GL_DIFFUSE:
368 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
369 break;
370 case GL_SPECULAR:
371 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
372 break;
373 case GL_SHININESS:
374 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
375 break;
376 case GL_AMBIENT_AND_DIFFUSE:
377 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
378 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
379 break;
380 case GL_COLOR_INDEXES:
381 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
382 break;
383 default:
384 gl_error( ctx, GL_INVALID_ENUM, where );
385 return 0;
386 }
387
388 if (face==GL_FRONT) {
389 bitmask &= FRONT_MATERIAL_BITS;
390 }
391 else if (face==GL_BACK) {
392 bitmask &= BACK_MATERIAL_BITS;
393 }
394 else if (face != GL_FRONT_AND_BACK) {
395 gl_error( ctx, GL_INVALID_ENUM, where );
396 return 0;
397 }
398
399 if (bitmask & ~legal) {
400 gl_error( ctx, GL_INVALID_ENUM, where );
401 return 0;
402 }
403
404 return bitmask;
405 }
406
407
408
409
410
411
412 /*
413 * Check if the global material has to be updated with info that was
414 * associated with a vertex via glMaterial.
415 * This function is used when any material values get changed between
416 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
417 * when GL_COLOR_MATERIAL is enabled.
418 *
419 * KW: Added code here to keep the precomputed variables uptodate.
420 * This means we can use the faster shade functions when using
421 * GL_COLOR_MATERIAL, and we can also now use the precomputed
422 * values in the slower shading functions, which further offsets
423 * the cost of doing this here.
424 */
425 void gl_update_material( GLcontext *ctx,
426 struct gl_material *src,
427 GLuint bitmask )
428 {
429 struct gl_light *light, *list = &ctx->Light.EnabledList;
430 GLfloat tmp[4];
431
432 if (ctx->Light.ColorMaterialEnabled)
433 bitmask &= ~ctx->Light.ColorMaterialBitmask;
434
435 if (!bitmask)
436 return;
437
438 if (bitmask & FRONT_AMBIENT_BIT) {
439 struct gl_material *mat = &ctx->Light.Material[0];
440 SUB_3V( tmp, src[0].Ambient, mat->Ambient );
441 ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp);
442 foreach (light, list) {
443 ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
444 }
445 COPY_4FV( mat->Ambient, src[0].Ambient );
446 }
447 if (bitmask & BACK_AMBIENT_BIT) {
448 struct gl_material *mat = &ctx->Light.Material[1];
449 SUB_3V( tmp, src[1].Ambient, mat->Ambient );
450 ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp);
451 foreach (light, list) {
452 ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
453 }
454 COPY_4FV( mat->Ambient, src[1].Ambient );
455 }
456 if (bitmask & FRONT_DIFFUSE_BIT) {
457 struct gl_material *mat = &ctx->Light.Material[0];
458 SUB_3V( tmp, src[0].Diffuse, mat->Diffuse );
459 foreach (light, list) {
460 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
461 }
462 COPY_4FV( mat->Diffuse, src[0].Diffuse );
463 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
464 }
465 if (bitmask & BACK_DIFFUSE_BIT) {
466 struct gl_material *mat = &ctx->Light.Material[1];
467 SUB_3V( tmp, src[1].Diffuse, mat->Diffuse );
468 foreach (light, list) {
469 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
470 }
471 COPY_4FV( mat->Diffuse, src[1].Diffuse );
472 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
473 }
474 if (bitmask & FRONT_SPECULAR_BIT) {
475 struct gl_material *mat = &ctx->Light.Material[0];
476 SUB_3V( tmp, src[0].Specular, mat->Specular );
477 foreach (light, list) {
478 if (light->Flags & LIGHT_SPECULAR) {
479 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
480 light->IsMatSpecular[0] =
481 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
482 }
483 }
484 COPY_4FV( mat->Specular, src[0].Specular );
485 }
486 if (bitmask & BACK_SPECULAR_BIT) {
487 struct gl_material *mat = &ctx->Light.Material[1];
488 SUB_3V( tmp, src[1].Specular, mat->Specular );
489 foreach (light, list) {
490 if (light->Flags & LIGHT_SPECULAR) {
491 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
492 light->IsMatSpecular[1] =
493 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
494 }
495 }
496 COPY_4FV( mat->Specular, src[1].Specular );
497 }
498 if (bitmask & FRONT_EMISSION_BIT) {
499 struct gl_material *mat = &ctx->Light.Material[0];
500 SUB_3V( tmp, src[0].Emission, mat->Emission );
501 ACC_3V( ctx->Light.BaseColor[0], tmp );
502 COPY_4FV( mat->Emission, src[0].Emission );
503 }
504 if (bitmask & BACK_EMISSION_BIT) {
505 struct gl_material *mat = &ctx->Light.Material[1];
506 SUB_3V( tmp, src[1].Emission, mat->Emission );
507 ACC_3V( ctx->Light.BaseColor[1], tmp );
508 COPY_4FV( mat->Emission, src[1].Emission );
509 }
510 if (bitmask & FRONT_SHININESS_BIT) {
511 GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess;
512 gl_compute_shine_table( ctx, 0, shininess );
513 gl_compute_shine_table( ctx, 2, shininess * .5 );
514 }
515 if (bitmask & BACK_SHININESS_BIT) {
516 GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess;
517 gl_compute_shine_table( ctx, 1, shininess );
518 gl_compute_shine_table( ctx, 3, shininess * .5 );
519 }
520 if (bitmask & FRONT_INDEXES_BIT) {
521 ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
522 ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
523 ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
524 }
525 if (bitmask & BACK_INDEXES_BIT) {
526 ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
527 ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
528 ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
529 }
530
531 }
532
533
534
535
536
537
538 void gl_update_color_material( GLcontext *ctx,
539 const GLubyte rgba[4] )
540 {
541 struct gl_light *light, *list = &ctx->Light.EnabledList;
542 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
543 GLfloat tmp[4], color[4];
544
545 UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
546
547 if (bitmask & FRONT_AMBIENT_BIT) {
548 struct gl_material *mat = &ctx->Light.Material[0];
549 SUB_3V( tmp, color, mat->Ambient );
550 ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp);
551 foreach (light, list) {
552 ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
553 }
554 COPY_4FV( mat->Ambient, color );
555 }
556
557 if (bitmask & BACK_AMBIENT_BIT) {
558 struct gl_material *mat = &ctx->Light.Material[1];
559 SUB_3V( tmp, color, mat->Ambient );
560 ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp);
561 foreach (light, list) {
562 ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
563 }
564 COPY_4FV( mat->Ambient, color );
565 }
566
567 if (bitmask & FRONT_DIFFUSE_BIT) {
568 struct gl_material *mat = &ctx->Light.Material[0];
569 SUB_3V( tmp, color, mat->Diffuse );
570 foreach (light, list) {
571 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
572 }
573 COPY_4FV( mat->Diffuse, color );
574 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
575 }
576
577 if (bitmask & BACK_DIFFUSE_BIT) {
578 struct gl_material *mat = &ctx->Light.Material[1];
579 SUB_3V( tmp, color, mat->Diffuse );
580 foreach (light, list) {
581 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
582 }
583 COPY_4FV( mat->Diffuse, color );
584 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
585 }
586
587 if (bitmask & FRONT_SPECULAR_BIT) {
588 struct gl_material *mat = &ctx->Light.Material[0];
589 SUB_3V( tmp, color, mat->Specular );
590 foreach (light, list) {
591 if (light->Flags & LIGHT_SPECULAR) {
592 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
593 light->IsMatSpecular[0] =
594 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
595 }
596 }
597 COPY_4FV( mat->Specular, color );
598 }
599 if (bitmask & BACK_SPECULAR_BIT) {
600 struct gl_material *mat = &ctx->Light.Material[1];
601 SUB_3V( tmp, color, mat->Specular );
602 foreach (light, list) {
603 if (light->Flags & LIGHT_SPECULAR) {
604 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
605 light->IsMatSpecular[1] =
606 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
607 }
608 }
609 COPY_4FV( mat->Specular, color );
610 }
611 if (bitmask & FRONT_EMISSION_BIT) {
612 struct gl_material *mat = &ctx->Light.Material[0];
613 SUB_3V( tmp, color, mat->Emission );
614 ACC_3V( ctx->Light.BaseColor[0], tmp );
615 COPY_4FV( mat->Emission, color );
616 }
617 if (bitmask & BACK_EMISSION_BIT) {
618 struct gl_material *mat = &ctx->Light.Material[1];
619 SUB_3V( tmp, color, mat->Emission );
620 ACC_3V( ctx->Light.BaseColor[1], tmp );
621 COPY_4FV( mat->Emission, color );
622 }
623 }
624
625
626
627
628 void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
629 {
630 GLuint bitmask;
631 GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
632 FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
633 FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
634 FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
635
636 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
637
638 bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
639
640 if (bitmask != 0) {
641 ctx->Light.ColorMaterialBitmask = bitmask;
642 ctx->Light.ColorMaterialFace = face;
643 ctx->Light.ColorMaterialMode = mode;
644 }
645 }
646
647
648
649 /* KW: This is now called directly (ie by name) from the glMaterial*
650 * API functions.
651 */
652 void gl_Materialfv( GLcontext *ctx,
653 GLenum face, GLenum pname, const GLfloat *params )
654 {
655 struct immediate *IM;
656 struct gl_material *mat;
657 GLuint bitmask;
658 GLuint count;
659
660 bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" );
661 if (bitmask == 0)
662 return;
663
664 IM = ctx->input;
665 count = IM->Count;
666
667 if (!(IM->Flag[count] & VERT_MATERIAL)) {
668 IM->Flag[count] |= VERT_MATERIAL;
669 IM->MaterialMask[count] = 0;
670 }
671
672 IM->MaterialMask[count] |= bitmask;
673 mat = IM->Material[count];
674 IM->LastMaterial = count;
675
676 if (bitmask & FRONT_AMBIENT_BIT) {
677 COPY_4FV( mat[0].Ambient, params );
678 }
679 if (bitmask & BACK_AMBIENT_BIT) {
680 COPY_4FV( mat[1].Ambient, params );
681 }
682 if (bitmask & FRONT_DIFFUSE_BIT) {
683 COPY_4FV( mat[0].Diffuse, params );
684 }
685 if (bitmask & BACK_DIFFUSE_BIT) {
686 COPY_4FV( mat[1].Diffuse, params );
687 }
688 if (bitmask & FRONT_SPECULAR_BIT) {
689 COPY_4FV( mat[0].Specular, params );
690 }
691 if (bitmask & BACK_SPECULAR_BIT) {
692 COPY_4FV( mat[1].Specular, params );
693 }
694 if (bitmask & FRONT_EMISSION_BIT) {
695 COPY_4FV( mat[0].Emission, params );
696 }
697 if (bitmask & BACK_EMISSION_BIT) {
698 COPY_4FV( mat[1].Emission, params );
699 }
700 if (bitmask & FRONT_SHININESS_BIT) {
701 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
702 mat[0].Shininess = shininess;
703 }
704 if (bitmask & BACK_SHININESS_BIT) {
705 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
706 mat[1].Shininess = shininess;
707 }
708 if (bitmask & FRONT_INDEXES_BIT) {
709 mat[0].AmbientIndex = params[0];
710 mat[0].DiffuseIndex = params[1];
711 mat[0].SpecularIndex = params[2];
712 }
713 if (bitmask & BACK_INDEXES_BIT) {
714 mat[1].AmbientIndex = params[0];
715 mat[1].DiffuseIndex = params[1];
716 mat[1].SpecularIndex = params[2];
717 }
718 }
719
720
721
722
723 void gl_GetMaterialfv( GLcontext *ctx,
724 GLenum face, GLenum pname, GLfloat *params )
725 {
726 GLuint f;
727
728 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
729
730 if (face==GL_FRONT) {
731 f = 0;
732 }
733 else if (face==GL_BACK) {
734 f = 1;
735 }
736 else {
737 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
738 return;
739 }
740 switch (pname) {
741 case GL_AMBIENT:
742 COPY_4FV( params, ctx->Light.Material[f].Ambient );
743 break;
744 case GL_DIFFUSE:
745 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
746 break;
747 case GL_SPECULAR:
748 COPY_4FV( params, ctx->Light.Material[f].Specular );
749 break;
750 case GL_EMISSION:
751 COPY_4FV( params, ctx->Light.Material[f].Emission );
752 break;
753 case GL_SHININESS:
754 *params = ctx->Light.Material[f].Shininess;
755 break;
756 case GL_COLOR_INDEXES:
757 params[0] = ctx->Light.Material[f].AmbientIndex;
758 params[1] = ctx->Light.Material[f].DiffuseIndex;
759 params[2] = ctx->Light.Material[f].SpecularIndex;
760 break;
761 default:
762 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
763 }
764 }
765
766
767
768 void gl_GetMaterialiv( GLcontext *ctx,
769 GLenum face, GLenum pname, GLint *params )
770 {
771 GLuint f;
772
773 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
774
775 if (face==GL_FRONT) {
776 f = 0;
777 }
778 else if (face==GL_BACK) {
779 f = 1;
780 }
781 else {
782 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
783 return;
784 }
785 switch (pname) {
786 case GL_AMBIENT:
787 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
788 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
789 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
790 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
791 break;
792 case GL_DIFFUSE:
793 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
794 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
795 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
796 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
797 break;
798 case GL_SPECULAR:
799 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
800 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
801 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
802 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
803 break;
804 case GL_EMISSION:
805 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
806 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
807 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
808 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
809 break;
810 case GL_SHININESS:
811 *params = ROUNDF( ctx->Light.Material[f].Shininess );
812 break;
813 case GL_COLOR_INDEXES:
814 params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
815 params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
816 params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
817 break;
818 default:
819 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
820 }
821 }
822
823
824
825
826 /**********************************************************************/
827 /***** Lighting computation *****/
828 /**********************************************************************/
829
830
831 /*
832 * Notes:
833 * When two-sided lighting is enabled we compute the color (or index)
834 * for both the front and back side of the primitive. Then, when the
835 * orientation of the facet is later learned, we can determine which
836 * color (or index) to use for rendering.
837 *
838 * KW: We now know orientation in advance and only shade for
839 * the side or sides which are actually required.
840 *
841 * Variables:
842 * n = normal vector
843 * V = vertex position
844 * P = light source position
845 * Pe = (0,0,0,1)
846 *
847 * Precomputed:
848 * IF P[3]==0 THEN
849 * // light at infinity
850 * IF local_viewer THEN
851 * VP_inf_norm = unit vector from V to P // Precompute
852 * ELSE
853 * // eye at infinity
854 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
855 * ENDIF
856 * ENDIF
857 *
858 * Functions:
859 * Normalize( v ) = normalized vector v
860 * Magnitude( v ) = length of vector v
861 */
862
863
864
865 /*
866 * Whenever the spotlight exponent for a light changes we must call
867 * this function to recompute the exponent lookup table.
868 */
869 void gl_compute_spot_exp_table( struct gl_light *l )
870 {
871 int i;
872 double exponent = l->SpotExponent;
873 double tmp = 0;
874 int clamp = 0;
875
876 l->SpotExpTable[0][0] = 0.0;
877
878 for (i=EXP_TABLE_SIZE-1;i>0;i--) {
879 if (clamp == 0) {
880 tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
881 if (tmp < FLT_MIN*100.0) {
882 tmp = 0.0;
883 clamp = 1;
884 }
885 }
886 l->SpotExpTable[i][0] = tmp;
887 }
888 for (i=0;i<EXP_TABLE_SIZE-1;i++) {
889 l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
890 }
891 l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
892 }
893
894
895
896
897 /* Calculate a new shine table. Doing this here saves a branch in
898 * lighting, and the cost of doing it early may be partially offset
899 * by keeping a MRU cache of shine tables for various shine values.
900 */
901 static void compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
902 {
903 int i;
904 GLfloat *m = tab->tab;
905
906 m[0] = 0;
907 if (shininess == 0) {
908 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
909 m[i] = 1;
910 } else {
911 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++) {
912 double t = pow( i/(GLfloat)SHINE_TABLE_SIZE, shininess );
913 m[i] = 0;
914 if (t > 1e-20) m[i] = t;
915 }
916 }
917
918 tab->shininess = shininess;
919 }
920
921 #define DISTSQR(a,b) ((a-b)*(a-b))
922
923 void gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
924 {
925 struct gl_shine_tab *list = ctx->ShineTabList;
926 struct gl_shine_tab *s;
927
928 foreach(s, list)
929 if ( DISTSQR(s->shininess, shininess) < 1e-4 )
930 break;
931
932 if (s == list)
933 {
934 foreach(s, list)
935 if (s->refcount == 0) break;
936
937 compute_shine_table( s, shininess );
938 }
939
940 ctx->ShineTable[i]->refcount--;
941 ctx->ShineTable[i] = s;
942 move_to_tail( list, s );
943 s->refcount++;
944 }
945
946
947
948
949 void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
950 {
951 GLuint i;
952
953 if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) {
954 gl_compute_shine_table( ctx, 0, l->Material[0].Shininess );
955 gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 );
956 }
957
958 if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) {
959 gl_compute_shine_table( ctx, 1, l->Material[1].Shininess );
960 gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 );
961 }
962
963 make_empty_list( &l->EnabledList );
964 for (i = 0 ; i < MAX_LIGHTS ; i++) {
965 if (l->Light[i].Enabled)
966 insert_at_tail( &l->EnabledList, &l->Light[i] );
967 }
968 }
969
970
971
972 /*
973 * Examine current lighting parameters to determine if the optimized lighting
974 * function can be used.
975 * Also, precompute some lighting values such as the products of light
976 * source and material ambient, diffuse and specular coefficients.
977 */
978 void gl_update_lighting( GLcontext *ctx )
979 {
980 struct gl_light *light;
981
982 ctx->Light.Flags = 0;
983
984 foreach(light, &ctx->Light.EnabledList) {
985
986 light->Flags = 0;
987
988 if (light->EyePosition[3] != 0.0F)
989 light->Flags |= LIGHT_POSITIONAL;
990
991 if (LEN_SQUARED_3FV(light->Specular) > 1e-16)
992 light->Flags |= LIGHT_SPECULAR;
993
994 if (light->SpotCutoff != 180.0F)
995 light->Flags |= LIGHT_SPOT;
996
997 ctx->Light.Flags |= light->Flags;
998 }
999
1000 ctx->Light.NeedVertices =
1001 ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
1002 (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) ||
1003 (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR)));
1004
1005
1006 /* Precompute some shading values.
1007 */
1008 if (ctx->Visual->RGBAflag)
1009 {
1010 GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1);
1011 GLuint side;
1012 for (side=0; side < sides; side++) {
1013 struct gl_material *mat = &ctx->Light.Material[side];
1014
1015 COPY_3V(ctx->Light.BaseColor[side], mat->Emission);
1016 ACC_SCALE_3V(ctx->Light.BaseColor[side],
1017 ctx->Light.Model.Ambient,
1018 mat->Ambient);
1019
1020 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side],
1021 ctx->Light.Material[side].Diffuse[3] );
1022 }
1023
1024 foreach (light, &ctx->Light.EnabledList) {
1025 for (side=0; side< sides; side++) {
1026 struct gl_material *mat = &ctx->Light.Material[side];
1027 SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse );
1028 SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient );
1029 ACC_3V( ctx->Light.BaseColor[side], light->MatAmbient[side] );
1030 if (light->Flags & LIGHT_SPECULAR)
1031 {
1032 SCALE_3V( light->MatSpecular[side], light->Specular,
1033 mat->Specular);
1034 light->IsMatSpecular[side] =
1035 (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16);
1036 }
1037 else
1038 light->IsMatSpecular[side] = 0;
1039 }
1040 }
1041 }
1042 else
1043 {
1044 static GLfloat ci[3] = { .30, .59, .11 };
1045
1046 foreach(light, &ctx->Light.EnabledList) {
1047 light->dli = DOT3(ci, light->Diffuse);
1048 light->sli = DOT3(ci, light->Specular);
1049 }
1050 }
1051 }
1052
1053 /* Need to seriously restrict the circumstances under which these
1054 * calc's are performed.
1055 */
1056 void gl_compute_light_positions( GLcontext *ctx )
1057 {
1058 struct gl_light *light;
1059
1060 if (ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer) {
1061 GLfloat eye_z[3] = { 0, 0, 1 };
1062 if (!ctx->NeedEyeCoords) {
1063 TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m );
1064 } else {
1065 COPY_3V( ctx->EyeZDir, eye_z );
1066 }
1067 }
1068
1069 foreach (light, &ctx->Light.EnabledList) {
1070
1071 if (!ctx->NeedEyeCoords) {
1072 TRANSFORM_POINT( light->Position, ctx->ModelView.inv,
1073 light->EyePosition );
1074 } else {
1075 COPY_4FV( light->Position, light->EyePosition );
1076 }
1077
1078 if (!(light->Flags & LIGHT_POSITIONAL))
1079 {
1080 /* VP (VP) = Normalize( Position ) */
1081 COPY_3V( light->VP_inf_norm, light->Position );
1082 NORMALIZE_3FV( light->VP_inf_norm );
1083
1084 if (!ctx->Light.Model.LocalViewer)
1085 {
1086 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1087 ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir);
1088 NORMALIZE_3FV( light->h_inf_norm );
1089 }
1090
1091 light->VP_inf_spot_attenuation = 1.0;
1092 }
1093
1094 if (light->Flags & LIGHT_SPOT)
1095 {
1096 if (ctx->NeedEyeNormals) {
1097 COPY_3V( light->NormDirection, light->EyeDirection );
1098 } else {
1099 TRANSFORM_NORMAL( light->NormDirection,
1100 light->EyeDirection,
1101 ctx->ModelView.m);
1102 }
1103
1104 NORMALIZE_3FV( light->NormDirection );
1105
1106
1107 /* Unlikely occurrance?
1108 */
1109 if (!(light->Flags & LIGHT_POSITIONAL)) {
1110 GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm,
1111 light->NormDirection);
1112
1113 if (PV_dot_dir > light->CosCutoff) {
1114 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1115 int k = (int) x;
1116 light->VP_inf_spot_attenuation =
1117 (light->SpotExpTable[k][0] +
1118 (x-k)*light->SpotExpTable[k][1]);
1119 }
1120 else
1121 light->VP_inf_spot_attenuation = 0;
1122 }
1123 }
1124 }
1125 }
1126
1127
1128
1129
1130
1131 void gl_update_normal_transform( GLcontext *ctx )
1132 {
1133 GLuint new_flag = 0;
1134 normal_func *last = ctx->NormalTransform;
1135
1136 ctx->vb_rescale_factor = 1.0;
1137
1138 if (ctx->NeedEyeCoords) {
1139 if (ctx->NeedNormals) {
1140 GLuint transform = NORM_TRANSFORM_NO_ROT;
1141
1142 if (ctx->ModelView.flags & (MAT_FLAG_GENERAL |
1143 MAT_FLAG_ROTATION |
1144 MAT_FLAG_GENERAL_3D |
1145 MAT_FLAG_PERSPECTIVE))
1146 transform = NORM_TRANSFORM;
1147
1148
1149 new_flag = ctx->NewState & NEW_MODELVIEW;
1150 ctx->vb_rescale_factor = ctx->rescale_factor;
1151
1152 if (ctx->Transform.Normalize)
1153 {
1154 ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE];
1155 }
1156 else if (ctx->Transform.RescaleNormals &&
1157 ctx->rescale_factor != 1.0)
1158 {
1159 ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE];
1160 }
1161 else
1162 {
1163 ctx->NormalTransform = gl_normal_tab[transform];
1164 }
1165 } else {
1166 ctx->NormalTransform = 0;
1167 }
1168 }
1169 else {
1170 if (ctx->NeedNormals) {
1171 ctx->vb_rescale_factor = 1.0/ctx->rescale_factor;
1172
1173 if (ctx->Transform.Normalize)
1174 {
1175 ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE];
1176 }
1177 else if (!ctx->Transform.RescaleNormals &&
1178 ctx->rescale_factor != 1.0)
1179 {
1180 ctx->NormalTransform = gl_normal_tab[NORM_RESCALE];
1181 }
1182 else
1183 {
1184 ctx->NormalTransform = 0;
1185 }
1186 } else {
1187 ctx->NormalTransform = 0;
1188 }
1189 }
1190
1191 if (last != ctx->NormalTransform || new_flag)
1192 ctx->NewState |= NEW_NORMAL_TRANSFORM;
1193 }
1194