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