1 /* $Id: light.c,v 1.55 2003/03/01 01:50:21 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 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.
35 #include "simple_list.h"
37 #include "math/m_xform.h"
38 #include "math/m_matrix.h"
41 /* XXX this is a bit of a hack needed for compilation within XFree86 */
48 _mesa_ShadeModel( GLenum mode
)
50 GET_CURRENT_CONTEXT(ctx
);
51 ASSERT_OUTSIDE_BEGIN_END(ctx
);
53 if (MESA_VERBOSE
& VERBOSE_API
)
54 _mesa_debug(ctx
, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode
));
56 if (mode
!= GL_FLAT
&& mode
!= GL_SMOOTH
) {
57 _mesa_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
61 if (ctx
->Light
.ShadeModel
== mode
)
64 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
65 ctx
->Light
.ShadeModel
= mode
;
66 ctx
->_TriangleCaps
^= DD_FLATSHADE
;
67 if (ctx
->Driver
.ShadeModel
)
68 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
74 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
76 _mesa_Lightfv( light
, pname
, ¶m
);
81 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
83 GET_CURRENT_CONTEXT(ctx
);
84 GLint i
= (GLint
) (light
- GL_LIGHT0
);
85 struct gl_light
*l
= &ctx
->Light
.Light
[i
];
87 if (i
< 0 || i
>= (GLint
) ctx
->Const
.MaxLights
) {
88 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(light=0x%x)", light
);
94 if (TEST_EQ_4V(l
->Ambient
, params
))
96 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
97 COPY_4V( l
->Ambient
, params
);
100 if (TEST_EQ_4V(l
->Diffuse
, params
))
102 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
103 COPY_4V( l
->Diffuse
, params
);
106 if (TEST_EQ_4V(l
->Specular
, params
))
108 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
109 COPY_4V( l
->Specular
, params
);
113 /* transform position by ModelView matrix */
114 TRANSFORM_POINT( tmp
, ctx
->ModelviewMatrixStack
.Top
->m
, params
);
115 if (TEST_EQ_4V(l
->EyePosition
, tmp
))
117 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
118 COPY_4V(l
->EyePosition
, tmp
);
119 if (l
->EyePosition
[3] != 0.0F
)
120 l
->_Flags
|= LIGHT_POSITIONAL
;
122 l
->_Flags
&= ~LIGHT_POSITIONAL
;
125 case GL_SPOT_DIRECTION
: {
127 /* transform direction by inverse modelview */
128 if (ctx
->ModelviewMatrixStack
.Top
->flags
& MAT_DIRTY_INVERSE
) {
129 _math_matrix_analyse( ctx
->ModelviewMatrixStack
.Top
);
131 TRANSFORM_NORMAL( tmp
, params
, ctx
->ModelviewMatrixStack
.Top
->inv
);
132 if (TEST_EQ_3V(l
->EyeDirection
, tmp
))
134 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
135 COPY_3V(l
->EyeDirection
, tmp
);
138 case GL_SPOT_EXPONENT
:
139 if (params
[0]<0.0 || params
[0]>128.0) {
140 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
143 if (l
->SpotExponent
== params
[0])
145 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
146 l
->SpotExponent
= params
[0];
147 _mesa_invalidate_spot_exp_table( l
);
150 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
151 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
154 if (l
->SpotCutoff
== params
[0])
156 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
157 l
->SpotCutoff
= params
[0];
158 l
->_CosCutoff
= (GLfloat
) _mesa_cos(params
[0]*DEG2RAD
);
159 if (l
->_CosCutoff
< 0)
161 if (l
->SpotCutoff
!= 180.0F
)
162 l
->_Flags
|= LIGHT_SPOT
;
164 l
->_Flags
&= ~LIGHT_SPOT
;
166 case GL_CONSTANT_ATTENUATION
:
168 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
171 if (l
->ConstantAttenuation
== params
[0])
173 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
174 l
->ConstantAttenuation
= params
[0];
176 case GL_LINEAR_ATTENUATION
:
178 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
181 if (l
->LinearAttenuation
== params
[0])
183 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
184 l
->LinearAttenuation
= params
[0];
186 case GL_QUADRATIC_ATTENUATION
:
188 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
191 if (l
->QuadraticAttenuation
== params
[0])
193 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
194 l
->QuadraticAttenuation
= params
[0];
197 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
201 if (ctx
->Driver
.Lightfv
)
202 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
);
207 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
209 _mesa_Lightiv( light
, pname
, ¶m
);
214 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
222 fparam
[0] = INT_TO_FLOAT( params
[0] );
223 fparam
[1] = INT_TO_FLOAT( params
[1] );
224 fparam
[2] = INT_TO_FLOAT( params
[2] );
225 fparam
[3] = INT_TO_FLOAT( params
[3] );
228 fparam
[0] = (GLfloat
) params
[0];
229 fparam
[1] = (GLfloat
) params
[1];
230 fparam
[2] = (GLfloat
) params
[2];
231 fparam
[3] = (GLfloat
) params
[3];
233 case GL_SPOT_DIRECTION
:
234 fparam
[0] = (GLfloat
) params
[0];
235 fparam
[1] = (GLfloat
) params
[1];
236 fparam
[2] = (GLfloat
) params
[2];
238 case GL_SPOT_EXPONENT
:
240 case GL_CONSTANT_ATTENUATION
:
241 case GL_LINEAR_ATTENUATION
:
242 case GL_QUADRATIC_ATTENUATION
:
243 fparam
[0] = (GLfloat
) params
[0];
246 /* error will be caught later in gl_Lightfv */
250 _mesa_Lightfv( light
, pname
, fparam
);
256 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
258 GET_CURRENT_CONTEXT(ctx
);
259 GLint l
= (GLint
) (light
- GL_LIGHT0
);
260 ASSERT_OUTSIDE_BEGIN_END(ctx
);
262 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
263 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
269 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
272 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
275 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
278 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
280 case GL_SPOT_DIRECTION
:
281 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
283 case GL_SPOT_EXPONENT
:
284 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
287 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
289 case GL_CONSTANT_ATTENUATION
:
290 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
292 case GL_LINEAR_ATTENUATION
:
293 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
295 case GL_QUADRATIC_ATTENUATION
:
296 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
299 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
307 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
309 GET_CURRENT_CONTEXT(ctx
);
310 GLint l
= (GLint
) (light
- GL_LIGHT0
);
311 ASSERT_OUTSIDE_BEGIN_END(ctx
);
313 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
314 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
320 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
321 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
322 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
323 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
326 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
327 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
328 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
329 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
332 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
333 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
334 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
335 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
338 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
339 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
340 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
341 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
343 case GL_SPOT_DIRECTION
:
344 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
345 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
346 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
348 case GL_SPOT_EXPONENT
:
349 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
352 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
354 case GL_CONSTANT_ATTENUATION
:
355 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
357 case GL_LINEAR_ATTENUATION
:
358 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
360 case GL_QUADRATIC_ATTENUATION
:
361 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
364 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
371 /**********************************************************************/
372 /*** Light Model ***/
373 /**********************************************************************/
377 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
381 GET_CURRENT_CONTEXT(ctx
);
382 ASSERT_OUTSIDE_BEGIN_END(ctx
);
385 case GL_LIGHT_MODEL_AMBIENT
:
386 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
388 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
389 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
391 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
392 newbool
= (params
[0]!=0.0);
393 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
395 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
396 ctx
->Light
.Model
.LocalViewer
= newbool
;
398 case GL_LIGHT_MODEL_TWO_SIDE
:
399 newbool
= (params
[0]!=0.0);
400 if (ctx
->Light
.Model
.TwoSide
== newbool
)
402 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
403 ctx
->Light
.Model
.TwoSide
= newbool
;
405 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
)
406 ctx
->_TriangleCaps
|= DD_TRI_LIGHT_TWOSIDE
;
408 ctx
->_TriangleCaps
&= ~DD_TRI_LIGHT_TWOSIDE
;
410 case GL_LIGHT_MODEL_COLOR_CONTROL
:
411 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
412 newenum
= GL_SINGLE_COLOR
;
413 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
414 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
416 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
420 if (ctx
->Light
.Model
.ColorControl
== newenum
)
422 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
423 ctx
->Light
.Model
.ColorControl
= newenum
;
425 if ((ctx
->Light
.Enabled
&&
426 ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
)
427 || ctx
->Fog
.ColorSumEnabled
)
428 ctx
->_TriangleCaps
|= DD_SEPARATE_SPECULAR
;
430 ctx
->_TriangleCaps
&= ~DD_SEPARATE_SPECULAR
;
434 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
438 if (ctx
->Driver
.LightModelfv
)
439 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
444 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
449 case GL_LIGHT_MODEL_AMBIENT
:
450 fparam
[0] = INT_TO_FLOAT( params
[0] );
451 fparam
[1] = INT_TO_FLOAT( params
[1] );
452 fparam
[2] = INT_TO_FLOAT( params
[2] );
453 fparam
[3] = INT_TO_FLOAT( params
[3] );
455 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
456 case GL_LIGHT_MODEL_TWO_SIDE
:
457 case GL_LIGHT_MODEL_COLOR_CONTROL
:
458 fparam
[0] = (GLfloat
) params
[0];
461 /* Error will be caught later in gl_LightModelfv */
464 _mesa_LightModelfv( pname
, fparam
);
469 _mesa_LightModeli( GLenum pname
, GLint param
)
471 _mesa_LightModeliv( pname
, ¶m
);
476 _mesa_LightModelf( GLenum pname
, GLfloat param
)
478 _mesa_LightModelfv( pname
, ¶m
);
483 /********** MATERIAL **********/
487 * Given a face and pname value (ala glColorMaterial), compute a bitmask
488 * of the targeted material values.
491 _mesa_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
492 GLuint legal
, const char *where
)
496 /* Make a bitmask indicating what material attribute(s) we're updating */
499 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
502 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
505 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
508 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
511 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
513 case GL_AMBIENT_AND_DIFFUSE
:
514 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
515 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
517 case GL_COLOR_INDEXES
:
518 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
521 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
525 if (face
==GL_FRONT
) {
526 bitmask
&= FRONT_MATERIAL_BITS
;
528 else if (face
==GL_BACK
) {
529 bitmask
&= BACK_MATERIAL_BITS
;
531 else if (face
!= GL_FRONT_AND_BACK
) {
532 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
536 if (bitmask
& ~legal
) {
537 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
545 /* Perform a straight copy between pairs of materials.
547 void _mesa_copy_material_pairs( struct gl_material dst
[2],
548 const struct gl_material src
[2],
551 if (bitmask
& FRONT_EMISSION_BIT
) {
552 COPY_4FV( dst
[0].Emission
, src
[0].Emission
);
554 if (bitmask
& BACK_EMISSION_BIT
) {
555 COPY_4FV( dst
[1].Emission
, src
[1].Emission
);
557 if (bitmask
& FRONT_AMBIENT_BIT
) {
558 COPY_4FV( dst
[0].Ambient
, src
[0].Ambient
);
560 if (bitmask
& BACK_AMBIENT_BIT
) {
561 COPY_4FV( dst
[1].Ambient
, src
[1].Ambient
);
563 if (bitmask
& FRONT_DIFFUSE_BIT
) {
564 COPY_4FV( dst
[0].Diffuse
, src
[0].Diffuse
);
566 if (bitmask
& BACK_DIFFUSE_BIT
) {
567 COPY_4FV( dst
[1].Diffuse
, src
[1].Diffuse
);
569 if (bitmask
& FRONT_SPECULAR_BIT
) {
570 COPY_4FV( dst
[0].Specular
, src
[0].Specular
);
572 if (bitmask
& BACK_SPECULAR_BIT
) {
573 COPY_4FV( dst
[1].Specular
, src
[1].Specular
);
575 if (bitmask
& FRONT_SHININESS_BIT
) {
576 dst
[0].Shininess
= src
[0].Shininess
;
578 if (bitmask
& BACK_SHININESS_BIT
) {
579 dst
[1].Shininess
= src
[1].Shininess
;
581 if (bitmask
& FRONT_INDEXES_BIT
) {
582 dst
[0].AmbientIndex
= src
[0].AmbientIndex
;
583 dst
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
584 dst
[0].SpecularIndex
= src
[0].SpecularIndex
;
586 if (bitmask
& BACK_INDEXES_BIT
) {
587 dst
[1].AmbientIndex
= src
[1].AmbientIndex
;
588 dst
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
589 dst
[1].SpecularIndex
= src
[1].SpecularIndex
;
595 * Check if the global material has to be updated with info that was
596 * associated with a vertex via glMaterial.
597 * This function is used when any material values get changed between
598 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
599 * when GL_COLOR_MATERIAL is enabled.
601 * src[0] is front material, src[1] is back material
603 * Additionally keeps the precomputed lighting state uptodate.
605 void _mesa_update_material( GLcontext
*ctx
,
606 const struct gl_material src
[2],
609 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
611 if (ctx
->Light
.ColorMaterialEnabled
)
612 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
614 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
615 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
620 /* update material emission */
621 if (bitmask
& FRONT_EMISSION_BIT
) {
622 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
623 COPY_4FV( mat
->Emission
, src
[0].Emission
);
625 if (bitmask
& BACK_EMISSION_BIT
) {
626 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
627 COPY_4FV( mat
->Emission
, src
[1].Emission
);
630 /* update material ambience */
631 if (bitmask
& FRONT_AMBIENT_BIT
) {
632 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
633 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
634 foreach (light
, list
) {
635 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, src
[0].Ambient
);
638 if (bitmask
& BACK_AMBIENT_BIT
) {
639 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
640 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
641 foreach (light
, list
) {
642 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, src
[1].Ambient
);
646 /* update BaseColor = emission + scene's ambience * material's ambience */
647 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
648 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
649 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
650 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
,
651 ctx
->Light
.Model
.Ambient
);
653 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
654 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
655 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
656 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
,
657 ctx
->Light
.Model
.Ambient
);
660 /* update material diffuse values */
661 if (bitmask
& FRONT_DIFFUSE_BIT
) {
662 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
663 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
664 foreach (light
, list
) {
665 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
668 if (bitmask
& BACK_DIFFUSE_BIT
) {
669 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
670 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
671 foreach (light
, list
) {
672 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
676 /* update material specular values */
677 if (bitmask
& FRONT_SPECULAR_BIT
) {
678 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
679 COPY_4FV( mat
->Specular
, src
[0].Specular
);
680 foreach (light
, list
) {
681 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
684 if (bitmask
& BACK_SPECULAR_BIT
) {
685 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
686 COPY_4FV( mat
->Specular
, src
[1].Specular
);
687 foreach (light
, list
) {
688 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
692 if (bitmask
& FRONT_SHININESS_BIT
) {
693 ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
694 _mesa_invalidate_shine_table( ctx
, 0 );
696 if (bitmask
& BACK_SHININESS_BIT
) {
697 ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
698 _mesa_invalidate_shine_table( ctx
, 1 );
701 if (bitmask
& FRONT_INDEXES_BIT
) {
702 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
703 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
704 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
706 if (bitmask
& BACK_INDEXES_BIT
) {
707 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
708 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
709 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
713 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
714 _mesa_debug(ctx
, "update_mat emission : %f %f %f\n",
715 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
716 _mesa_debug(ctx
, "update_mat specular : %f %f %f\n",
717 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
718 _mesa_debug(ctx
, "update_mat diffuse : %f %f %f\n",
719 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
720 _mesa_debug(ctx
, "update_mat ambient : %f %f %f\n",
721 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
732 * Update the current materials from the given rgba color
733 * according to the bitmask in ColorMaterialBitmask, which is
734 * set by glColorMaterial().
736 void _mesa_update_color_material( GLcontext
*ctx
,
737 const GLfloat color
[4] )
739 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
740 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
742 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
743 _mesa_debug(ctx
, "_mesa_update_color_material, mask 0x%x\n", bitmask
);
745 /* update emissive colors */
746 if (bitmask
& FRONT_EMISSION_BIT
) {
747 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
748 COPY_4FV( mat
->Emission
, color
);
751 if (bitmask
& BACK_EMISSION_BIT
) {
752 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
753 COPY_4FV( mat
->Emission
, color
);
756 /* update light->_MatAmbient = light's ambient * material's ambient */
757 if (bitmask
& FRONT_AMBIENT_BIT
) {
758 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
759 foreach (light
, list
) {
760 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, color
);
762 COPY_4FV( mat
->Ambient
, color
);
765 if (bitmask
& BACK_AMBIENT_BIT
) {
766 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
767 foreach (light
, list
) {
768 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, color
);
770 COPY_4FV( mat
->Ambient
, color
);
773 /* update BaseColor = emission + scene's ambience * material's ambience */
774 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
775 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
776 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
777 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
780 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
781 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
782 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
783 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
786 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
787 if (bitmask
& FRONT_DIFFUSE_BIT
) {
788 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
789 COPY_4FV( mat
->Diffuse
, color
);
790 foreach (light
, list
) {
791 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
795 if (bitmask
& BACK_DIFFUSE_BIT
) {
796 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
797 COPY_4FV( mat
->Diffuse
, color
);
798 foreach (light
, list
) {
799 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
803 /* update light->_MatSpecular = light's specular * material's specular */
804 if (bitmask
& FRONT_SPECULAR_BIT
) {
805 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
806 COPY_4FV( mat
->Specular
, color
);
807 foreach (light
, list
) {
808 ACC_SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
812 if (bitmask
& BACK_SPECULAR_BIT
) {
813 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
814 COPY_4FV( mat
->Specular
, color
);
815 foreach (light
, list
) {
816 ACC_SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
821 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
822 _mesa_debug(ctx
, "update_color_mat emission : %f %f %f\n",
823 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
824 _mesa_debug(ctx
, "update_color_mat specular : %f %f %f\n",
825 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
826 _mesa_debug(ctx
, "update_color_mat diffuse : %f %f %f\n",
827 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
828 _mesa_debug(ctx
, "update_color_mat ambient : %f %f %f\n",
829 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
837 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
839 GET_CURRENT_CONTEXT(ctx
);
841 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
842 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
843 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
844 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
845 ASSERT_OUTSIDE_BEGIN_END(ctx
);
847 if (MESA_VERBOSE
&VERBOSE_API
)
848 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
849 _mesa_lookup_enum_by_nr(face
),
850 _mesa_lookup_enum_by_nr(mode
));
852 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
854 if (ctx
->Light
.ColorMaterialBitmask
== bitmask
&&
855 ctx
->Light
.ColorMaterialFace
== face
&&
856 ctx
->Light
.ColorMaterialMode
== mode
)
859 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
860 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
861 ctx
->Light
.ColorMaterialFace
= face
;
862 ctx
->Light
.ColorMaterialMode
= mode
;
864 if (ctx
->Light
.ColorMaterialEnabled
) {
865 FLUSH_CURRENT( ctx
, 0 );
866 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
869 if (ctx
->Driver
.ColorMaterial
)
870 (*ctx
->Driver
.ColorMaterial
)( ctx
, face
, mode
);
878 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
880 GET_CURRENT_CONTEXT(ctx
);
882 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
884 if (face
==GL_FRONT
) {
887 else if (face
==GL_BACK
) {
891 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
896 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
899 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
902 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
905 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
908 *params
= ctx
->Light
.Material
[f
].Shininess
;
910 case GL_COLOR_INDEXES
:
911 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
912 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
913 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
916 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
923 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
925 GET_CURRENT_CONTEXT(ctx
);
927 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
929 if (face
==GL_FRONT
) {
932 else if (face
==GL_BACK
) {
936 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
941 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
942 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
943 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
944 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
947 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
948 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
949 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
950 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
953 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
954 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
955 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
956 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
959 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
960 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
961 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
962 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
965 *params
= IROUND( ctx
->Light
.Material
[f
].Shininess
);
967 case GL_COLOR_INDEXES
:
968 params
[0] = IROUND( ctx
->Light
.Material
[f
].AmbientIndex
);
969 params
[1] = IROUND( ctx
->Light
.Material
[f
].DiffuseIndex
);
970 params
[2] = IROUND( ctx
->Light
.Material
[f
].SpecularIndex
);
973 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
980 /**********************************************************************/
981 /***** Lighting computation *****/
982 /**********************************************************************/
987 * When two-sided lighting is enabled we compute the color (or index)
988 * for both the front and back side of the primitive. Then, when the
989 * orientation of the facet is later learned, we can determine which
990 * color (or index) to use for rendering.
992 * KW: We now know orientation in advance and only shade for
993 * the side or sides which are actually required.
997 * V = vertex position
998 * P = light source position
1003 * // light at infinity
1004 * IF local_viewer THEN
1005 * _VP_inf_norm = unit vector from V to P // Precompute
1007 * // eye at infinity
1008 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1013 * Normalize( v ) = normalized vector v
1014 * Magnitude( v ) = length of vector v
1020 * Whenever the spotlight exponent for a light changes we must call
1021 * this function to recompute the exponent lookup table.
1024 _mesa_invalidate_spot_exp_table( struct gl_light
*l
)
1026 l
->_SpotExpTable
[0][0] = -1;
1029 static void validate_spot_exp_table( struct gl_light
*l
)
1032 GLdouble exponent
= l
->SpotExponent
;
1036 l
->_SpotExpTable
[0][0] = 0.0;
1038 for (i
= EXP_TABLE_SIZE
- 1; i
> 0 ;i
--) {
1040 tmp
= _mesa_pow(i
/ (GLdouble
) (EXP_TABLE_SIZE
- 1), exponent
);
1041 if (tmp
< FLT_MIN
* 100.0) {
1046 l
->_SpotExpTable
[i
][0] = (GLfloat
) tmp
;
1048 for (i
= 0; i
< EXP_TABLE_SIZE
- 1; i
++) {
1049 l
->_SpotExpTable
[i
][1] = (l
->_SpotExpTable
[i
+1][0] -
1050 l
->_SpotExpTable
[i
][0]);
1052 l
->_SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
1058 /* Calculate a new shine table. Doing this here saves a branch in
1059 * lighting, and the cost of doing it early may be partially offset
1060 * by keeping a MRU cache of shine tables for various shine values.
1063 _mesa_invalidate_shine_table( GLcontext
*ctx
, GLuint i
)
1065 if (ctx
->_ShineTable
[i
])
1066 ctx
->_ShineTable
[i
]->refcount
--;
1067 ctx
->_ShineTable
[i
] = 0;
1070 static void validate_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
1072 struct gl_shine_tab
*list
= ctx
->_ShineTabList
;
1073 struct gl_shine_tab
*s
;
1076 if ( s
->shininess
== shininess
)
1084 if (s
->refcount
== 0)
1089 if (shininess
== 0.0) {
1090 for (j
= 1 ; j
<= SHINE_TABLE_SIZE
; j
++)
1094 for (j
= 1 ; j
< SHINE_TABLE_SIZE
; j
++) {
1095 GLdouble t
, x
= j
/ (GLfloat
) (SHINE_TABLE_SIZE
- 1);
1096 if (x
< 0.005) /* underflow check */
1098 t
= _mesa_pow(x
, shininess
);
1104 m
[SHINE_TABLE_SIZE
] = 1.0;
1107 s
->shininess
= shininess
;
1110 if (ctx
->_ShineTable
[i
])
1111 ctx
->_ShineTable
[i
]->refcount
--;
1113 ctx
->_ShineTable
[i
] = s
;
1114 move_to_tail( list
, s
);
1119 _mesa_validate_all_lighting_tables( GLcontext
*ctx
)
1124 shininess
= ctx
->Light
.Material
[0].Shininess
;
1125 if (!ctx
->_ShineTable
[0] || ctx
->_ShineTable
[0]->shininess
!= shininess
)
1126 validate_shine_table( ctx
, 0, shininess
);
1128 shininess
= ctx
->Light
.Material
[1].Shininess
;
1129 if (!ctx
->_ShineTable
[1] || ctx
->_ShineTable
[1]->shininess
!= shininess
)
1130 validate_shine_table( ctx
, 1, shininess
);
1132 for (i
= 0 ; i
< MAX_LIGHTS
; i
++)
1133 if (ctx
->Light
.Light
[i
]._SpotExpTable
[0][0] == -1)
1134 validate_spot_exp_table( &ctx
->Light
.Light
[i
] );
1141 * Examine current lighting parameters to determine if the optimized lighting
1142 * function can be used.
1143 * Also, precompute some lighting values such as the products of light
1144 * source and material ambient, diffuse and specular coefficients.
1147 _mesa_update_lighting( GLcontext
*ctx
)
1149 struct gl_light
*light
;
1150 ctx
->_NeedEyeCoords
&= ~NEED_EYE_LIGHT
;
1151 ctx
->_NeedNormals
&= ~NEED_NORMALS_LIGHT
;
1152 ctx
->Light
._Flags
= 0;
1154 if (!ctx
->Light
.Enabled
)
1157 ctx
->_NeedNormals
|= NEED_NORMALS_LIGHT
;
1159 foreach(light
, &ctx
->Light
.EnabledList
) {
1160 ctx
->Light
._Flags
|= light
->_Flags
;
1163 ctx
->Light
._NeedVertices
=
1164 ((ctx
->Light
._Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
1165 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
1166 ctx
->Light
.Model
.LocalViewer
);
1168 if ((ctx
->Light
._Flags
& LIGHT_POSITIONAL
) ||
1169 ctx
->Light
.Model
.LocalViewer
)
1170 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1173 /* XXX: This test is overkill & needs to be fixed both for software and
1174 * hardware t&l drivers. The above should be sufficient & should
1175 * be tested to verify this.
1177 if (ctx
->Light
._NeedVertices
)
1178 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1181 /* Precompute some shading values. Although we reference
1182 * Light.Material here, we can get away without flushing
1183 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
1184 * are flushed, they will update the derived state at that time.
1186 if (ctx
->Visual
.rgbMode
) {
1187 GLuint sides
= ctx
->Light
.Model
.TwoSide
? 2 : 1;
1189 for (side
=0; side
< sides
; side
++) {
1190 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1192 COPY_3V(ctx
->Light
._BaseColor
[side
], mat
->Emission
);
1193 ACC_SCALE_3V(ctx
->Light
._BaseColor
[side
],
1194 ctx
->Light
.Model
.Ambient
,
1198 foreach (light
, &ctx
->Light
.EnabledList
) {
1199 for (side
=0; side
< sides
; side
++) {
1200 const struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1201 SCALE_3V( light
->_MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1202 SCALE_3V( light
->_MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1203 SCALE_3V( light
->_MatSpecular
[side
], light
->Specular
,
1209 static const GLfloat ci
[3] = { .30F
, .59F
, .11F
};
1210 foreach(light
, &ctx
->Light
.EnabledList
) {
1211 light
->_dli
= DOT3(ci
, light
->Diffuse
);
1212 light
->_sli
= DOT3(ci
, light
->Specular
);
1220 * _TNL_NEW_NEED_EYE_COORDS
1222 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1223 * Also update on lighting space changes.
1226 _mesa_compute_light_positions( GLcontext
*ctx
)
1228 struct gl_light
*light
;
1229 static const GLfloat eye_z
[3] = { 0, 0, 1 };
1231 if (!ctx
->Light
.Enabled
)
1234 if (ctx
->_NeedEyeCoords
) {
1235 COPY_3V( ctx
->_EyeZDir
, eye_z
);
1238 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
1241 foreach (light
, &ctx
->Light
.EnabledList
) {
1243 if (ctx
->_NeedEyeCoords
) {
1244 COPY_4FV( light
->_Position
, light
->EyePosition
);
1247 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
1248 light
->EyePosition
);
1251 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1252 /* VP (VP) = Normalize( Position ) */
1253 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
1254 NORMALIZE_3FV( light
->_VP_inf_norm
);
1256 if (!ctx
->Light
.Model
.LocalViewer
) {
1257 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1258 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
1259 NORMALIZE_3FV( light
->_h_inf_norm
);
1261 light
->_VP_inf_spot_attenuation
= 1.0;
1264 if (light
->_Flags
& LIGHT_SPOT
) {
1265 if (ctx
->_NeedEyeCoords
) {
1266 COPY_3V( light
->_NormDirection
, light
->EyeDirection
);
1269 TRANSFORM_NORMAL( light
->_NormDirection
,
1270 light
->EyeDirection
,
1271 ctx
->ModelviewMatrixStack
.Top
->m
);
1274 NORMALIZE_3FV( light
->_NormDirection
);
1276 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1277 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1278 light
->_NormDirection
);
1280 if (PV_dot_dir
> light
->_CosCutoff
) {
1281 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1283 light
->_VP_inf_spot_attenuation
=
1284 (GLfloat
) (light
->_SpotExpTable
[k
][0] +
1285 (x
-k
)*light
->_SpotExpTable
[k
][1]);
1288 light
->_VP_inf_spot_attenuation
= 0;