1 /* $Id: light.c,v 1.28 2000/11/24 10:25:05 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
39 #include "simple_list.h"
42 #include "math/m_xform.h"
43 #include "math/m_matrix.h"
47 /* XXX this is a bit of a hack needed for compilation within XFree86 */
54 _mesa_ShadeModel( GLenum mode
)
56 GET_CURRENT_CONTEXT(ctx
);
57 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glShadeModel");
59 if (MESA_VERBOSE
& VERBOSE_API
)
60 fprintf(stderr
, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode
));
62 if (mode
== GL_FLAT
|| mode
== GL_SMOOTH
) {
63 if (ctx
->Light
.ShadeModel
!= mode
) {
64 ctx
->Light
.ShadeModel
= mode
;
65 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
66 SET_BITS(ctx
->_TriangleCaps
, DD_FLATSHADE
);
68 CLEAR_BITS(ctx
->_TriangleCaps
, DD_FLATSHADE
);
70 ctx
->NewState
|= _NEW_LIGHT
;
72 if (ctx
->Driver
.ShadeModel
)
73 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
77 gl_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
84 _mesa_Lightf( GLenum light
, GLenum pname
, GLfloat param
)
86 _mesa_Lightfv( light
, pname
, ¶m
);
91 _mesa_Lightfv( GLenum light
, GLenum pname
, const GLfloat
*params
)
93 GET_CURRENT_CONTEXT(ctx
);
94 GLint i
= (GLint
) (light
- GL_LIGHT0
);
95 struct gl_light
*l
= &ctx
->Light
.Light
[i
];
97 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLight");
99 if (i
< 0 || i
>= MAX_LIGHTS
) {
100 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
106 COPY_4V( l
->Ambient
, params
);
109 COPY_4V( l
->Diffuse
, params
);
112 COPY_4V( l
->Specular
, params
);
115 /* transform position by ModelView matrix */
116 TRANSFORM_POINT( l
->EyePosition
, ctx
->ModelView
.m
, params
);
117 if (l
->EyePosition
[3] != 0.0F
)
118 l
->_Flags
|= LIGHT_POSITIONAL
;
120 l
->_Flags
&= ~LIGHT_POSITIONAL
;
122 case GL_SPOT_DIRECTION
:
123 /* transform direction by inverse modelview */
124 if (ctx
->ModelView
.flags
& MAT_DIRTY_INVERSE
) {
125 _math_matrix_analyse( &ctx
->ModelView
);
127 TRANSFORM_NORMAL( l
->EyeDirection
, params
, ctx
->ModelView
.inv
);
129 case GL_SPOT_EXPONENT
:
130 if (params
[0]<0.0 || params
[0]>128.0) {
131 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
134 if (l
->SpotExponent
!= params
[0]) {
135 l
->SpotExponent
= params
[0];
136 gl_compute_spot_exp_table( l
);
140 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
141 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
144 l
->SpotCutoff
= params
[0];
145 l
->_CosCutoff
= cos(params
[0]*DEG2RAD
);
146 if (l
->_CosCutoff
< 0)
148 if (l
->SpotCutoff
!= 180.0F
)
149 l
->_Flags
|= LIGHT_SPOT
;
151 l
->_Flags
&= ~LIGHT_SPOT
;
153 case GL_CONSTANT_ATTENUATION
:
155 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
158 l
->ConstantAttenuation
= params
[0];
160 case GL_LINEAR_ATTENUATION
:
162 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
165 l
->LinearAttenuation
= params
[0];
167 case GL_QUADRATIC_ATTENUATION
:
169 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
172 l
->QuadraticAttenuation
= params
[0];
175 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
179 if (ctx
->Driver
.Lightfv
)
180 ctx
->Driver
.Lightfv( ctx
, light
, pname
, params
);
182 ctx
->NewState
|= _NEW_LIGHT
;
187 _mesa_Lighti( GLenum light
, GLenum pname
, GLint param
)
189 _mesa_Lightiv( light
, pname
, ¶m
);
194 _mesa_Lightiv( GLenum light
, GLenum pname
, const GLint
*params
)
202 fparam
[0] = INT_TO_FLOAT( params
[0] );
203 fparam
[1] = INT_TO_FLOAT( params
[1] );
204 fparam
[2] = INT_TO_FLOAT( params
[2] );
205 fparam
[3] = INT_TO_FLOAT( params
[3] );
208 fparam
[0] = (GLfloat
) params
[0];
209 fparam
[1] = (GLfloat
) params
[1];
210 fparam
[2] = (GLfloat
) params
[2];
211 fparam
[3] = (GLfloat
) params
[3];
213 case GL_SPOT_DIRECTION
:
214 fparam
[0] = (GLfloat
) params
[0];
215 fparam
[1] = (GLfloat
) params
[1];
216 fparam
[2] = (GLfloat
) params
[2];
218 case GL_SPOT_EXPONENT
:
220 case GL_CONSTANT_ATTENUATION
:
221 case GL_LINEAR_ATTENUATION
:
222 case GL_QUADRATIC_ATTENUATION
:
223 fparam
[0] = (GLfloat
) params
[0];
226 /* error will be caught later in gl_Lightfv */
230 _mesa_Lightfv( light
, pname
, fparam
);
236 _mesa_GetLightfv( GLenum light
, GLenum pname
, GLfloat
*params
)
238 GET_CURRENT_CONTEXT(ctx
);
239 GLint l
= (GLint
) (light
- GL_LIGHT0
);
241 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
243 if (l
<0 || l
>=MAX_LIGHTS
) {
244 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
250 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
253 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
256 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
259 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
261 case GL_SPOT_DIRECTION
:
262 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
264 case GL_SPOT_EXPONENT
:
265 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
268 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
270 case GL_CONSTANT_ATTENUATION
:
271 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
273 case GL_LINEAR_ATTENUATION
:
274 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
276 case GL_QUADRATIC_ATTENUATION
:
277 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
280 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
288 _mesa_GetLightiv( GLenum light
, GLenum pname
, GLint
*params
)
290 GET_CURRENT_CONTEXT(ctx
);
291 GLint l
= (GLint
) (light
- GL_LIGHT0
);
293 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
295 if (l
<0 || l
>=MAX_LIGHTS
) {
296 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
302 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
303 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
304 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
305 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
308 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
309 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
310 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
311 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
314 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
315 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
316 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
317 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
320 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
321 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
322 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
323 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
325 case GL_SPOT_DIRECTION
:
326 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
327 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
328 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
330 case GL_SPOT_EXPONENT
:
331 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
334 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
336 case GL_CONSTANT_ATTENUATION
:
337 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
339 case GL_LINEAR_ATTENUATION
:
340 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
342 case GL_QUADRATIC_ATTENUATION
:
343 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
346 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
353 /**********************************************************************/
354 /*** Light Model ***/
355 /**********************************************************************/
359 _mesa_LightModelfv( GLenum pname
, const GLfloat
*params
)
361 GET_CURRENT_CONTEXT(ctx
);
362 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLightModelfv");
365 case GL_LIGHT_MODEL_AMBIENT
:
366 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
368 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
370 ctx
->Light
.Model
.LocalViewer
= GL_FALSE
;
372 ctx
->Light
.Model
.LocalViewer
= GL_TRUE
;
374 case GL_LIGHT_MODEL_TWO_SIDE
:
376 ctx
->Light
.Model
.TwoSide
= GL_FALSE
;
378 ctx
->Light
.Model
.TwoSide
= GL_TRUE
;
380 case GL_LIGHT_MODEL_COLOR_CONTROL
:
381 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
) {
382 ctx
->Light
.Model
.ColorControl
= GL_SINGLE_COLOR
;
383 if (!ctx
->Fog
.ColorSumEnabled
)
384 CLEAR_BITS(ctx
->_TriangleCaps
, DD_SEPERATE_SPECULAR
);
386 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
) {
387 ctx
->Light
.Model
.ColorControl
= GL_SEPARATE_SPECULAR_COLOR
;
388 SET_BITS(ctx
->_TriangleCaps
, DD_SEPERATE_SPECULAR
);
391 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param)" );
395 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel" );
399 if (ctx
->Driver
.LightModelfv
)
400 ctx
->Driver
.LightModelfv( ctx
, pname
, params
);
402 ctx
->NewState
|= _NEW_LIGHT
;
407 _mesa_LightModeliv( GLenum pname
, const GLint
*params
)
410 GET_CURRENT_CONTEXT(ctx
);
411 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLightModeliv");
414 case GL_LIGHT_MODEL_AMBIENT
:
415 fparam
[0] = INT_TO_FLOAT( params
[0] );
416 fparam
[1] = INT_TO_FLOAT( params
[1] );
417 fparam
[2] = INT_TO_FLOAT( params
[2] );
418 fparam
[3] = INT_TO_FLOAT( params
[3] );
420 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
421 case GL_LIGHT_MODEL_TWO_SIDE
:
422 case GL_LIGHT_MODEL_COLOR_CONTROL
:
423 fparam
[0] = (GLfloat
) params
[0];
426 /* Error will be caught later in gl_LightModelfv */
429 _mesa_LightModelfv( pname
, fparam
);
434 _mesa_LightModeli( GLenum pname
, GLint param
)
436 _mesa_LightModeliv( pname
, ¶m
);
441 _mesa_LightModelf( GLenum pname
, GLfloat param
)
443 _mesa_LightModelfv( pname
, ¶m
);
448 /********** MATERIAL **********/
452 * Given a face and pname value (ala glColorMaterial), compute a bitmask
453 * of the targeted material values.
455 GLuint
gl_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
461 /* Make a bitmask indicating what material attribute(s) we're updating */
464 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
467 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
470 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
473 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
476 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
478 case GL_AMBIENT_AND_DIFFUSE
:
479 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
480 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
482 case GL_COLOR_INDEXES
:
483 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
486 gl_error( ctx
, GL_INVALID_ENUM
, where
);
490 if (face
==GL_FRONT
) {
491 bitmask
&= FRONT_MATERIAL_BITS
;
493 else if (face
==GL_BACK
) {
494 bitmask
&= BACK_MATERIAL_BITS
;
496 else if (face
!= GL_FRONT_AND_BACK
) {
497 gl_error( ctx
, GL_INVALID_ENUM
, where
);
501 if (bitmask
& ~legal
) {
502 gl_error( ctx
, GL_INVALID_ENUM
, where
);
512 * Check if the global material has to be updated with info that was
513 * associated with a vertex via glMaterial.
514 * This function is used when any material values get changed between
515 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
516 * when GL_COLOR_MATERIAL is enabled.
518 * src[0] is front material, src[1] is back material
520 * KW: Added code here to keep the precomputed variables uptodate.
521 * This means we can use the faster shade functions when using
522 * GL_COLOR_MATERIAL, and we can also now use the precomputed
523 * values in the slower shading functions, which further offsets
524 * the cost of doing this here.
526 void gl_update_material( GLcontext
*ctx
,
527 const struct gl_material src
[2],
530 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
532 if (ctx
->Light
.ColorMaterialEnabled
)
533 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
535 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
536 fprintf(stderr
, "gl_update_material, mask 0x%x\n", bitmask
);
541 /* update material emission */
542 if (bitmask
& FRONT_EMISSION_BIT
) {
543 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
544 COPY_4FV( mat
->Emission
, src
[0].Emission
);
546 if (bitmask
& BACK_EMISSION_BIT
) {
547 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
548 COPY_4FV( mat
->Emission
, src
[1].Emission
);
551 /* update material ambience */
552 if (bitmask
& FRONT_AMBIENT_BIT
) {
553 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
554 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
555 foreach (light
, list
) {
556 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, src
[0].Ambient
);
559 if (bitmask
& BACK_AMBIENT_BIT
) {
560 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
561 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
562 foreach (light
, list
) {
563 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, src
[1].Ambient
);
567 /* update BaseColor = emission + scene's ambience * material's ambience */
568 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
569 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
570 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
571 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
,
572 ctx
->Light
.Model
.Ambient
);
574 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
575 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
576 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
577 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
,
578 ctx
->Light
.Model
.Ambient
);
581 /* update material diffuse values */
582 if (bitmask
& FRONT_DIFFUSE_BIT
) {
583 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
584 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
585 foreach (light
, list
) {
586 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
588 FLOAT_COLOR_TO_CHAN(ctx
->Light
._BaseAlpha
[0], mat
->Diffuse
[3]);
590 if (bitmask
& BACK_DIFFUSE_BIT
) {
591 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
592 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
593 foreach (light
, list
) {
594 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
596 FLOAT_COLOR_TO_CHAN(ctx
->Light
._BaseAlpha
[1], mat
->Diffuse
[3]);
599 /* update material specular values */
600 if (bitmask
& FRONT_SPECULAR_BIT
) {
601 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
602 COPY_4FV( mat
->Specular
, src
[0].Specular
);
603 foreach (light
, list
) {
604 ACC_SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
607 if (bitmask
& BACK_SPECULAR_BIT
) {
608 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
609 COPY_4FV( mat
->Specular
, src
[1].Specular
);
610 foreach (light
, list
) {
611 ACC_SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
615 if (bitmask
& FRONT_SHININESS_BIT
) {
616 GLfloat shininess
= ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
617 gl_compute_shine_table( ctx
, 0, shininess
);
618 gl_compute_shine_table( ctx
, 2, shininess
* .5 );
620 if (bitmask
& BACK_SHININESS_BIT
) {
621 GLfloat shininess
= ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
622 gl_compute_shine_table( ctx
, 1, shininess
);
623 gl_compute_shine_table( ctx
, 3, shininess
* .5 );
626 if (bitmask
& FRONT_INDEXES_BIT
) {
627 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
628 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
629 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
631 if (bitmask
& BACK_INDEXES_BIT
) {
632 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
633 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
634 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
639 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
640 fprintf(stderr
, "update_mat emission : %f %f %f\n",
644 fprintf(stderr
, "update_mat specular : %f %f %f\n",
648 fprintf(stderr
, "update_mat diffuse : %f %f %f\n",
652 fprintf(stderr
, "update_mat ambient : %f %f %f\n",
663 * Update the current materials from the given rgba color
664 * according to the bitmask in ColorMaterialBitmask, which is
665 * set by glColorMaterial().
667 void gl_update_color_material( GLcontext
*ctx
,
668 const GLchan rgba
[4] )
670 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
671 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
674 color
[0] = CHAN_TO_FLOAT(rgba
[0]);
675 color
[1] = CHAN_TO_FLOAT(rgba
[1]);
676 color
[2] = CHAN_TO_FLOAT(rgba
[2]);
677 color
[3] = CHAN_TO_FLOAT(rgba
[3]);
679 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
680 fprintf(stderr
, "gl_update_color_material, mask 0x%x\n", bitmask
);
682 /* update emissive colors */
683 if (bitmask
& FRONT_EMISSION_BIT
) {
684 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
685 COPY_4FV( mat
->Emission
, color
);
688 if (bitmask
& BACK_EMISSION_BIT
) {
689 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
690 COPY_4FV( mat
->Emission
, color
);
693 /* update light->_MatAmbient = light's ambient * material's ambient */
694 if (bitmask
& FRONT_AMBIENT_BIT
) {
695 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
696 foreach (light
, list
) {
697 SCALE_3V( light
->_MatAmbient
[0], light
->Ambient
, color
);
699 COPY_4FV( mat
->Ambient
, color
);
702 if (bitmask
& BACK_AMBIENT_BIT
) {
703 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
704 foreach (light
, list
) {
705 SCALE_3V( light
->_MatAmbient
[1], light
->Ambient
, color
);
707 COPY_4FV( mat
->Ambient
, color
);
710 /* update BaseColor = emission + scene's ambience * material's ambience */
711 if (bitmask
& (FRONT_EMISSION_BIT
| FRONT_AMBIENT_BIT
)) {
712 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
713 COPY_3V( ctx
->Light
._BaseColor
[0], mat
->Emission
);
714 ACC_SCALE_3V( ctx
->Light
._BaseColor
[0], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
717 if (bitmask
& (BACK_EMISSION_BIT
| BACK_AMBIENT_BIT
)) {
718 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
719 COPY_3V( ctx
->Light
._BaseColor
[1], mat
->Emission
);
720 ACC_SCALE_3V( ctx
->Light
._BaseColor
[1], mat
->Ambient
, ctx
->Light
.Model
.Ambient
);
723 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
724 if (bitmask
& FRONT_DIFFUSE_BIT
) {
725 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
726 COPY_4FV( mat
->Diffuse
, color
);
727 foreach (light
, list
) {
728 SCALE_3V( light
->_MatDiffuse
[0], light
->Diffuse
, mat
->Diffuse
);
730 FLOAT_COLOR_TO_CHAN(ctx
->Light
._BaseAlpha
[0], mat
->Diffuse
[3]);
733 if (bitmask
& BACK_DIFFUSE_BIT
) {
734 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
735 COPY_4FV( mat
->Diffuse
, color
);
736 foreach (light
, list
) {
737 SCALE_3V( light
->_MatDiffuse
[1], light
->Diffuse
, mat
->Diffuse
);
739 FLOAT_COLOR_TO_CHAN(ctx
->Light
._BaseAlpha
[1], mat
->Diffuse
[3]);
742 /* update light->_MatSpecular = light's specular * material's specular */
743 if (bitmask
& FRONT_SPECULAR_BIT
) {
744 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
745 COPY_4FV( mat
->Specular
, color
);
746 foreach (light
, list
) {
747 ACC_SCALE_3V( light
->_MatSpecular
[0], light
->Specular
, mat
->Specular
);
751 if (bitmask
& BACK_SPECULAR_BIT
) {
752 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
753 COPY_4FV( mat
->Specular
, color
);
754 foreach (light
, list
) {
755 ACC_SCALE_3V( light
->_MatSpecular
[1], light
->Specular
, mat
->Specular
);
761 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
762 fprintf(stderr
, "update_color_mat emission : %f %f %f\n",
766 fprintf(stderr
, "update_color_mat specular : %f %f %f\n",
770 fprintf(stderr
, "update_color_mat diffuse : %f %f %f\n",
774 fprintf(stderr
, "update_color_mat ambient : %f %f %f\n",
785 _mesa_ColorMaterial( GLenum face
, GLenum mode
)
787 GET_CURRENT_CONTEXT(ctx
);
789 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
790 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
791 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
792 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
794 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glColorMaterial");
796 if (MESA_VERBOSE
&VERBOSE_API
)
797 fprintf(stderr
, "glColorMaterial %s %s\n",
798 gl_lookup_enum_by_nr(face
),
799 gl_lookup_enum_by_nr(mode
));
801 bitmask
= gl_material_bitmask( ctx
, face
, mode
, legal
, "glColorMaterial" );
804 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
805 ctx
->Light
.ColorMaterialFace
= face
;
806 ctx
->Light
.ColorMaterialMode
= mode
;
809 if (ctx
->Light
.ColorMaterialEnabled
) {
810 FLUSH_TNL( ctx
, FLUSH_UPDATE_CURRENT
);
811 gl_update_color_material( ctx
, ctx
->Current
.Color
);
814 ctx
->NewState
|= _NEW_LIGHT
;
822 _mesa_GetMaterialfv( GLenum face
, GLenum pname
, GLfloat
*params
)
824 GET_CURRENT_CONTEXT(ctx
);
827 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialfv");
829 if (face
==GL_FRONT
) {
832 else if (face
==GL_BACK
) {
836 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
841 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
844 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
847 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
850 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
853 *params
= ctx
->Light
.Material
[f
].Shininess
;
855 case GL_COLOR_INDEXES
:
856 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
857 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
858 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
861 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
868 _mesa_GetMaterialiv( GLenum face
, GLenum pname
, GLint
*params
)
870 GET_CURRENT_CONTEXT(ctx
);
873 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialiv");
875 if (face
==GL_FRONT
) {
878 else if (face
==GL_BACK
) {
882 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
887 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
888 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
889 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
890 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
893 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
894 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
895 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
896 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
899 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
900 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
901 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
902 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
905 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
906 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
907 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
908 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
911 *params
= ROUNDF( ctx
->Light
.Material
[f
].Shininess
);
913 case GL_COLOR_INDEXES
:
914 params
[0] = ROUNDF( ctx
->Light
.Material
[f
].AmbientIndex
);
915 params
[1] = ROUNDF( ctx
->Light
.Material
[f
].DiffuseIndex
);
916 params
[2] = ROUNDF( ctx
->Light
.Material
[f
].SpecularIndex
);
919 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
926 /**********************************************************************/
927 /***** Lighting computation *****/
928 /**********************************************************************/
933 * When two-sided lighting is enabled we compute the color (or index)
934 * for both the front and back side of the primitive. Then, when the
935 * orientation of the facet is later learned, we can determine which
936 * color (or index) to use for rendering.
938 * KW: We now know orientation in advance and only shade for
939 * the side or sides which are actually required.
943 * V = vertex position
944 * P = light source position
949 * // light at infinity
950 * IF local_viewer THEN
951 * _VP_inf_norm = unit vector from V to P // Precompute
954 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
959 * Normalize( v ) = normalized vector v
960 * Magnitude( v ) = length of vector v
966 * Whenever the spotlight exponent for a light changes we must call
967 * this function to recompute the exponent lookup table.
970 gl_compute_spot_exp_table( struct gl_light
*l
)
973 GLdouble exponent
= l
->SpotExponent
;
977 l
->_SpotExpTable
[0][0] = 0.0;
979 for (i
= EXP_TABLE_SIZE
- 1; i
> 0 ;i
--) {
981 tmp
= pow(i
/ (GLdouble
) (EXP_TABLE_SIZE
- 1), exponent
);
982 if (tmp
< FLT_MIN
* 100.0) {
987 l
->_SpotExpTable
[i
][0] = tmp
;
989 for (i
= 0; i
< EXP_TABLE_SIZE
- 1; i
++) {
990 l
->_SpotExpTable
[i
][1] = l
->_SpotExpTable
[i
+1][0] - l
->_SpotExpTable
[i
][0];
992 l
->_SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
998 /* Calculate a new shine table. Doing this here saves a branch in
999 * lighting, and the cost of doing it early may be partially offset
1000 * by keeping a MRU cache of shine tables for various shine values.
1003 compute_shine_table( struct gl_shine_tab
*tab
, GLfloat shininess
)
1006 GLfloat
*m
= tab
->tab
;
1009 if (shininess
== 0.0) {
1010 for (i
= 1 ; i
<= SHINE_TABLE_SIZE
; i
++)
1014 for (i
= 1 ; i
< SHINE_TABLE_SIZE
; i
++) {
1015 GLdouble t
= pow(i
/ (GLfloat
) (SHINE_TABLE_SIZE
- 1), shininess
);
1021 m
[SHINE_TABLE_SIZE
] = 1.0;
1024 tab
->shininess
= shininess
;
1029 gl_compute_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
1031 #define DISTSQR(a,b) ((a-b)*(a-b))
1032 struct gl_shine_tab
*list
= ctx
->_ShineTabList
;
1033 struct gl_shine_tab
*s
;
1036 if ( DISTSQR(s
->shininess
, shininess
) < 1e-4 )
1041 if (s
->refcount
== 0)
1044 compute_shine_table( s
, shininess
);
1047 ctx
->_ShineTable
[i
]->refcount
--;
1048 ctx
->_ShineTable
[i
] = s
;
1049 move_to_tail( list
, s
);
1058 * Examine current lighting parameters to determine if the optimized lighting
1059 * function can be used.
1060 * Also, precompute some lighting values such as the products of light
1061 * source and material ambient, diffuse and specular coefficients.
1064 gl_update_lighting( GLcontext
*ctx
)
1066 struct gl_light
*light
;
1067 ctx
->_TriangleCaps
&= ~(DD_TRI_LIGHT_TWOSIDE
|DD_LIGHTING_CULL
);
1068 ctx
->_NeedEyeCoords
&= ~NEED_EYE_LIGHT
;
1069 ctx
->_NeedNormals
&= ~NEED_NORMALS_LIGHT
;
1070 ctx
->Light
._Flags
= 0;
1072 if (!ctx
->Light
.Enabled
)
1075 ctx
->_NeedNormals
|= NEED_NORMALS_LIGHT
;
1077 if (ctx
->Light
.Model
.TwoSide
)
1078 ctx
->_TriangleCaps
|= (DD_TRI_LIGHT_TWOSIDE
|DD_LIGHTING_CULL
);
1080 foreach(light
, &ctx
->Light
.EnabledList
) {
1081 ctx
->Light
._Flags
|= light
->_Flags
;
1084 ctx
->Light
._NeedVertices
=
1085 ((ctx
->Light
._Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
1086 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
||
1087 ctx
->Light
.Model
.LocalViewer
);
1089 if ((ctx
->Light
._Flags
& LIGHT_POSITIONAL
) ||
1090 ctx
->Light
.Model
.LocalViewer
)
1091 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1094 /* XXX: This test is overkill & needs to be fixed both for software and
1095 * hardware t&l drivers. The above should be sufficient & should
1096 * be tested to verify this.
1098 if (ctx
->Light
._NeedVertices
)
1099 ctx
->_NeedEyeCoords
|= NEED_EYE_LIGHT
;
1102 /* Precompute some shading values.
1104 if (ctx
->Visual
.RGBAflag
) {
1105 GLuint sides
= ctx
->Light
.Model
.TwoSide
? 2 : 1;
1107 for (side
=0; side
< sides
; side
++) {
1108 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1110 COPY_3V(ctx
->Light
._BaseColor
[side
], mat
->Emission
);
1111 ACC_SCALE_3V(ctx
->Light
._BaseColor
[side
],
1112 ctx
->Light
.Model
.Ambient
,
1115 FLOAT_COLOR_TO_CHAN(ctx
->Light
._BaseAlpha
[side
],
1116 ctx
->Light
.Material
[side
].Diffuse
[3] );
1119 foreach (light
, &ctx
->Light
.EnabledList
) {
1120 for (side
=0; side
< sides
; side
++) {
1121 const struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1122 SCALE_3V( light
->_MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1123 SCALE_3V( light
->_MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1124 SCALE_3V( light
->_MatSpecular
[side
], light
->Specular
,
1130 static const GLfloat ci
[3] = { .30, .59, .11 };
1131 foreach(light
, &ctx
->Light
.EnabledList
) {
1132 light
->_dli
= DOT3(ci
, light
->Diffuse
);
1133 light
->_sli
= DOT3(ci
, light
->Specular
);
1141 * _TNL_NEW_NEED_EYE_COORDS
1143 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1144 * Also update on lighting space changes.
1147 gl_compute_light_positions( GLcontext
*ctx
)
1149 struct gl_light
*light
;
1150 static const GLfloat eye_z
[3] = { 0, 0, 1 };
1152 if (!ctx
->Light
.Enabled
)
1155 if (ctx
->_NeedEyeCoords
) {
1156 COPY_3V( ctx
->_EyeZDir
, eye_z
);
1159 TRANSFORM_NORMAL( ctx
->_EyeZDir
, eye_z
, ctx
->ModelView
.m
);
1162 foreach (light
, &ctx
->Light
.EnabledList
) {
1164 if (ctx
->_NeedEyeCoords
) {
1165 COPY_4FV( light
->_Position
, light
->EyePosition
);
1168 TRANSFORM_POINT( light
->_Position
, ctx
->ModelView
.inv
,
1169 light
->EyePosition
);
1172 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1173 /* VP (VP) = Normalize( Position ) */
1174 COPY_3V( light
->_VP_inf_norm
, light
->_Position
);
1175 NORMALIZE_3FV( light
->_VP_inf_norm
);
1177 if (!ctx
->Light
.Model
.LocalViewer
) {
1178 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1179 ADD_3V( light
->_h_inf_norm
, light
->_VP_inf_norm
, ctx
->_EyeZDir
);
1180 NORMALIZE_3FV( light
->_h_inf_norm
);
1182 light
->_VP_inf_spot_attenuation
= 1.0;
1185 if (light
->_Flags
& LIGHT_SPOT
) {
1186 if (ctx
->_NeedEyeCoords
) {
1187 COPY_3V( light
->_NormDirection
, light
->EyeDirection
);
1190 TRANSFORM_NORMAL( light
->_NormDirection
,
1191 light
->EyeDirection
,
1195 NORMALIZE_3FV( light
->_NormDirection
);
1197 if (!(light
->_Flags
& LIGHT_POSITIONAL
)) {
1198 GLfloat PV_dot_dir
= - DOT3(light
->_VP_inf_norm
,
1199 light
->_NormDirection
);
1201 if (PV_dot_dir
> light
->_CosCutoff
) {
1202 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1204 light
->_VP_inf_spot_attenuation
=
1205 (light
->_SpotExpTable
[k
][0] +
1206 (x
-k
)*light
->_SpotExpTable
[k
][1]);
1209 light
->_VP_inf_spot_attenuation
= 0;