3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "simple_list.h"
36 #include "math/m_xform.h"
37 #include "math/m_matrix.h"
40 /* XXX this is a bit of a hack needed for compilation within XFree86 */
47 _mesa_ShadeModel( GLenum mode
)
49 GET_CURRENT_CONTEXT(ctx
);
50 ASSERT_OUTSIDE_BEGIN_END(ctx
);
52 if (MESA_VERBOSE
& VERBOSE_API
)
53 _mesa_debug(ctx
, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode
));
55 if (mode
!= GL_FLAT
&& mode
!= GL_SMOOTH
) {
56 _mesa_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
60 if (ctx
->Light
.ShadeModel
== mode
)
63 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
64 ctx
->Light
.ShadeModel
= mode
;
65 ctx
->_TriangleCaps
^= DD_FLATSHADE
;
66 if (ctx
->Driver
.ShadeModel
)
67 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
73 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
75 _mesa_Lightfv( light
, pname
, ¶m
);
80 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
82 GET_CURRENT_CONTEXT(ctx
);
83 GLint i
= (GLint
) (light
- GL_LIGHT0
);
84 struct gl_light
*l
= &ctx
->Light
.Light
[i
];
86 if (i
< 0 || i
>= (GLint
) ctx
->Const
.MaxLights
) {
87 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(light=0x%x)", light
);
93 if (TEST_EQ_4V(l
->Ambient
, params
))
95 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
96 COPY_4V( l
->Ambient
, params
);
99 if (TEST_EQ_4V(l
->Diffuse
, params
))
101 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
102 COPY_4V( l
->Diffuse
, params
);
105 if (TEST_EQ_4V(l
->Specular
, params
))
107 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
108 COPY_4V( l
->Specular
, params
);
112 /* transform position by ModelView matrix */
113 TRANSFORM_POINT( tmp
, ctx
->ModelviewMatrixStack
.Top
->m
, params
);
114 if (TEST_EQ_4V(l
->EyePosition
, tmp
))
116 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
117 COPY_4V(l
->EyePosition
, tmp
);
118 if (l
->EyePosition
[3] != 0.0F
)
119 l
->_Flags
|= LIGHT_POSITIONAL
;
121 l
->_Flags
&= ~LIGHT_POSITIONAL
;
124 case GL_SPOT_DIRECTION
: {
126 /* transform direction by inverse modelview */
127 if (ctx
->ModelviewMatrixStack
.Top
->flags
& MAT_DIRTY_INVERSE
) {
128 _math_matrix_analyse( ctx
->ModelviewMatrixStack
.Top
);
130 TRANSFORM_NORMAL( tmp
, params
, ctx
->ModelviewMatrixStack
.Top
->inv
);
131 if (TEST_EQ_3V(l
->EyeDirection
, tmp
))
133 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
134 COPY_3V(l
->EyeDirection
, tmp
);
137 case GL_SPOT_EXPONENT
:
138 if (params
[0]<0.0 || params
[0]>ctx
->Const
.MaxSpotExponent
) {
139 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
142 if (l
->SpotExponent
== params
[0])
144 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
145 l
->SpotExponent
= params
[0];
146 _mesa_invalidate_spot_exp_table( l
);
149 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
150 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
153 if (l
->SpotCutoff
== params
[0])
155 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
156 l
->SpotCutoff
= params
[0];
157 l
->_CosCutoff
= (GLfloat
) _mesa_cos(params
[0]*DEG2RAD
);
158 if (l
->_CosCutoff
< 0)
160 if (l
->SpotCutoff
!= 180.0F
)
161 l
->_Flags
|= LIGHT_SPOT
;
163 l
->_Flags
&= ~LIGHT_SPOT
;
165 case GL_CONSTANT_ATTENUATION
:
167 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
170 if (l
->ConstantAttenuation
== params
[0])
172 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
173 l
->ConstantAttenuation
= params
[0];
175 case GL_LINEAR_ATTENUATION
:
177 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
180 if (l
->LinearAttenuation
== params
[0])
182 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
183 l
->LinearAttenuation
= params
[0];
185 case GL_QUADRATIC_ATTENUATION
:
187 _mesa_error( ctx
, GL_INVALID_VALUE
, "glLight" );
190 if (l
->QuadraticAttenuation
== params
[0])
192 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
193 l
->QuadraticAttenuation
= params
[0];
196 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLight(pname=0x%x)", pname
);
200 if (ctx
->Driver
.Lightfv
)
201 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
);
206 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
208 _mesa_Lightiv( light
, pname
, ¶m
);
213 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
221 fparam
[0] = INT_TO_FLOAT( params
[0] );
222 fparam
[1] = INT_TO_FLOAT( params
[1] );
223 fparam
[2] = INT_TO_FLOAT( params
[2] );
224 fparam
[3] = INT_TO_FLOAT( params
[3] );
227 fparam
[0] = (GLfloat
) params
[0];
228 fparam
[1] = (GLfloat
) params
[1];
229 fparam
[2] = (GLfloat
) params
[2];
230 fparam
[3] = (GLfloat
) params
[3];
232 case GL_SPOT_DIRECTION
:
233 fparam
[0] = (GLfloat
) params
[0];
234 fparam
[1] = (GLfloat
) params
[1];
235 fparam
[2] = (GLfloat
) params
[2];
237 case GL_SPOT_EXPONENT
:
239 case GL_CONSTANT_ATTENUATION
:
240 case GL_LINEAR_ATTENUATION
:
241 case GL_QUADRATIC_ATTENUATION
:
242 fparam
[0] = (GLfloat
) params
[0];
245 /* error will be caught later in gl_Lightfv */
249 _mesa_Lightfv( light
, pname
, fparam
);
255 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
257 GET_CURRENT_CONTEXT(ctx
);
258 GLint l
= (GLint
) (light
- GL_LIGHT0
);
259 ASSERT_OUTSIDE_BEGIN_END(ctx
);
261 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
262 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
268 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
271 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
274 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
277 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
279 case GL_SPOT_DIRECTION
:
280 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
282 case GL_SPOT_EXPONENT
:
283 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
286 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
288 case GL_CONSTANT_ATTENUATION
:
289 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
291 case GL_LINEAR_ATTENUATION
:
292 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
294 case GL_QUADRATIC_ATTENUATION
:
295 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
298 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
306 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
308 GET_CURRENT_CONTEXT(ctx
);
309 GLint l
= (GLint
) (light
- GL_LIGHT0
);
310 ASSERT_OUTSIDE_BEGIN_END(ctx
);
312 if (l
< 0 || l
>= (GLint
) ctx
->Const
.MaxLights
) {
313 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
319 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
320 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
321 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
322 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
325 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
326 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
327 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
328 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
331 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
332 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
333 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
334 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
337 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
338 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
339 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
340 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
342 case GL_SPOT_DIRECTION
:
343 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
344 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
345 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
347 case GL_SPOT_EXPONENT
:
348 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
351 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
353 case GL_CONSTANT_ATTENUATION
:
354 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
356 case GL_LINEAR_ATTENUATION
:
357 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
359 case GL_QUADRATIC_ATTENUATION
:
360 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
363 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
370 /**********************************************************************/
371 /*** Light Model ***/
372 /**********************************************************************/
376 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
380 GET_CURRENT_CONTEXT(ctx
);
381 ASSERT_OUTSIDE_BEGIN_END(ctx
);
384 case GL_LIGHT_MODEL_AMBIENT
:
385 if (TEST_EQ_4V( ctx
->Light
.Model
.Ambient
, params
))
387 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
388 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
390 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
391 newbool
= (params
[0]!=0.0);
392 if (ctx
->Light
.Model
.LocalViewer
== newbool
)
394 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
395 ctx
->Light
.Model
.LocalViewer
= newbool
;
397 case GL_LIGHT_MODEL_TWO_SIDE
:
398 newbool
= (params
[0]!=0.0);
399 if (ctx
->Light
.Model
.TwoSide
== newbool
)
401 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
402 ctx
->Light
.Model
.TwoSide
= newbool
;
404 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
)
405 ctx
->_TriangleCaps
|= DD_TRI_LIGHT_TWOSIDE
;
407 ctx
->_TriangleCaps
&= ~DD_TRI_LIGHT_TWOSIDE
;
409 case GL_LIGHT_MODEL_COLOR_CONTROL
:
410 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
411 newenum
= GL_SINGLE_COLOR
;
412 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
)
413 newenum
= GL_SEPARATE_SPECULAR_COLOR
;
415 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param=0x0%x)",
419 if (ctx
->Light
.Model
.ColorControl
== newenum
)
421 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
422 ctx
->Light
.Model
.ColorControl
= newenum
;
424 if ((ctx
->Light
.Enabled
&&
425 ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
)
426 || ctx
->Fog
.ColorSumEnabled
)
427 ctx
->_TriangleCaps
|= DD_SEPARATE_SPECULAR
;
429 ctx
->_TriangleCaps
&= ~DD_SEPARATE_SPECULAR
;
433 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLightModel(pname=0x%x)", pname
);
437 if (ctx
->Driver
.LightModelfv
)
438 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
443 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
448 case GL_LIGHT_MODEL_AMBIENT
:
449 fparam
[0] = INT_TO_FLOAT( params
[0] );
450 fparam
[1] = INT_TO_FLOAT( params
[1] );
451 fparam
[2] = INT_TO_FLOAT( params
[2] );
452 fparam
[3] = INT_TO_FLOAT( params
[3] );
454 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
455 case GL_LIGHT_MODEL_TWO_SIDE
:
456 case GL_LIGHT_MODEL_COLOR_CONTROL
:
457 fparam
[0] = (GLfloat
) params
[0];
460 /* Error will be caught later in gl_LightModelfv */
463 _mesa_LightModelfv( pname
, fparam
);
468 _mesa_LightModeli( GLenum pname
, GLint param
)
470 _mesa_LightModeliv( pname
, ¶m
);
475 _mesa_LightModelf( GLenum pname
, GLfloat param
)
477 _mesa_LightModelfv( pname
, ¶m
);
482 /********** MATERIAL **********/
486 * Given a face and pname value (ala glColorMaterial), compute a bitmask
487 * of the targeted material values.
490 _mesa_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
491 GLuint legal
, const char *where
)
495 /* Make a bitmask indicating what material attribute(s) we're updating */
498 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
501 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
504 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
507 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
510 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
512 case GL_AMBIENT_AND_DIFFUSE
:
513 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
514 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
516 case GL_COLOR_INDEXES
:
517 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
520 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
524 if (face
==GL_FRONT
) {
525 bitmask
&= FRONT_MATERIAL_BITS
;
527 else if (face
==GL_BACK
) {
528 bitmask
&= BACK_MATERIAL_BITS
;
530 else if (face
!= GL_FRONT_AND_BACK
) {
531 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
535 if (bitmask
& ~legal
) {
536 _mesa_error( ctx
, GL_INVALID_ENUM
, where
);
544 /* Perform a straight copy between pairs of materials.
546 void _mesa_copy_material_pairs( struct gl_material dst
[2],
547 const struct gl_material src
[2],
550 if (bitmask
& FRONT_EMISSION_BIT
) {
551 COPY_4FV( dst
[0].Emission
, src
[0].Emission
);
553 if (bitmask
& BACK_EMISSION_BIT
) {
554 COPY_4FV( dst
[1].Emission
, src
[1].Emission
);
556 if (bitmask
& FRONT_AMBIENT_BIT
) {
557 COPY_4FV( dst
[0].Ambient
, src
[0].Ambient
);
559 if (bitmask
& BACK_AMBIENT_BIT
) {
560 COPY_4FV( dst
[1].Ambient
, src
[1].Ambient
);
562 if (bitmask
& FRONT_DIFFUSE_BIT
) {
563 COPY_4FV( dst
[0].Diffuse
, src
[0].Diffuse
);
565 if (bitmask
& BACK_DIFFUSE_BIT
) {
566 COPY_4FV( dst
[1].Diffuse
, src
[1].Diffuse
);
568 if (bitmask
& FRONT_SPECULAR_BIT
) {
569 COPY_4FV( dst
[0].Specular
, src
[0].Specular
);
571 if (bitmask
& BACK_SPECULAR_BIT
) {
572 COPY_4FV( dst
[1].Specular
, src
[1].Specular
);
574 if (bitmask
& FRONT_SHININESS_BIT
) {
575 dst
[0].Shininess
= src
[0].Shininess
;
577 if (bitmask
& BACK_SHININESS_BIT
) {
578 dst
[1].Shininess
= src
[1].Shininess
;
580 if (bitmask
& FRONT_INDEXES_BIT
) {
581 dst
[0].AmbientIndex
= src
[0].AmbientIndex
;
582 dst
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
583 dst
[0].SpecularIndex
= src
[0].SpecularIndex
;
585 if (bitmask
& BACK_INDEXES_BIT
) {
586 dst
[1].AmbientIndex
= src
[1].AmbientIndex
;
587 dst
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
588 dst
[1].SpecularIndex
= src
[1].SpecularIndex
;
594 * Check if the global material has to be updated with info that was
595 * associated with a vertex via glMaterial.
596 * This function is used when any material values get changed between
597 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
598 * when GL_COLOR_MATERIAL is enabled.
600 * src[0] is front material, src[1] is back material
602 * Additionally keeps the precomputed lighting state uptodate.
604 void _mesa_update_material( GLcontext
*ctx
,
605 const struct gl_material src
[2],
608 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
610 if (ctx
->Light
.ColorMaterialEnabled
)
611 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
613 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
614 _mesa_debug(ctx
, "_mesa_update_material, mask 0x%x\n", bitmask
);
619 /* update material emission */
620 if (bitmask
& FRONT_EMISSION_BIT
) {
621 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
622 COPY_4FV( mat
->Emission
, src
[0].Emission
);
624 if (bitmask
& BACK_EMISSION_BIT
) {
625 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
626 COPY_4FV( mat
->Emission
, src
[1].Emission
);
629 /* update material ambience */
630 if (bitmask
& FRONT_AMBIENT_BIT
) {
631 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
632 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
633 foreach (light
, list
) {
634 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, src
[0].Ambient
);
637 if (bitmask
& BACK_AMBIENT_BIT
) {
638 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
639 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
640 foreach (light
, list
) {
641 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, src
[1].Ambient
);
645 /* update BaseColor = emission + scene's ambience * material's ambience */
646 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
647 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
648 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
649 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
,
650 ctx
->Light
.Model
.Ambient
);
652 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
653 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
654 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
655 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
,
656 ctx
->Light
.Model
.Ambient
);
659 /* update material diffuse values */
660 if (bitmask
& FRONT_DIFFUSE_BIT
) {
661 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
662 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
663 foreach (light
, list
) {
664 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
667 if (bitmask
& BACK_DIFFUSE_BIT
) {
668 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
669 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
670 foreach (light
, list
) {
671 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
675 /* update material specular values */
676 if (bitmask
& FRONT_SPECULAR_BIT
) {
677 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
678 COPY_4FV( mat
->Specular
, src
[0].Specular
);
679 foreach (light
, list
) {
680 SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
683 if (bitmask
& BACK_SPECULAR_BIT
) {
684 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
685 COPY_4FV( mat
->Specular
, src
[1].Specular
);
686 foreach (light
, list
) {
687 SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
691 if (bitmask
& FRONT_SHININESS_BIT
) {
692 ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
693 _mesa_invalidate_shine_table( ctx
, 0 );
695 if (bitmask
& BACK_SHININESS_BIT
) {
696 ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
697 _mesa_invalidate_shine_table( ctx
, 1 );
700 if (bitmask
& FRONT_INDEXES_BIT
) {
701 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
702 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
703 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
705 if (bitmask
& BACK_INDEXES_BIT
) {
706 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
707 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
708 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
712 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
713 _mesa_debug(ctx
, "update_mat emission : %f %f %f\n",
714 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
715 _mesa_debug(ctx
, "update_mat specular : %f %f %f\n",
716 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
717 _mesa_debug(ctx
, "update_mat diffuse : %f %f %f\n",
718 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
719 _mesa_debug(ctx
, "update_mat ambient : %f %f %f\n",
720 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
731 * Update the current materials from the given rgba color
732 * according to the bitmask in ColorMaterialBitmask, which is
733 * set by glColorMaterial().
735 void _mesa_update_color_material( GLcontext
*ctx
,
736 const GLfloat color
[4] )
738 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
739 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
741 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
742 _mesa_debug(ctx
, "_mesa_update_color_material, mask 0x%x\n", bitmask
);
744 /* update emissive colors */
745 if (bitmask
& FRONT_EMISSION_BIT
) {
746 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
747 COPY_4FV( mat
->Emission
, color
);
750 if (bitmask
& BACK_EMISSION_BIT
) {
751 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
752 COPY_4FV( mat
->Emission
, color
);
755 /* update light->_MatAmbient = light's ambient * material's ambient */
756 if (bitmask
& FRONT_AMBIENT_BIT
) {
757 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
758 foreach (light
, list
) {
759 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, color
);
761 COPY_4FV( mat
->Ambient
, color
);
764 if (bitmask
& BACK_AMBIENT_BIT
) {
765 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
766 foreach (light
, list
) {
767 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, color
);
769 COPY_4FV( mat
->Ambient
, color
);
772 /* update BaseColor = emission + scene's ambience * material's ambience */
773 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
774 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
775 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
776 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
779 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
780 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
781 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
782 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
785 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
786 if (bitmask
& FRONT_DIFFUSE_BIT
) {
787 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
788 COPY_4FV( mat
->Diffuse
, color
);
789 foreach (light
, list
) {
790 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
794 if (bitmask
& BACK_DIFFUSE_BIT
) {
795 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
796 COPY_4FV( mat
->Diffuse
, color
);
797 foreach (light
, list
) {
798 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
802 /* update light->_MatSpecular = light's specular * material's specular */
803 if (bitmask
& FRONT_SPECULAR_BIT
) {
804 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
805 COPY_4FV( mat
->Specular
, color
);
806 foreach (light
, list
) {
807 ACC_SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
811 if (bitmask
& BACK_SPECULAR_BIT
) {
812 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
813 COPY_4FV( mat
->Specular
, color
);
814 foreach (light
, list
) {
815 ACC_SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
820 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
821 _mesa_debug(ctx
, "update_color_mat emission : %f %f %f\n",
822 mat
->Emission
[0], mat
->Emission
[1], mat
->Emission
[2]);
823 _mesa_debug(ctx
, "update_color_mat specular : %f %f %f\n",
824 mat
->Specular
[0], mat
->Specular
[1], mat
->Specular
[2]);
825 _mesa_debug(ctx
, "update_color_mat diffuse : %f %f %f\n",
826 mat
->Diffuse
[0], mat
->Diffuse
[1], mat
->Diffuse
[2]);
827 _mesa_debug(ctx
, "update_color_mat ambient : %f %f %f\n",
828 mat
->Ambient
[0], mat
->Ambient
[1], mat
->Ambient
[2]);
836 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
838 GET_CURRENT_CONTEXT(ctx
);
840 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
841 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
842 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
843 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
844 ASSERT_OUTSIDE_BEGIN_END(ctx
);
846 if (MESA_VERBOSE
&VERBOSE_API
)
847 _mesa_debug(ctx
, "glColorMaterial %s %s\n",
848 _mesa_lookup_enum_by_nr(face
),
849 _mesa_lookup_enum_by_nr(mode
));
851 bitmask
= _mesa_material_bitmask(ctx
, face
, mode
, legal
, "glColorMaterial");
853 if (ctx
->Light
.ColorMaterialBitmask
== bitmask
&&
854 ctx
->Light
.ColorMaterialFace
== face
&&
855 ctx
->Light
.ColorMaterialMode
== mode
)
858 FLUSH_VERTICES(ctx
, _NEW_LIGHT
);
859 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
860 ctx
->Light
.ColorMaterialFace
= face
;
861 ctx
->Light
.ColorMaterialMode
= mode
;
863 if (ctx
->Light
.ColorMaterialEnabled
) {
864 FLUSH_CURRENT( ctx
, 0 );
865 _mesa_update_color_material(ctx
,ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
]);
868 if (ctx
->Driver
.ColorMaterial
)
869 (*ctx
->Driver
.ColorMaterial
)( ctx
, face
, mode
);
877 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
879 GET_CURRENT_CONTEXT(ctx
);
881 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
883 if (face
==GL_FRONT
) {
886 else if (face
==GL_BACK
) {
890 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
895 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
898 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
901 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
904 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
907 *params
= ctx
->Light
.Material
[f
].Shininess
;
909 case GL_COLOR_INDEXES
:
910 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
911 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
912 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
915 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
922 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
924 GET_CURRENT_CONTEXT(ctx
);
926 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* update materials */
928 if (face
==GL_FRONT
) {
931 else if (face
==GL_BACK
) {
935 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
940 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
941 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
942 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
943 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
946 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
947 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
948 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
949 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
952 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
953 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
954 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
955 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
958 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
959 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
960 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
961 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
964 *params
= IROUND( ctx
->Light
.Material
[f
].Shininess
);
966 case GL_COLOR_INDEXES
:
967 params
[0] = IROUND( ctx
->Light
.Material
[f
].AmbientIndex
);
968 params
[1] = IROUND( ctx
->Light
.Material
[f
].DiffuseIndex
);
969 params
[2] = IROUND( ctx
->Light
.Material
[f
].SpecularIndex
);
972 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
979 /**********************************************************************/
980 /***** Lighting computation *****/
981 /**********************************************************************/
986 * When two-sided lighting is enabled we compute the color (or index)
987 * for both the front and back side of the primitive. Then, when the
988 * orientation of the facet is later learned, we can determine which
989 * color (or index) to use for rendering.
991 * KW: We now know orientation in advance and only shade for
992 * the side or sides which are actually required.
996 * V = vertex position
997 * P = light source position
1002 * // light at infinity
1003 * IF local_viewer THEN
1004 * _VP_inf_norm = unit vector from V to P // Precompute
1006 * // eye at infinity
1007 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1012 * Normalize( v ) = normalized vector v
1013 * Magnitude( v ) = length of vector v
1019 * Whenever the spotlight exponent for a light changes we must call
1020 * this function to recompute the exponent lookup table.
1023 _mesa_invalidate_spot_exp_table( struct gl_light
*l
)
1025 l
->_SpotExpTable
[0][0] = -1;
1028 static void validate_spot_exp_table( struct gl_light
*l
)
1031 GLdouble exponent
= l
->SpotExponent
;
1035 l
->_SpotExpTable
[0][0] = 0.0;
1037 for (i
= EXP_TABLE_SIZE
- 1; i
> 0 ;i
--) {
1039 tmp
= _mesa_pow(i
/ (GLdouble
) (EXP_TABLE_SIZE
- 1), exponent
);
1040 if (tmp
< FLT_MIN
* 100.0) {
1045 l
->_SpotExpTable
[i
][0] = (GLfloat
) tmp
;
1047 for (i
= 0; i
< EXP_TABLE_SIZE
- 1; i
++) {
1048 l
->_SpotExpTable
[i
][1] = (l
->_SpotExpTable
[i
+1][0] -
1049 l
->_SpotExpTable
[i
][0]);
1051 l
->_SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
1057 /* Calculate a new shine table. Doing this here saves a branch in
1058 * lighting, and the cost of doing it early may be partially offset
1059 * by keeping a MRU cache of shine tables for various shine values.
1062 _mesa_invalidate_shine_table( GLcontext
*ctx
, GLuint i
)
1064 if (ctx
->_ShineTable
[i
])
1065 ctx
->_ShineTable
[i
]->refcount
--;
1066 ctx
->_ShineTable
[i
] = 0;
1069 static void validate_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
1071 struct gl_shine_tab
*list
= ctx
->_ShineTabList
;
1072 struct gl_shine_tab
*s
;
1075 if ( s
->shininess
== shininess
)
1083 if (s
->refcount
== 0)
1088 if (shininess
== 0.0) {
1089 for (j
= 1 ; j
<= SHINE_TABLE_SIZE
; j
++)
1093 for (j
= 1 ; j
< SHINE_TABLE_SIZE
; j
++) {
1094 GLdouble t
, x
= j
/ (GLfloat
) (SHINE_TABLE_SIZE
- 1);
1095 if (x
< 0.005) /* underflow check */
1097 t
= _mesa_pow(x
, shininess
);
1103 m
[SHINE_TABLE_SIZE
] = 1.0;
1106 s
->shininess
= shininess
;
1109 if (ctx
->_ShineTable
[i
])
1110 ctx
->_ShineTable
[i
]->refcount
--;
1112 ctx
->_ShineTable
[i
] = s
;
1113 move_to_tail( list
, s
);
1118 _mesa_validate_all_lighting_tables( GLcontext
*ctx
)
1123 shininess
= ctx
->Light
.Material
[0].Shininess
;
1124 if (!ctx
->_ShineTable
[0] || ctx
->_ShineTable
[0]->shininess
!= shininess
)
1125 validate_shine_table( ctx
, 0, shininess
);
1127 shininess
= ctx
->Light
.Material
[1].Shininess
;
1128 if (!ctx
->_ShineTable
[1] || ctx
->_ShineTable
[1]->shininess
!= shininess
)
1129 validate_shine_table( ctx
, 1, shininess
);
1131 for (i
= 0 ; i
< MAX_LIGHTS
; i
++)
1132 if (ctx
->Light
.Light
[i
]._SpotExpTable
[0][0] == -1)
1133 validate_spot_exp_table( &ctx
->Light
.Light
[i
] );
1140 * Examine current lighting parameters to determine if the optimized lighting
1141 * function can be used.
1142 * Also, precompute some lighting values such as the products of light
1143 * source and material ambient, diffuse and specular coefficients.
1146 _mesa_update_lighting( GLcontext
*ctx
)
1148 struct gl_light
*light
;
1149 ctx
->Light
._NeedEyeCoords
= 0;
1150 ctx
->Light
._Flags
= 0;
1152 if (!ctx
->Light
.Enabled
)
1155 foreach(light
, &ctx
->Light
.EnabledList
) {
1156 ctx
->Light
._Flags
|= light
->_Flags
;
1159 ctx
->Light
._NeedVertices
=
1160 ((ctx
->Light
._Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
1161 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
1162 ctx
->Light
.Model
.LocalViewer
);
1164 ctx
->Light
._NeedEyeCoords
= ((ctx
->Light
._Flags
& LIGHT_POSITIONAL
) ||
1165 ctx
->Light
.Model
.LocalViewer
);
1169 /* XXX: This test is overkill & needs to be fixed both for software and
1170 * hardware t&l drivers. The above should be sufficient & should
1171 * be tested to verify this.
1173 if (ctx
->Light
._NeedVertices
)
1174 ctx
->Light
._NeedEyeCoords
= GL_TRUE
;
1177 /* Precompute some shading values. Although we reference
1178 * Light.Material here, we can get away without flushing
1179 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
1180 * are flushed, they will update the derived state at that time.
1182 if (ctx
->Visual
.rgbMode
) {
1183 GLuint sides
= ctx
->Light
.Model
.TwoSide
? 2 : 1;
1185 for (side
=0; side
< sides
; side
++) {
1186 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1188 COPY_3V(ctx
->Light
._BaseColor
[side
], mat
->Emission
);
1189 ACC_SCALE_3V(ctx
->Light
._BaseColor
[side
],
1190 ctx
->Light
.Model
.Ambient
,
1194 foreach (light
, &ctx
->Light
.EnabledList
) {
1195 for (side
=0; side
< sides
; side
++) {
1196 const struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1197 SCALE_3V( light
->_MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1198 SCALE_3V( light
->_MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1199 SCALE_3V( light
->_MatSpecular
[side
], light
->Specular
,
1205 static const GLfloat ci
[3] = { .30F
, .59F
, .11F
};
1206 foreach(light
, &ctx
->Light
.EnabledList
) {
1207 light
->_dli
= DOT3(ci
, light
->Diffuse
);
1208 light
->_sli
= DOT3(ci
, light
->Specular
);
1216 * _TNL_NEW_NEED_EYE_COORDS
1218 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1219 * Also update on lighting space changes.
1222 _mesa_compute_light_positions( GLcontext
*ctx
)
1224 struct gl_light
*light
;
1225 static const GLfloat eye_z
[3] = { 0, 0, 1 };
1227 if (!ctx
->Light
.Enabled
)
1230 if (ctx
->_NeedEyeCoords
) {
1231 COPY_3V( ctx
->_EyeZDir
, eye_z
);
1234 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelviewMatrixStack
.Top
->m
);
1237 foreach (light
, &ctx
->Light
.EnabledList
) {
1239 if (ctx
->_NeedEyeCoords
) {
1240 COPY_4FV( light
->_Position
, light
->EyePosition
);
1243 TRANSFORM_POINT( light
->_Position
, ctx
->ModelviewMatrixStack
.Top
->inv
,
1244 light
->EyePosition
);
1247 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1248 /* VP (VP) = Normalize( Position ) */
1249 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
1250 NORMALIZE_3FV( light
->_VP_inf_norm
);
1252 if (!ctx
->Light
.Model
.LocalViewer
) {
1253 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1254 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
1255 NORMALIZE_3FV( light
->_h_inf_norm
);
1257 light
->_VP_inf_spot_attenuation
= 1.0;
1260 if (light
->_Flags
& LIGHT_SPOT
) {
1261 if (ctx
->_NeedEyeCoords
) {
1262 COPY_3V( light
->_NormDirection
, light
->EyeDirection
);
1265 TRANSFORM_NORMAL( light
->_NormDirection
,
1266 light
->EyeDirection
,
1267 ctx
->ModelviewMatrixStack
.Top
->m
);
1270 NORMALIZE_3FV( light
->_NormDirection
);
1272 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1273 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1274 light
->_NormDirection
);
1276 if (PV_dot_dir
> light
->_CosCutoff
) {
1277 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1279 light
->_VP_inf_spot_attenuation
=
1280 (GLfloat
) (light
->_SpotExpTable
[k
][0] +
1281 (x
-k
)*light
->_SpotExpTable
[k
][1]);
1284 light
->_VP_inf_spot_attenuation
= 0;
1296 update_modelview_scale( GLcontext
*ctx
)
1298 ctx
->_ModelViewInvScale
= 1.0F
;
1299 if (ctx
->ModelviewMatrixStack
.Top
->flags
& (MAT_FLAG_UNIFORM_SCALE
|
1300 MAT_FLAG_GENERAL_SCALE
|
1301 MAT_FLAG_GENERAL_3D
|
1302 MAT_FLAG_GENERAL
) ) {
1303 const GLfloat
*m
= ctx
->ModelviewMatrixStack
.Top
->inv
;
1304 GLfloat f
= m
[2] * m
[2] + m
[6] * m
[6] + m
[10] * m
[10];
1305 if (f
< 1e-12) f
= 1.0;
1306 if (ctx
->_NeedEyeCoords
)
1307 ctx
->_ModelViewInvScale
= (GLfloat
) INV_SQRTF(f
);
1309 ctx
->_ModelViewInvScale
= (GLfloat
) SQRTF(f
);
1314 /* Bring uptodate any state that relies on _NeedEyeCoords.
1316 void _mesa_update_tnl_spaces( GLcontext
*ctx
, GLuint new_state
)
1318 const GLuint oldneedeyecoords
= ctx
->_NeedEyeCoords
;
1320 ctx
->_NeedEyeCoords
= 0;
1322 if (ctx
->_ForceEyeCoords
||
1323 (ctx
->Texture
._GenFlags
& TEXGEN_NEED_EYE_COORD
) ||
1324 ctx
->Point
._Attenuated
||
1325 ctx
->Light
._NeedEyeCoords
)
1326 ctx
->_NeedEyeCoords
= 1;
1328 if (ctx
->Light
.Enabled
&&
1329 !TEST_MAT_FLAGS( ctx
->ModelviewMatrixStack
.Top
,
1330 MAT_FLAGS_LENGTH_PRESERVING
))
1331 ctx
->_NeedEyeCoords
= 1;
1334 /* Check if the truth-value interpretations of the bitfields have
1337 if (oldneedeyecoords
!= ctx
->_NeedEyeCoords
) {
1338 /* Recalculate all state that depends on _NeedEyeCoords.
1340 update_modelview_scale(ctx
);
1341 _mesa_compute_light_positions( ctx
);
1343 if (ctx
->Driver
.LightingSpaceChange
)
1344 ctx
->Driver
.LightingSpaceChange( ctx
);
1347 GLuint new_state
= ctx
->NewState
;
1349 /* Recalculate that same state only if it has been invalidated
1350 * by other statechanges.
1352 if (new_state
& _NEW_MODELVIEW
)
1353 update_modelview_scale(ctx
);
1355 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
))
1356 _mesa_compute_light_positions( ctx
);
1361 /* Drivers may need this if the hardware tnl unit doesn't support the
1362 * light-in-modelspace optimization. It's also useful for debugging.
1365 _mesa_allow_light_in_model( GLcontext
*ctx
, GLboolean flag
)
1367 ctx
->_ForceEyeCoords
= flag
;
1368 ctx
->NewState
|= _NEW_POINT
; /* one of the bits from
1369 * _MESA_NEW_NEED_EYE_COORDS.
1375 /**********************************************************************/
1376 /***** Initialization *****/
1377 /**********************************************************************/
1380 * Initialize the n-th light data structure.
1382 * \param l pointer to the gl_light structure to be initialized.
1383 * \param n number of the light.
1384 * \note The defaults for light 0 are different than the other lights.
1387 init_light( struct gl_light
*l
, GLuint n
)
1389 make_empty_list( l
);
1391 ASSIGN_4V( l
->Ambient
, 0.0, 0.0, 0.0, 1.0 );
1393 ASSIGN_4V( l
->Diffuse
, 1.0, 1.0, 1.0, 1.0 );
1394 ASSIGN_4V( l
->Specular
, 1.0, 1.0, 1.0, 1.0 );
1397 ASSIGN_4V( l
->Diffuse
, 0.0, 0.0, 0.0, 1.0 );
1398 ASSIGN_4V( l
->Specular
, 0.0, 0.0, 0.0, 1.0 );
1400 ASSIGN_4V( l
->EyePosition
, 0.0, 0.0, 1.0, 0.0 );
1401 ASSIGN_3V( l
->EyeDirection
, 0.0, 0.0, -1.0 );
1402 l
->SpotExponent
= 0.0;
1403 _mesa_invalidate_spot_exp_table( l
);
1404 l
->SpotCutoff
= 180.0;
1405 l
->_CosCutoff
= 0.0; /* KW: -ve values not admitted */
1406 l
->ConstantAttenuation
= 1.0;
1407 l
->LinearAttenuation
= 0.0;
1408 l
->QuadraticAttenuation
= 0.0;
1409 l
->Enabled
= GL_FALSE
;
1413 * Initialize the light model data structure.
1415 * \param lm pointer to the gl_lightmodel structure to be initialized.
1418 init_lightmodel( struct gl_lightmodel
*lm
)
1420 ASSIGN_4V( lm
->Ambient
, 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1421 lm
->LocalViewer
= GL_FALSE
;
1422 lm
->TwoSide
= GL_FALSE
;
1423 lm
->ColorControl
= GL_SINGLE_COLOR
;
1427 * Initialize the material data structure.
1429 * \param m pointer to the gl_material structure to be initialized.
1432 init_material( struct gl_material
*m
)
1434 ASSIGN_4V( m
->Ambient
, 0.2F
, 0.2F
, 0.2F
, 1.0F
);
1435 ASSIGN_4V( m
->Diffuse
, 0.8F
, 0.8F
, 0.8F
, 1.0F
);
1436 ASSIGN_4V( m
->Specular
, 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1437 ASSIGN_4V( m
->Emission
, 0.0F
, 0.0F
, 0.0F
, 1.0F
);
1439 m
->AmbientIndex
= 0;
1440 m
->DiffuseIndex
= 1;
1441 m
->SpecularIndex
= 1;
1445 void _mesa_init_lighting( GLcontext
*ctx
)
1449 /* Lighting group */
1450 for (i
=0;i
<MAX_LIGHTS
;i
++) {
1451 init_light( &ctx
->Light
.Light
[i
], i
);
1453 make_empty_list( &ctx
->Light
.EnabledList
);
1455 init_lightmodel( &ctx
->Light
.Model
);
1456 init_material( &ctx
->Light
.Material
[0] );
1457 init_material( &ctx
->Light
.Material
[1] );
1458 ctx
->Light
.ShadeModel
= GL_SMOOTH
;
1459 ctx
->Light
.Enabled
= GL_FALSE
;
1460 ctx
->Light
.ColorMaterialFace
= GL_FRONT_AND_BACK
;
1461 ctx
->Light
.ColorMaterialMode
= GL_AMBIENT_AND_DIFFUSE
;
1462 ctx
->Light
.ColorMaterialBitmask
= _mesa_material_bitmask( ctx
,
1464 GL_AMBIENT_AND_DIFFUSE
, ~0, 0 );
1466 ctx
->Light
.ColorMaterialEnabled
= GL_FALSE
;
1468 /* Lighting miscellaneous */
1469 ctx
->_ShineTabList
= MALLOC_STRUCT( gl_shine_tab
);
1470 make_empty_list( ctx
->_ShineTabList
);
1471 for (i
= 0 ; i
< 10 ; i
++) {
1472 struct gl_shine_tab
*s
= MALLOC_STRUCT( gl_shine_tab
);
1475 insert_at_tail( ctx
->_ShineTabList
, s
);
1481 ctx
->Light
._NeedEyeCoords
= 0;
1482 ctx
->_NeedEyeCoords
= 0;
1483 ctx
->_ModelViewInvScale
= 1.0;
1487 void _mesa_free_lighting_data( GLcontext
*ctx
)
1489 struct gl_shine_tab
*s
, *tmps
;
1491 /* Free lighting shininess exponentiation table */
1492 foreach_s( s
, tmps
, ctx
->_ShineTabList
) {
1495 FREE( ctx
->_ShineTabList
);