1 /* $Id: light.c,v 1.53 2002/10/24 23:57:21 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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.
36 #include "simple_list.h"
38 #include "math/m_xform.h"
39 #include "math/m_matrix.h"
42 /* XXX this is a bit of a hack needed for compilation within XFree86 */
49 _mesa_ShadeModel( GLenum mode
)
51 GET_CURRENT_CONTEXT(ctx
);
52 ASSERT_OUTSIDE_BEGIN_END(ctx
);
54 if (MESA_VERBOSE
& VERBOSE_API
)
55 _mesa_debug(ctx
, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode
));
57 if (mode
!= GL_FLAT
&& mode
!= GL_SMOOTH
) {
58 _mesa_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
62 if (ctx
->Light
.ShadeModel
== mode
)
65 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
66 ctx
->Light
.ShadeModel
= mode
;
67 ctx
->_TriangleCaps
^= DD_FLATSHADE
;
68 if (ctx
->Driver
.ShadeModel
)
69 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
75 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
77 _mesa_Lightfv( light
, pname
, ¶m
);
82 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
84 GET_CURRENT_CONTEXT(ctx
);
85 GLint i
= (GLint
) (light
- GL_LIGHT0
);
86 struct gl_light
*l
= &ctx
->Light
.Light
[i
];
88 if (i
< 0 || i
>= (GLint
) ctx
->Const
.MaxLights
) {
89 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(light=0x%x)", light
);
95 if (TEST_EQ_4V(l
->Ambient
, params
))
97 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
98 COPY_4V( l
->Ambient
, params
);
101 if (TEST_EQ_4V(l
->Diffuse
, params
))
103 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
104 COPY_4V( l
->Diffuse
, params
);
107 if (TEST_EQ_4V(l
->Specular
, params
))
109 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
110 COPY_4V( l
->Specular
, params
);
114 /* transform position by ModelView matrix */
115 TRANSFORM_POINT( tmp
, ctx
->ModelviewMatrixStack
.Top
->m
, params
);
116 if (TEST_EQ_4V(l
->EyePosition
, tmp
))
118 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
119 COPY_4V(l
->EyePosition
, tmp
);
120 if (l
->EyePosition
[3] != 0.0F
)
121 l
->_Flags
|= LIGHT_POSITIONAL
;
123 l
->_Flags
&= ~LIGHT_POSITIONAL
;
126 case GL_SPOT_DIRECTION
: {
128 /* transform direction by inverse modelview */
129 if (ctx
->ModelviewMatrixStack
.Top
->flags
& MAT_DIRTY_INVERSE
) {
130 _math_matrix_analyse( ctx
->ModelviewMatrixStack
.Top
);
132 TRANSFORM_NORMAL( tmp
, params
, ctx
->ModelviewMatrixStack
.Top
->inv
);
133 if (TEST_EQ_3V(l
->EyeDirection
, tmp
))
135 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
136 COPY_3V(l
->EyeDirection
, tmp
);
139 case GL_SPOT_EXPONENT
:
140 if (params
[0]<0.0 || params
[0]>128.0) {
141 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
144 if (l
->SpotExponent
== params
[0])
146 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
147 l
->SpotExponent
= params
[0];
148 _mesa_invalidate_spot_exp_table( l
);
151 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
152 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
155 if (l
->SpotCutoff
== params
[0])
157 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
158 l
->SpotCutoff
= params
[0];
159 l
->_CosCutoff
= (GLfloat
) cos(params
[0]*DEG2RAD
);
160 if (l
->_CosCutoff
< 0)
162 if (l
->SpotCutoff
!= 180.0F
)
163 l
->_Flags
|= LIGHT_SPOT
;
165 l
->_Flags
&= ~LIGHT_SPOT
;
167 case GL_CONSTANT_ATTENUATION
:
169 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
172 if (l
->ConstantAttenuation
== params
[0])
174 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
175 l
->ConstantAttenuation
= params
[0];
177 case GL_LINEAR_ATTENUATION
:
179 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
182 if (l
->LinearAttenuation
== params
[0])
184 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
185 l
->LinearAttenuation
= params
[0];
187 case GL_QUADRATIC_ATTENUATION
:
189 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
192 if (l
->QuadraticAttenuation
== params
[0])
194 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
195 l
->QuadraticAttenuation
= params
[0];
198 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
202 if (ctx
->Driver
.Lightfv
)
203 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
);
208 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
210 _mesa_Lightiv( light
, pname
, ¶m
);
215 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
223 fparam
[0] = INT_TO_FLOAT( params
[0] );
224 fparam
[1] = INT_TO_FLOAT( params
[1] );
225 fparam
[2] = INT_TO_FLOAT( params
[2] );
226 fparam
[3] = INT_TO_FLOAT( params
[3] );
229 fparam
[0] = (GLfloat
) params
[0];
230 fparam
[1] = (GLfloat
) params
[1];
231 fparam
[2] = (GLfloat
) params
[2];
232 fparam
[3] = (GLfloat
) params
[3];
234 case GL_SPOT_DIRECTION
:
235 fparam
[0] = (GLfloat
) params
[0];
236 fparam
[1] = (GLfloat
) params
[1];
237 fparam
[2] = (GLfloat
) params
[2];
239 case GL_SPOT_EXPONENT
:
241 case GL_CONSTANT_ATTENUATION
:
242 case GL_LINEAR_ATTENUATION
:
243 case GL_QUADRATIC_ATTENUATION
:
244 fparam
[0] = (GLfloat
) params
[0];
247 /* error will be caught later in gl_Lightfv */
251 _mesa_Lightfv( light
, pname
, fparam
);
257 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
259 GET_CURRENT_CONTEXT(ctx
);
260 GLint l
= (GLint
) (light
- GL_LIGHT0
);
261 ASSERT_OUTSIDE_BEGIN_END(ctx
);
263 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
264 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
270 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
273 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
276 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
279 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
281 case GL_SPOT_DIRECTION
:
282 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
284 case GL_SPOT_EXPONENT
:
285 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
288 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
290 case GL_CONSTANT_ATTENUATION
:
291 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
293 case GL_LINEAR_ATTENUATION
:
294 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
296 case GL_QUADRATIC_ATTENUATION
:
297 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
300 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
308 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
310 GET_CURRENT_CONTEXT(ctx
);
311 GLint l
= (GLint
) (light
- GL_LIGHT0
);
312 ASSERT_OUTSIDE_BEGIN_END(ctx
);
314 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
315 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
321 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
322 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
323 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
324 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
327 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
328 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
329 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
330 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
333 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
334 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
335 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
336 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
339 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
340 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
341 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
342 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
344 case GL_SPOT_DIRECTION
:
345 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
346 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
347 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
349 case GL_SPOT_EXPONENT
:
350 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
353 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
355 case GL_CONSTANT_ATTENUATION
:
356 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
358 case GL_LINEAR_ATTENUATION
:
359 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
361 case GL_QUADRATIC_ATTENUATION
:
362 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
365 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
372 /**********************************************************************/
373 /*** Light Model ***/
374 /**********************************************************************/
378 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
382 GET_CURRENT_CONTEXT(ctx
);
383 ASSERT_OUTSIDE_BEGIN_END(ctx
);
386 case GL_LIGHT_MODEL_AMBIENT
:
387 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
389 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
390 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
392 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
393 newbool
= (params
[0]!=0.0);
394 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
396 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
397 ctx
->Light
.Model
.LocalViewer
= newbool
;
399 case GL_LIGHT_MODEL_TWO_SIDE
:
400 newbool
= (params
[0]!=0.0);
401 if (ctx
->Light
.Model
.TwoSide
== newbool
)
403 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
404 ctx
->Light
.Model
.TwoSide
= newbool
;
406 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
)
407 ctx
->_TriangleCaps
|= DD_TRI_LIGHT_TWOSIDE
;
409 ctx
->_TriangleCaps
&= ~DD_TRI_LIGHT_TWOSIDE
;
411 case GL_LIGHT_MODEL_COLOR_CONTROL
:
412 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
413 newenum
= GL_SINGLE_COLOR
;
414 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
415 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
417 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
421 if (ctx
->Light
.Model
.ColorControl
== newenum
)
423 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
424 ctx
->Light
.Model
.ColorControl
= newenum
;
426 if ((ctx
->Light
.Enabled
&&
427 ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
)
428 || ctx
->Fog
.ColorSumEnabled
)
429 ctx
->_TriangleCaps
|= DD_SEPARATE_SPECULAR
;
431 ctx
->_TriangleCaps
&= ~DD_SEPARATE_SPECULAR
;
435 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
439 if (ctx
->Driver
.LightModelfv
)
440 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
445 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
450 case GL_LIGHT_MODEL_AMBIENT
:
451 fparam
[0] = INT_TO_FLOAT( params
[0] );
452 fparam
[1] = INT_TO_FLOAT( params
[1] );
453 fparam
[2] = INT_TO_FLOAT( params
[2] );
454 fparam
[3] = INT_TO_FLOAT( params
[3] );
456 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
457 case GL_LIGHT_MODEL_TWO_SIDE
:
458 case GL_LIGHT_MODEL_COLOR_CONTROL
:
459 fparam
[0] = (GLfloat
) params
[0];
462 /* Error will be caught later in gl_LightModelfv */
465 _mesa_LightModelfv( pname
, fparam
);
470 _mesa_LightModeli( GLenum pname
, GLint param
)
472 _mesa_LightModeliv( pname
, ¶m
);
477 _mesa_LightModelf( GLenum pname
, GLfloat param
)
479 _mesa_LightModelfv( pname
, ¶m
);
484 /********** MATERIAL **********/
488 * Given a face and pname value (ala glColorMaterial), compute a bitmask
489 * of the targeted material values.
492 _mesa_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
493 GLuint legal
, const char *where
)
497 /* Make a bitmask indicating what material attribute(s) we're updating */
500 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
503 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
506 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
509 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
512 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
514 case GL_AMBIENT_AND_DIFFUSE
:
515 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
516 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
518 case GL_COLOR_INDEXES
:
519 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
522 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
526 if (face
==GL_FRONT
) {
527 bitmask
&= FRONT_MATERIAL_BITS
;
529 else if (face
==GL_BACK
) {
530 bitmask
&= BACK_MATERIAL_BITS
;
532 else if (face
!= GL_FRONT_AND_BACK
) {
533 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
537 if (bitmask
& ~legal
) {
538 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
546 /* Perform a straight copy between pairs of materials.
548 void _mesa_copy_material_pairs( struct gl_material dst
[2],
549 const struct gl_material src
[2],
552 if (bitmask
& FRONT_EMISSION_BIT
) {
553 COPY_4FV( dst
[0].Emission
, src
[0].Emission
);
555 if (bitmask
& BACK_EMISSION_BIT
) {
556 COPY_4FV( dst
[1].Emission
, src
[1].Emission
);
558 if (bitmask
& FRONT_AMBIENT_BIT
) {
559 COPY_4FV( dst
[0].Ambient
, src
[0].Ambient
);
561 if (bitmask
& BACK_AMBIENT_BIT
) {
562 COPY_4FV( dst
[1].Ambient
, src
[1].Ambient
);
564 if (bitmask
& FRONT_DIFFUSE_BIT
) {
565 COPY_4FV( dst
[0].Diffuse
, src
[0].Diffuse
);
567 if (bitmask
& BACK_DIFFUSE_BIT
) {
568 COPY_4FV( dst
[1].Diffuse
, src
[1].Diffuse
);
570 if (bitmask
& FRONT_SPECULAR_BIT
) {
571 COPY_4FV( dst
[0].Specular
, src
[0].Specular
);
573 if (bitmask
& BACK_SPECULAR_BIT
) {
574 COPY_4FV( dst
[1].Specular
, src
[1].Specular
);
576 if (bitmask
& FRONT_SHININESS_BIT
) {
577 dst
[0].Shininess
= src
[0].Shininess
;
579 if (bitmask
& BACK_SHININESS_BIT
) {
580 dst
[1].Shininess
= src
[1].Shininess
;
582 if (bitmask
& FRONT_INDEXES_BIT
) {
583 dst
[0].AmbientIndex
= src
[0].AmbientIndex
;
584 dst
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
585 dst
[0].SpecularIndex
= src
[0].SpecularIndex
;
587 if (bitmask
& BACK_INDEXES_BIT
) {
588 dst
[1].AmbientIndex
= src
[1].AmbientIndex
;
589 dst
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
590 dst
[1].SpecularIndex
= src
[1].SpecularIndex
;
596 * Check if the global material has to be updated with info that was
597 * associated with a vertex via glMaterial.
598 * This function is used when any material values get changed between
599 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
600 * when GL_COLOR_MATERIAL is enabled.
602 * src[0] is front material, src[1] is back material
604 * Additionally keeps the precomputed lighting state uptodate.
606 void _mesa_update_material( GLcontext
*ctx
,
607 const struct gl_material src
[2],
610 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
612 if (ctx
->Light
.ColorMaterialEnabled
)
613 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
615 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
616 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
621 /* update material emission */
622 if (bitmask
& FRONT_EMISSION_BIT
) {
623 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
624 COPY_4FV( mat
->Emission
, src
[0].Emission
);
626 if (bitmask
& BACK_EMISSION_BIT
) {
627 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
628 COPY_4FV( mat
->Emission
, src
[1].Emission
);
631 /* update material ambience */
632 if (bitmask
& FRONT_AMBIENT_BIT
) {
633 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
634 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
635 foreach (light
, list
) {
636 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, src
[0].Ambient
);
639 if (bitmask
& BACK_AMBIENT_BIT
) {
640 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
641 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
642 foreach (light
, list
) {
643 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, src
[1].Ambient
);
647 /* update BaseColor = emission + scene's ambience * material's ambience */
648 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
649 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
650 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
651 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
,
652 ctx
->Light
.Model
.Ambient
);
654 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
655 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
656 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
657 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
,
658 ctx
->Light
.Model
.Ambient
);
661 /* update material diffuse values */
662 if (bitmask
& FRONT_DIFFUSE_BIT
) {
663 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
664 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
665 foreach (light
, list
) {
666 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
669 if (bitmask
& BACK_DIFFUSE_BIT
) {
670 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
671 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
672 foreach (light
, list
) {
673 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
677 /* update material specular values */
678 if (bitmask
& FRONT_SPECULAR_BIT
) {
679 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
680 COPY_4FV( mat
->Specular
, src
[0].Specular
);
681 foreach (light
, list
) {
682 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
685 if (bitmask
& BACK_SPECULAR_BIT
) {
686 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
687 COPY_4FV( mat
->Specular
, src
[1].Specular
);
688 foreach (light
, list
) {
689 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
693 if (bitmask
& FRONT_SHININESS_BIT
) {
694 ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
695 _mesa_invalidate_shine_table( ctx
, 0 );
697 if (bitmask
& BACK_SHININESS_BIT
) {
698 ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
699 _mesa_invalidate_shine_table( ctx
, 1 );
702 if (bitmask
& FRONT_INDEXES_BIT
) {
703 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
704 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
705 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
707 if (bitmask
& BACK_INDEXES_BIT
) {
708 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
709 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
710 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
714 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
715 _mesa_debug(ctx
, "update_mat emission : %f %f %f\n",
716 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
717 _mesa_debug(ctx
, "update_mat specular : %f %f %f\n",
718 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
719 _mesa_debug(ctx
, "update_mat diffuse : %f %f %f\n",
720 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
721 _mesa_debug(ctx
, "update_mat ambient : %f %f %f\n",
722 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
733 * Update the current materials from the given rgba color
734 * according to the bitmask in ColorMaterialBitmask, which is
735 * set by glColorMaterial().
737 void _mesa_update_color_material( GLcontext
*ctx
,
738 const GLfloat color
[4] )
740 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
741 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
743 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
744 _mesa_debug(ctx
, "_mesa_update_color_material, mask 0x%x\n", bitmask
);
746 /* update emissive colors */
747 if (bitmask
& FRONT_EMISSION_BIT
) {
748 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
749 COPY_4FV( mat
->Emission
, color
);
752 if (bitmask
& BACK_EMISSION_BIT
) {
753 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
754 COPY_4FV( mat
->Emission
, color
);
757 /* update light->_MatAmbient = light's ambient * material's ambient */
758 if (bitmask
& FRONT_AMBIENT_BIT
) {
759 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
760 foreach (light
, list
) {
761 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, color
);
763 COPY_4FV( mat
->Ambient
, color
);
766 if (bitmask
& BACK_AMBIENT_BIT
) {
767 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
768 foreach (light
, list
) {
769 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, color
);
771 COPY_4FV( mat
->Ambient
, color
);
774 /* update BaseColor = emission + scene's ambience * material's ambience */
775 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
776 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
777 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
778 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
781 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
782 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
783 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
784 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
787 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
788 if (bitmask
& FRONT_DIFFUSE_BIT
) {
789 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
790 COPY_4FV( mat
->Diffuse
, color
);
791 foreach (light
, list
) {
792 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
796 if (bitmask
& BACK_DIFFUSE_BIT
) {
797 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
798 COPY_4FV( mat
->Diffuse
, color
);
799 foreach (light
, list
) {
800 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
804 /* update light->_MatSpecular = light's specular * material's specular */
805 if (bitmask
& FRONT_SPECULAR_BIT
) {
806 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
807 COPY_4FV( mat
->Specular
, color
);
808 foreach (light
, list
) {
809 ACC_SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
813 if (bitmask
& BACK_SPECULAR_BIT
) {
814 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
815 COPY_4FV( mat
->Specular
, color
);
816 foreach (light
, list
) {
817 ACC_SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
822 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
823 _mesa_debug(ctx
, "update_color_mat emission : %f %f %f\n",
824 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
825 _mesa_debug(ctx
, "update_color_mat specular : %f %f %f\n",
826 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
827 _mesa_debug(ctx
, "update_color_mat diffuse : %f %f %f\n",
828 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
829 _mesa_debug(ctx
, "update_color_mat ambient : %f %f %f\n",
830 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
838 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
840 GET_CURRENT_CONTEXT(ctx
);
842 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
843 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
844 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
845 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
846 ASSERT_OUTSIDE_BEGIN_END(ctx
);
848 if (MESA_VERBOSE
&VERBOSE_API
)
849 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
850 _mesa_lookup_enum_by_nr(face
),
851 _mesa_lookup_enum_by_nr(mode
));
853 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
855 if (ctx
->Light
.ColorMaterialBitmask
== bitmask
&&
856 ctx
->Light
.ColorMaterialFace
== face
&&
857 ctx
->Light
.ColorMaterialMode
== mode
)
860 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
861 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
862 ctx
->Light
.ColorMaterialFace
= face
;
863 ctx
->Light
.ColorMaterialMode
= mode
;
865 if (ctx
->Light
.ColorMaterialEnabled
) {
866 FLUSH_CURRENT( ctx
, 0 );
867 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
870 if (ctx
->Driver
.ColorMaterial
)
871 (*ctx
->Driver
.ColorMaterial
)( ctx
, face
, mode
);
879 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
881 GET_CURRENT_CONTEXT(ctx
);
883 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
885 if (face
==GL_FRONT
) {
888 else if (face
==GL_BACK
) {
892 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
897 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
900 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
903 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
906 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
909 *params
= ctx
->Light
.Material
[f
].Shininess
;
911 case GL_COLOR_INDEXES
:
912 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
913 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
914 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
917 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
924 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
926 GET_CURRENT_CONTEXT(ctx
);
928 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
930 if (face
==GL_FRONT
) {
933 else if (face
==GL_BACK
) {
937 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
942 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
943 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
944 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
945 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
948 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
949 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
950 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
951 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
954 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
955 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
956 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
957 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
960 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
961 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
962 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
963 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
966 *params
= ROUNDF( ctx
->Light
.Material
[f
].Shininess
);
968 case GL_COLOR_INDEXES
:
969 params
[0] = ROUNDF( ctx
->Light
.Material
[f
].AmbientIndex
);
970 params
[1] = ROUNDF( ctx
->Light
.Material
[f
].DiffuseIndex
);
971 params
[2] = ROUNDF( ctx
->Light
.Material
[f
].SpecularIndex
);
974 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
981 /**********************************************************************/
982 /***** Lighting computation *****/
983 /**********************************************************************/
988 * When two-sided lighting is enabled we compute the color (or index)
989 * for both the front and back side of the primitive. Then, when the
990 * orientation of the facet is later learned, we can determine which
991 * color (or index) to use for rendering.
993 * KW: We now know orientation in advance and only shade for
994 * the side or sides which are actually required.
998 * V = vertex position
999 * P = light source position
1004 * // light at infinity
1005 * IF local_viewer THEN
1006 * _VP_inf_norm = unit vector from V to P // Precompute
1008 * // eye at infinity
1009 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1014 * Normalize( v ) = normalized vector v
1015 * Magnitude( v ) = length of vector v
1021 * Whenever the spotlight exponent for a light changes we must call
1022 * this function to recompute the exponent lookup table.
1025 _mesa_invalidate_spot_exp_table( struct gl_light
*l
)
1027 l
->_SpotExpTable
[0][0] = -1;
1030 static void validate_spot_exp_table( struct gl_light
*l
)
1033 GLdouble exponent
= l
->SpotExponent
;
1037 l
->_SpotExpTable
[0][0] = 0.0;
1039 for (i
= EXP_TABLE_SIZE
- 1; i
> 0 ;i
--) {
1041 tmp
= pow(i
/ (GLdouble
) (EXP_TABLE_SIZE
- 1), exponent
);
1042 if (tmp
< FLT_MIN
* 100.0) {
1047 l
->_SpotExpTable
[i
][0] = (GLfloat
) tmp
;
1049 for (i
= 0; i
< EXP_TABLE_SIZE
- 1; i
++) {
1050 l
->_SpotExpTable
[i
][1] = (l
->_SpotExpTable
[i
+1][0] -
1051 l
->_SpotExpTable
[i
][0]);
1053 l
->_SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
1059 /* Calculate a new shine table. Doing this here saves a branch in
1060 * lighting, and the cost of doing it early may be partially offset
1061 * by keeping a MRU cache of shine tables for various shine values.
1064 _mesa_invalidate_shine_table( GLcontext
*ctx
, GLuint i
)
1066 if (ctx
->_ShineTable
[i
])
1067 ctx
->_ShineTable
[i
]->refcount
--;
1068 ctx
->_ShineTable
[i
] = 0;
1071 static void validate_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
1073 struct gl_shine_tab
*list
= ctx
->_ShineTabList
;
1074 struct gl_shine_tab
*s
;
1077 if ( s
->shininess
== shininess
)
1085 if (s
->refcount
== 0)
1090 if (shininess
== 0.0) {
1091 for (j
= 1 ; j
<= SHINE_TABLE_SIZE
; j
++)
1095 for (j
= 1 ; j
< SHINE_TABLE_SIZE
; j
++) {
1096 GLdouble t
, x
= j
/ (GLfloat
) (SHINE_TABLE_SIZE
- 1);
1097 if (x
< 0.005) /* underflow check */
1099 t
= pow(x
, shininess
);
1105 m
[SHINE_TABLE_SIZE
] = 1.0;
1108 s
->shininess
= shininess
;
1111 if (ctx
->_ShineTable
[i
])
1112 ctx
->_ShineTable
[i
]->refcount
--;
1114 ctx
->_ShineTable
[i
] = s
;
1115 move_to_tail( list
, s
);
1120 _mesa_validate_all_lighting_tables( GLcontext
*ctx
)
1125 shininess
= ctx
->Light
.Material
[0].Shininess
;
1126 if (!ctx
->_ShineTable
[0] || ctx
->_ShineTable
[0]->shininess
!= shininess
)
1127 validate_shine_table( ctx
, 0, shininess
);
1129 shininess
= ctx
->Light
.Material
[1].Shininess
;
1130 if (!ctx
->_ShineTable
[1] || ctx
->_ShineTable
[1]->shininess
!= shininess
)
1131 validate_shine_table( ctx
, 1, shininess
);
1133 for (i
= 0 ; i
< MAX_LIGHTS
; i
++)
1134 if (ctx
->Light
.Light
[i
]._SpotExpTable
[0][0] == -1)
1135 validate_spot_exp_table( &ctx
->Light
.Light
[i
] );
1142 * Examine current lighting parameters to determine if the optimized lighting
1143 * function can be used.
1144 * Also, precompute some lighting values such as the products of light
1145 * source and material ambient, diffuse and specular coefficients.
1148 _mesa_update_lighting( GLcontext
*ctx
)
1150 struct gl_light
*light
;
1151 ctx
->_NeedEyeCoords
&= ~NEED_EYE_LIGHT
;
1152 ctx
->_NeedNormals
&= ~NEED_NORMALS_LIGHT
;
1153 ctx
->Light
._Flags
= 0;
1155 if (!ctx
->Light
.Enabled
)
1158 ctx
->_NeedNormals
|= NEED_NORMALS_LIGHT
;
1160 foreach(light
, &ctx
->Light
.EnabledList
) {
1161 ctx
->Light
._Flags
|= light
->_Flags
;
1164 ctx
->Light
._NeedVertices
=
1165 ((ctx
->Light
._Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
1166 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
1167 ctx
->Light
.Model
.LocalViewer
);
1169 if ((ctx
->Light
._Flags
& LIGHT_POSITIONAL
) ||
1170 ctx
->Light
.Model
.LocalViewer
)
1171 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1174 /* XXX: This test is overkill & needs to be fixed both for software and
1175 * hardware t&l drivers. The above should be sufficient & should
1176 * be tested to verify this.
1178 if (ctx
->Light
._NeedVertices
)
1179 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1182 /* Precompute some shading values. Although we reference
1183 * Light.Material here, we can get away without flushing
1184 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
1185 * are flushed, they will update the derived state at that time.
1187 if (ctx
->Visual
.rgbMode
) {
1188 GLuint sides
= ctx
->Light
.Model
.TwoSide
? 2 : 1;
1190 for (side
=0; side
< sides
; side
++) {
1191 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1193 COPY_3V(ctx
->Light
._BaseColor
[side
], mat
->Emission
);
1194 ACC_SCALE_3V(ctx
->Light
._BaseColor
[side
],
1195 ctx
->Light
.Model
.Ambient
,
1199 foreach (light
, &ctx
->Light
.EnabledList
) {
1200 for (side
=0; side
< sides
; side
++) {
1201 const struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1202 SCALE_3V( light
->_MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1203 SCALE_3V( light
->_MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1204 SCALE_3V( light
->_MatSpecular
[side
], light
->Specular
,
1210 static const GLfloat ci
[3] = { .30F
, .59F
, .11F
};
1211 foreach(light
, &ctx
->Light
.EnabledList
) {
1212 light
->_dli
= DOT3(ci
, light
->Diffuse
);
1213 light
->_sli
= DOT3(ci
, light
->Specular
);
1221 * _TNL_NEW_NEED_EYE_COORDS
1223 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1224 * Also update on lighting space changes.
1227 _mesa_compute_light_positions( GLcontext
*ctx
)
1229 struct gl_light
*light
;
1230 static const GLfloat eye_z
[3] = { 0, 0, 1 };
1232 if (!ctx
->Light
.Enabled
)
1235 if (ctx
->_NeedEyeCoords
) {
1236 COPY_3V( ctx
->_EyeZDir
, eye_z
);
1239 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
1242 foreach (light
, &ctx
->Light
.EnabledList
) {
1244 if (ctx
->_NeedEyeCoords
) {
1245 COPY_4FV( light
->_Position
, light
->EyePosition
);
1248 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
1249 light
->EyePosition
);
1252 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1253 /* VP (VP) = Normalize( Position ) */
1254 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
1255 NORMALIZE_3FV( light
->_VP_inf_norm
);
1257 if (!ctx
->Light
.Model
.LocalViewer
) {
1258 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1259 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
1260 NORMALIZE_3FV( light
->_h_inf_norm
);
1262 light
->_VP_inf_spot_attenuation
= 1.0;
1265 if (light
->_Flags
& LIGHT_SPOT
) {
1266 if (ctx
->_NeedEyeCoords
) {
1267 COPY_3V( light
->_NormDirection
, light
->EyeDirection
);
1270 TRANSFORM_NORMAL( light
->_NormDirection
,
1271 light
->EyeDirection
,
1272 ctx
->ModelviewMatrixStack
.Top
->m
);
1275 NORMALIZE_3FV( light
->_NormDirection
);
1277 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1278 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1279 light
->_NormDirection
);
1281 if (PV_dot_dir
> light
->_CosCutoff
) {
1282 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1284 light
->_VP_inf_spot_attenuation
=
1285 (GLfloat
) (light
->_SpotExpTable
[k
][0] +
1286 (x
-k
)*light
->_SpotExpTable
[k
][1]);
1289 light
->_VP_inf_spot_attenuation
= 0;