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