1 /* $Id: light.c,v 1.6 1999/10/19 20:32:40 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
41 #include "GL/xf86glx.h"
50 #include "simple_list.h"
58 void gl_ShadeModel( GLcontext
*ctx
, GLenum mode
)
60 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glShadeModel");
62 if (MESA_VERBOSE
& VERBOSE_API
)
63 fprintf(stderr
, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode
));
69 if (ctx
->Light
.ShadeModel
!=mode
) {
70 ctx
->Light
.ShadeModel
= mode
;
71 ctx
->TriangleCaps
^= DD_FLATSHADE
;
72 ctx
->NewState
|= NEW_RASTER_OPS
;
76 gl_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
79 if (ctx
->Driver
.ShadeModel
)
80 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
85 void gl_Lightfv( GLcontext
*ctx
,
86 GLenum light
, GLenum pname
, const GLfloat
*params
,
93 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLight");
95 l
= (GLint
) (light
- GL_LIGHT0
);
97 if (l
<0 || l
>=MAX_LIGHTS
) {
98 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
104 COPY_4V( ctx
->Light
.Light
[l
].Ambient
, params
);
107 COPY_4V( ctx
->Light
.Light
[l
].Diffuse
, params
);
110 COPY_4V( ctx
->Light
.Light
[l
].Specular
, params
);
113 /* transform position by ModelView matrix */
114 TRANSFORM_POINT( ctx
->Light
.Light
[l
].EyePosition
,
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
);
123 TRANSFORM_NORMAL( ctx
->Light
.Light
[l
].EyeDirection
,
125 ctx
->ModelView
.inv
);
127 case GL_SPOT_EXPONENT
:
128 if (params
[0]<0.0 || params
[0]>128.0) {
129 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
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
] );
138 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
139 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
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;
147 case GL_CONSTANT_ATTENUATION
:
149 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
152 ctx
->Light
.Light
[l
].ConstantAttenuation
= params
[0];
154 case GL_LINEAR_ATTENUATION
:
156 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
159 ctx
->Light
.Light
[l
].LinearAttenuation
= params
[0];
161 case GL_QUADRATIC_ATTENUATION
:
163 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
166 ctx
->Light
.Light
[l
].QuadraticAttenuation
= params
[0];
169 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
173 if (ctx
->Driver
.Lightfv
)
174 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
, nparams
);
176 ctx
->NewState
|= NEW_LIGHTING
;
181 void gl_GetLightfv( GLcontext
*ctx
,
182 GLenum light
, GLenum pname
, GLfloat
*params
)
184 GLint l
= (GLint
) (light
- GL_LIGHT0
);
186 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
188 if (l
<0 || l
>=MAX_LIGHTS
) {
189 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
195 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
198 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
201 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
204 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
206 case GL_SPOT_DIRECTION
:
207 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
209 case GL_SPOT_EXPONENT
:
210 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
213 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
215 case GL_CONSTANT_ATTENUATION
:
216 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
218 case GL_LINEAR_ATTENUATION
:
219 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
221 case GL_QUADRATIC_ATTENUATION
:
222 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
225 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
232 void gl_GetLightiv( GLcontext
*ctx
, GLenum light
, GLenum pname
, GLint
*params
)
234 GLint l
= (GLint
) (light
- GL_LIGHT0
);
236 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
238 if (l
<0 || l
>=MAX_LIGHTS
) {
239 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
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]);
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]);
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]);
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];
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];
273 case GL_SPOT_EXPONENT
:
274 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
277 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
279 case GL_CONSTANT_ATTENUATION
:
280 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
282 case GL_LINEAR_ATTENUATION
:
283 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
285 case GL_QUADRATIC_ATTENUATION
:
286 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
289 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
296 /**********************************************************************/
297 /*** Light Model ***/
298 /**********************************************************************/
301 void gl_LightModelfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
303 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLightModel");
306 case GL_LIGHT_MODEL_AMBIENT
:
307 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
309 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
311 ctx
->Light
.Model
.LocalViewer
= GL_FALSE
;
313 ctx
->Light
.Model
.LocalViewer
= GL_TRUE
;
315 case GL_LIGHT_MODEL_TWO_SIDE
:
317 ctx
->Light
.Model
.TwoSide
= GL_FALSE
;
319 ctx
->Light
.Model
.TwoSide
= GL_TRUE
;
321 case GL_LIGHT_MODEL_COLOR_CONTROL
:
322 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
) {
323 ctx
->Light
.Model
.ColorControl
= GL_SINGLE_COLOR
;
324 ctx
->TriangleCaps
&= ~DD_SEPERATE_SPECULAR
;
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
;
331 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param)" );
333 ctx
->NewState
|= NEW_RASTER_OPS
;
336 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel" );
340 if (ctx
->Driver
.LightModelfv
)
341 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
343 ctx
->NewState
|= NEW_LIGHTING
;
349 /********** MATERIAL **********/
353 * Given a face and pname value (ala glColorMaterial), compute a bitmask
354 * of the targeted material values.
356 GLuint
gl_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
362 /* Make a bitmask indicating what material attribute(s) we're updating */
365 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
368 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
371 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
374 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
377 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
379 case GL_AMBIENT_AND_DIFFUSE
:
380 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
381 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
383 case GL_COLOR_INDEXES
:
384 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
387 gl_error( ctx
, GL_INVALID_ENUM
, where
);
391 if (face
==GL_FRONT
) {
392 bitmask
&= FRONT_MATERIAL_BITS
;
394 else if (face
==GL_BACK
) {
395 bitmask
&= BACK_MATERIAL_BITS
;
397 else if (face
!= GL_FRONT_AND_BACK
) {
398 gl_error( ctx
, GL_INVALID_ENUM
, where
);
402 if (bitmask
& ~legal
) {
403 gl_error( ctx
, GL_INVALID_ENUM
, where
);
416 * Check if the global material has to be updated with info that was
417 * associated with a vertex via glMaterial.
418 * This function is used when any material values get changed between
419 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
420 * when GL_COLOR_MATERIAL is enabled.
422 * KW: Added code here to keep the precomputed variables uptodate.
423 * This means we can use the faster shade functions when using
424 * GL_COLOR_MATERIAL, and we can also now use the precomputed
425 * values in the slower shading functions, which further offsets
426 * the cost of doing this here.
428 void gl_update_material( GLcontext
*ctx
,
429 struct gl_material
*src
,
432 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
435 if (ctx
->Light
.ColorMaterialEnabled
)
436 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
441 if (bitmask
& FRONT_AMBIENT_BIT
) {
442 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
443 SUB_3V( tmp
, src
[0].Ambient
, mat
->Ambient
);
444 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], ctx
->Light
.Model
.Ambient
, tmp
);
445 foreach (light
, list
) {
446 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
448 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
450 if (bitmask
& BACK_AMBIENT_BIT
) {
451 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
452 SUB_3V( tmp
, src
[1].Ambient
, mat
->Ambient
);
453 ACC_SCALE_3V( ctx
->Light
.BaseColor
[1], ctx
->Light
.Model
.Ambient
, tmp
);
454 foreach (light
, list
) {
455 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
457 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
459 if (bitmask
& FRONT_DIFFUSE_BIT
) {
460 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
461 SUB_3V( tmp
, src
[0].Diffuse
, mat
->Diffuse
);
462 foreach (light
, list
) {
463 ACC_SCALE_3V( light
->MatDiffuse
[0], light
->Diffuse
, tmp
);
465 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
466 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[0], mat
->Diffuse
[3]);
468 if (bitmask
& BACK_DIFFUSE_BIT
) {
469 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
470 SUB_3V( tmp
, src
[1].Diffuse
, mat
->Diffuse
);
471 foreach (light
, list
) {
472 ACC_SCALE_3V( light
->MatDiffuse
[1], light
->Diffuse
, tmp
);
474 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
475 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[1], mat
->Diffuse
[3]);
477 if (bitmask
& FRONT_SPECULAR_BIT
) {
478 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
479 SUB_3V( tmp
, src
[0].Specular
, mat
->Specular
);
480 foreach (light
, list
) {
481 if (light
->Flags
& LIGHT_SPECULAR
) {
482 ACC_SCALE_3V( light
->MatSpecular
[0], light
->Specular
, tmp
);
483 light
->IsMatSpecular
[0] =
484 (LEN_SQUARED_3FV(light
->MatSpecular
[0]) > 1e-16);
487 COPY_4FV( mat
->Specular
, src
[0].Specular
);
489 if (bitmask
& BACK_SPECULAR_BIT
) {
490 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
491 SUB_3V( tmp
, src
[1].Specular
, mat
->Specular
);
492 foreach (light
, list
) {
493 if (light
->Flags
& LIGHT_SPECULAR
) {
494 ACC_SCALE_3V( light
->MatSpecular
[1], light
->Specular
, tmp
);
495 light
->IsMatSpecular
[1] =
496 (LEN_SQUARED_3FV(light
->MatSpecular
[1]) > 1e-16);
499 COPY_4FV( mat
->Specular
, src
[1].Specular
);
501 if (bitmask
& FRONT_EMISSION_BIT
) {
502 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
503 SUB_3V( tmp
, src
[0].Emission
, mat
->Emission
);
504 ACC_3V( ctx
->Light
.BaseColor
[0], tmp
);
505 COPY_4FV( mat
->Emission
, src
[0].Emission
);
507 if (bitmask
& BACK_EMISSION_BIT
) {
508 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
509 SUB_3V( tmp
, src
[1].Emission
, mat
->Emission
);
510 ACC_3V( ctx
->Light
.BaseColor
[1], tmp
);
511 COPY_4FV( mat
->Emission
, src
[1].Emission
);
513 if (bitmask
& FRONT_SHININESS_BIT
) {
514 GLfloat shininess
= ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
515 gl_compute_shine_table( ctx
, 0, shininess
);
516 gl_compute_shine_table( ctx
, 2, shininess
* .5 );
518 if (bitmask
& BACK_SHININESS_BIT
) {
519 GLfloat shininess
= ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
520 gl_compute_shine_table( ctx
, 1, shininess
);
521 gl_compute_shine_table( ctx
, 3, shininess
* .5 );
523 if (bitmask
& FRONT_INDEXES_BIT
) {
524 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
525 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
526 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
528 if (bitmask
& BACK_INDEXES_BIT
) {
529 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
530 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
531 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
541 void gl_update_color_material( GLcontext
*ctx
,
542 const GLubyte rgba
[4] )
544 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
545 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
546 GLfloat tmp
[4], color
[4];
548 UBYTE_RGBA_TO_FLOAT_RGBA( color
, rgba
);
550 if (bitmask
& FRONT_AMBIENT_BIT
) {
551 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
552 SUB_3V( tmp
, color
, mat
->Ambient
);
553 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], ctx
->Light
.Model
.Ambient
, tmp
);
554 foreach (light
, list
) {
555 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
557 COPY_4FV( mat
->Ambient
, color
);
560 if (bitmask
& BACK_AMBIENT_BIT
) {
561 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
562 SUB_3V( tmp
, color
, mat
->Ambient
);
563 ACC_SCALE_3V( ctx
->Light
.BaseColor
[1], ctx
->Light
.Model
.Ambient
, tmp
);
564 foreach (light
, list
) {
565 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
567 COPY_4FV( mat
->Ambient
, color
);
570 if (bitmask
& FRONT_DIFFUSE_BIT
) {
571 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
572 SUB_3V( tmp
, color
, mat
->Diffuse
);
573 foreach (light
, list
) {
574 ACC_SCALE_3V( light
->MatDiffuse
[0], light
->Diffuse
, tmp
);
576 COPY_4FV( mat
->Diffuse
, color
);
577 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[0], mat
->Diffuse
[3]);
580 if (bitmask
& BACK_DIFFUSE_BIT
) {
581 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
582 SUB_3V( tmp
, color
, mat
->Diffuse
);
583 foreach (light
, list
) {
584 ACC_SCALE_3V( light
->MatDiffuse
[1], light
->Diffuse
, tmp
);
586 COPY_4FV( mat
->Diffuse
, color
);
587 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[1], mat
->Diffuse
[3]);
590 if (bitmask
& FRONT_SPECULAR_BIT
) {
591 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
592 SUB_3V( tmp
, color
, mat
->Specular
);
593 foreach (light
, list
) {
594 if (light
->Flags
& LIGHT_SPECULAR
) {
595 ACC_SCALE_3V( light
->MatSpecular
[0], light
->Specular
, tmp
);
596 light
->IsMatSpecular
[0] =
597 (LEN_SQUARED_3FV(light
->MatSpecular
[0]) > 1e-16);
600 COPY_4FV( mat
->Specular
, color
);
602 if (bitmask
& BACK_SPECULAR_BIT
) {
603 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
604 SUB_3V( tmp
, color
, mat
->Specular
);
605 foreach (light
, list
) {
606 if (light
->Flags
& LIGHT_SPECULAR
) {
607 ACC_SCALE_3V( light
->MatSpecular
[1], light
->Specular
, tmp
);
608 light
->IsMatSpecular
[1] =
609 (LEN_SQUARED_3FV(light
->MatSpecular
[1]) > 1e-16);
612 COPY_4FV( mat
->Specular
, color
);
614 if (bitmask
& FRONT_EMISSION_BIT
) {
615 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
616 SUB_3V( tmp
, color
, mat
->Emission
);
617 ACC_3V( ctx
->Light
.BaseColor
[0], tmp
);
618 COPY_4FV( mat
->Emission
, color
);
620 if (bitmask
& BACK_EMISSION_BIT
) {
621 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
622 SUB_3V( tmp
, color
, mat
->Emission
);
623 ACC_3V( ctx
->Light
.BaseColor
[1], tmp
);
624 COPY_4FV( mat
->Emission
, color
);
631 void gl_ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
634 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
635 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
636 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
637 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
639 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glColorMaterial");
641 bitmask
= gl_material_bitmask( ctx
, face
, mode
, legal
, "glColorMaterial" );
644 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
645 ctx
->Light
.ColorMaterialFace
= face
;
646 ctx
->Light
.ColorMaterialMode
= mode
;
652 /* KW: This is now called directly (ie by name) from the glMaterial*
655 void gl_Materialfv( GLcontext
*ctx
,
656 GLenum face
, GLenum pname
, const GLfloat
*params
)
658 struct immediate
*IM
;
659 struct gl_material
*mat
;
663 bitmask
= gl_material_bitmask( ctx
, face
, pname
, ~0, "gl_Materialfv" );
672 (struct gl_material (*)[2]) MALLOC( sizeof(struct gl_material
) *
674 IM
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * VB_SIZE
);
678 if (!(IM
->Flag
[count
] & VERT_MATERIAL
)) {
679 IM
->Flag
[count
] |= VERT_MATERIAL
;
680 IM
->MaterialMask
[count
] = 0;
684 IM
->MaterialMask
[count
] |= bitmask
;
685 mat
= IM
->Material
[count
];
687 if (bitmask
& FRONT_AMBIENT_BIT
) {
688 COPY_4FV( mat
[0].Ambient
, params
);
690 if (bitmask
& BACK_AMBIENT_BIT
) {
691 COPY_4FV( mat
[1].Ambient
, params
);
693 if (bitmask
& FRONT_DIFFUSE_BIT
) {
694 COPY_4FV( mat
[0].Diffuse
, params
);
696 if (bitmask
& BACK_DIFFUSE_BIT
) {
697 COPY_4FV( mat
[1].Diffuse
, params
);
699 if (bitmask
& FRONT_SPECULAR_BIT
) {
700 COPY_4FV( mat
[0].Specular
, params
);
702 if (bitmask
& BACK_SPECULAR_BIT
) {
703 COPY_4FV( mat
[1].Specular
, params
);
705 if (bitmask
& FRONT_EMISSION_BIT
) {
706 COPY_4FV( mat
[0].Emission
, params
);
708 if (bitmask
& BACK_EMISSION_BIT
) {
709 COPY_4FV( mat
[1].Emission
, params
);
711 if (bitmask
& FRONT_SHININESS_BIT
) {
712 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
713 mat
[0].Shininess
= shininess
;
715 if (bitmask
& BACK_SHININESS_BIT
) {
716 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
717 mat
[1].Shininess
= shininess
;
719 if (bitmask
& FRONT_INDEXES_BIT
) {
720 mat
[0].AmbientIndex
= params
[0];
721 mat
[0].DiffuseIndex
= params
[1];
722 mat
[0].SpecularIndex
= params
[2];
724 if (bitmask
& BACK_INDEXES_BIT
) {
725 mat
[1].AmbientIndex
= params
[0];
726 mat
[1].DiffuseIndex
= params
[1];
727 mat
[1].SpecularIndex
= params
[2];
734 void gl_GetMaterialfv( GLcontext
*ctx
,
735 GLenum face
, GLenum pname
, GLfloat
*params
)
739 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialfv");
741 if (face
==GL_FRONT
) {
744 else if (face
==GL_BACK
) {
748 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
753 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
756 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
759 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
762 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
765 *params
= ctx
->Light
.Material
[f
].Shininess
;
767 case GL_COLOR_INDEXES
:
768 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
769 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
770 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
773 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
779 void gl_GetMaterialiv( GLcontext
*ctx
,
780 GLenum face
, GLenum pname
, GLint
*params
)
784 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialiv");
786 if (face
==GL_FRONT
) {
789 else if (face
==GL_BACK
) {
793 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
798 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
799 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
800 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
801 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
804 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
805 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
806 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
807 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
810 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
811 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
812 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
813 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
816 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
817 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
818 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
819 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
822 *params
= ROUNDF( ctx
->Light
.Material
[f
].Shininess
);
824 case GL_COLOR_INDEXES
:
825 params
[0] = ROUNDF( ctx
->Light
.Material
[f
].AmbientIndex
);
826 params
[1] = ROUNDF( ctx
->Light
.Material
[f
].DiffuseIndex
);
827 params
[2] = ROUNDF( ctx
->Light
.Material
[f
].SpecularIndex
);
830 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
837 /**********************************************************************/
838 /***** Lighting computation *****/
839 /**********************************************************************/
844 * When two-sided lighting is enabled we compute the color (or index)
845 * for both the front and back side of the primitive. Then, when the
846 * orientation of the facet is later learned, we can determine which
847 * color (or index) to use for rendering.
849 * KW: We now know orientation in advance and only shade for
850 * the side or sides which are actually required.
854 * V = vertex position
855 * P = light source position
860 * // light at infinity
861 * IF local_viewer THEN
862 * VP_inf_norm = unit vector from V to P // Precompute
865 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
870 * Normalize( v ) = normalized vector v
871 * Magnitude( v ) = length of vector v
877 * Whenever the spotlight exponent for a light changes we must call
878 * this function to recompute the exponent lookup table.
880 void gl_compute_spot_exp_table( struct gl_light
*l
)
883 double exponent
= l
->SpotExponent
;
887 l
->SpotExpTable
[0][0] = 0.0;
889 for (i
=EXP_TABLE_SIZE
-1;i
>0;i
--) {
891 tmp
= pow(i
/(double)(EXP_TABLE_SIZE
-1), exponent
);
892 if (tmp
< FLT_MIN
*100.0) {
897 l
->SpotExpTable
[i
][0] = tmp
;
899 for (i
=0;i
<EXP_TABLE_SIZE
-1;i
++) {
900 l
->SpotExpTable
[i
][1] = l
->SpotExpTable
[i
+1][0] - l
->SpotExpTable
[i
][0];
902 l
->SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
908 /* Calculate a new shine table. Doing this here saves a branch in
909 * lighting, and the cost of doing it early may be partially offset
910 * by keeping a MRU cache of shine tables for various shine values.
912 static void compute_shine_table( struct gl_shine_tab
*tab
, GLfloat shininess
)
915 GLfloat
*m
= tab
->tab
;
918 if (shininess
== 0) {
919 for (i
= 1 ; i
<= SHINE_TABLE_SIZE
; i
++)
922 for (i
= 1 ; i
<= SHINE_TABLE_SIZE
; i
++) {
923 double t
= pow( i
/(GLfloat
)SHINE_TABLE_SIZE
, shininess
);
925 if (t
> 1e-20) m
[i
] = t
;
929 tab
->shininess
= shininess
;
932 #define DISTSQR(a,b) ((a-b)*(a-b))
934 void gl_compute_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
936 struct gl_shine_tab
*list
= ctx
->ShineTabList
;
937 struct gl_shine_tab
*s
;
940 if ( DISTSQR(s
->shininess
, shininess
) < 1e-4 )
946 if (s
->refcount
== 0) break;
948 compute_shine_table( s
, shininess
);
951 ctx
->ShineTable
[i
]->refcount
--;
952 ctx
->ShineTable
[i
] = s
;
953 move_to_tail( list
, s
);
960 void gl_reinit_light_attrib( GLcontext
*ctx
, struct gl_light_attrib
*l
)
964 if (ctx
->ShineTable
[0]->shininess
!= l
->Material
[0].Shininess
) {
965 gl_compute_shine_table( ctx
, 0, l
->Material
[0].Shininess
);
966 gl_compute_shine_table( ctx
, 2, l
->Material
[0].Shininess
* .5 );
969 if (ctx
->ShineTable
[1]->shininess
!= l
->Material
[1].Shininess
) {
970 gl_compute_shine_table( ctx
, 1, l
->Material
[1].Shininess
);
971 gl_compute_shine_table( ctx
, 3, l
->Material
[1].Shininess
* .5 );
974 make_empty_list( &l
->EnabledList
);
975 for (i
= 0 ; i
< MAX_LIGHTS
; i
++) {
976 if (l
->Light
[i
].Enabled
)
977 insert_at_tail( &l
->EnabledList
, &l
->Light
[i
] );
984 * Examine current lighting parameters to determine if the optimized lighting
985 * function can be used.
986 * Also, precompute some lighting values such as the products of light
987 * source and material ambient, diffuse and specular coefficients.
989 void gl_update_lighting( GLcontext
*ctx
)
991 struct gl_light
*light
;
993 ctx
->Light
.Flags
= 0;
995 foreach(light
, &ctx
->Light
.EnabledList
) {
999 if (light
->EyePosition
[3] != 0.0F
)
1000 light
->Flags
|= LIGHT_POSITIONAL
;
1002 if (LEN_SQUARED_3FV(light
->Specular
) > 1e-16)
1003 light
->Flags
|= LIGHT_SPECULAR
;
1005 if (light
->SpotCutoff
!= 180.0F
)
1006 light
->Flags
|= LIGHT_SPOT
;
1008 ctx
->Light
.Flags
|= light
->Flags
;
1011 ctx
->Light
.NeedVertices
=
1012 ((ctx
->Light
.Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
1013 (ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) ||
1014 (ctx
->Light
.Model
.LocalViewer
&& (ctx
->Light
.Flags
& LIGHT_SPECULAR
)));
1017 /* Precompute some shading values.
1019 if (ctx
->Visual
->RGBAflag
)
1021 GLuint sides
= ((ctx
->TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
) ? 2 : 1);
1023 for (side
=0; side
< sides
; side
++) {
1024 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1026 COPY_3V(ctx
->Light
.BaseColor
[side
], mat
->Emission
);
1027 ACC_SCALE_3V(ctx
->Light
.BaseColor
[side
],
1028 ctx
->Light
.Model
.Ambient
,
1031 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[side
],
1032 ctx
->Light
.Material
[side
].Diffuse
[3] );
1035 foreach (light
, &ctx
->Light
.EnabledList
) {
1036 for (side
=0; side
< sides
; side
++) {
1037 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1038 SCALE_3V( light
->MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1039 SCALE_3V( light
->MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1040 ACC_3V( ctx
->Light
.BaseColor
[side
], light
->MatAmbient
[side
] );
1041 if (light
->Flags
& LIGHT_SPECULAR
)
1043 SCALE_3V( light
->MatSpecular
[side
], light
->Specular
,
1045 light
->IsMatSpecular
[side
] =
1046 (LEN_SQUARED_3FV(light
->MatSpecular
[side
]) > 1e-16);
1049 light
->IsMatSpecular
[side
] = 0;
1055 static GLfloat ci
[3] = { .30, .59, .11 };
1057 foreach(light
, &ctx
->Light
.EnabledList
) {
1058 light
->dli
= DOT3(ci
, light
->Diffuse
);
1059 light
->sli
= DOT3(ci
, light
->Specular
);
1064 /* Need to seriously restrict the circumstances under which these
1065 * calc's are performed.
1067 void gl_compute_light_positions( GLcontext
*ctx
)
1069 struct gl_light
*light
;
1071 if (ctx
->Light
.NeedVertices
&& !ctx
->Light
.Model
.LocalViewer
) {
1072 GLfloat eye_z
[3] = { 0, 0, 1 };
1073 if (!ctx
->NeedEyeCoords
) {
1074 TRANSFORM_NORMAL( ctx
->EyeZDir
, eye_z
, ctx
->ModelView
.m
);
1076 COPY_3V( ctx
->EyeZDir
, eye_z
);
1080 foreach (light
, &ctx
->Light
.EnabledList
) {
1082 if (!ctx
->NeedEyeCoords
) {
1083 TRANSFORM_POINT( light
->Position
, ctx
->ModelView
.inv
,
1084 light
->EyePosition
);
1086 COPY_4FV( light
->Position
, light
->EyePosition
);
1089 if (!(light
->Flags
& LIGHT_POSITIONAL
))
1091 /* VP (VP) = Normalize( Position ) */
1092 COPY_3V( light
->VP_inf_norm
, light
->Position
);
1093 NORMALIZE_3FV( light
->VP_inf_norm
);
1095 if (!ctx
->Light
.Model
.LocalViewer
)
1097 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1098 ADD_3V( light
->h_inf_norm
, light
->VP_inf_norm
, ctx
->EyeZDir
);
1099 NORMALIZE_3FV( light
->h_inf_norm
);
1102 light
->VP_inf_spot_attenuation
= 1.0;
1105 if (light
->Flags
& LIGHT_SPOT
)
1107 if (ctx
->NeedEyeNormals
) {
1108 COPY_3V( light
->NormDirection
, light
->EyeDirection
);
1110 TRANSFORM_NORMAL( light
->NormDirection
,
1111 light
->EyeDirection
,
1115 NORMALIZE_3FV( light
->NormDirection
);
1118 /* Unlikely occurrance?
1120 if (!(light
->Flags
& LIGHT_POSITIONAL
)) {
1121 GLfloat PV_dot_dir
= - DOT3(light
->VP_inf_norm
,
1122 light
->NormDirection
);
1124 if (PV_dot_dir
> light
->CosCutoff
) {
1125 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1127 light
->VP_inf_spot_attenuation
=
1128 (light
->SpotExpTable
[k
][0] +
1129 (x
-k
)*light
->SpotExpTable
[k
][1]);
1132 light
->VP_inf_spot_attenuation
= 0;
1142 void gl_update_normal_transform( GLcontext
*ctx
)
1144 GLuint new_flag
= 0;
1145 normal_func
*last
= ctx
->NormalTransform
;
1147 ctx
->vb_rescale_factor
= 1.0;
1149 if (ctx
->NeedEyeCoords
) {
1150 if (ctx
->NeedNormals
) {
1151 GLuint transform
= NORM_TRANSFORM_NO_ROT
;
1153 if (ctx
->ModelView
.flags
& (MAT_FLAG_GENERAL
|
1155 MAT_FLAG_GENERAL_3D
|
1156 MAT_FLAG_PERSPECTIVE
))
1157 transform
= NORM_TRANSFORM
;
1160 new_flag
= ctx
->NewState
& NEW_MODELVIEW
;
1161 ctx
->vb_rescale_factor
= ctx
->rescale_factor
;
1163 if (ctx
->Transform
.Normalize
)
1165 ctx
->NormalTransform
= gl_normal_tab
[transform
| NORM_NORMALIZE
];
1167 else if (ctx
->Transform
.RescaleNormals
&&
1168 ctx
->rescale_factor
!= 1.0)
1170 ctx
->NormalTransform
= gl_normal_tab
[transform
| NORM_RESCALE
];
1174 ctx
->NormalTransform
= gl_normal_tab
[transform
];
1177 ctx
->NormalTransform
= 0;
1181 if (ctx
->NeedNormals
) {
1182 ctx
->vb_rescale_factor
= 1.0/ctx
->rescale_factor
;
1184 if (ctx
->Transform
.Normalize
)
1186 ctx
->NormalTransform
= gl_normal_tab
[NORM_NORMALIZE
];
1188 else if (!ctx
->Transform
.RescaleNormals
&&
1189 ctx
->rescale_factor
!= 1.0)
1191 ctx
->NormalTransform
= gl_normal_tab
[NORM_RESCALE
];
1195 ctx
->NormalTransform
= 0;
1198 ctx
->NormalTransform
= 0;
1202 if (last
!= ctx
->NormalTransform
|| new_flag
)
1203 ctx
->NewState
|= NEW_NORMAL_TRANSFORM
;