1 /* $Id: light.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45 #include "simple_list.h"
50 #include "GL/xf86glx.h"
56 void gl_ShadeModel( GLcontext
*ctx
, GLenum mode
)
58 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glShadeModel");
60 if (MESA_VERBOSE
& VERBOSE_API
)
61 fprintf(stderr
, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode
));
66 if (ctx
->Light
.ShadeModel
!=mode
) {
67 ctx
->Light
.ShadeModel
= mode
;
68 ctx
->TriangleCaps
^= DD_FLATSHADE
;
69 ctx
->NewState
|= NEW_RASTER_OPS
;
73 gl_error( ctx
, GL_INVALID_ENUM
, "glShadeModel" );
76 if (ctx
->Driver
.ShadeModel
)
77 (*ctx
->Driver
.ShadeModel
)( ctx
, mode
);
82 void gl_Lightfv( GLcontext
*ctx
,
83 GLenum light
, GLenum pname
, const GLfloat
*params
,
90 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLight");
92 l
= (GLint
) (light
- GL_LIGHT0
);
94 if (l
<0 || l
>=MAX_LIGHTS
) {
95 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
101 COPY_4V( ctx
->Light
.Light
[l
].Ambient
, params
);
104 COPY_4V( ctx
->Light
.Light
[l
].Diffuse
, params
);
107 COPY_4V( ctx
->Light
.Light
[l
].Specular
, params
);
110 /* transform position by ModelView matrix */
111 TRANSFORM_POINT( ctx
->Light
.Light
[l
].EyePosition
,
115 case GL_SPOT_DIRECTION
:
116 /* transform direction by inverse modelview */
117 if (ctx
->ModelView
.flags
& MAT_DIRTY_INVERSE
) {
118 gl_matrix_analyze( &ctx
->ModelView
);
120 TRANSFORM_NORMAL( ctx
->Light
.Light
[l
].EyeDirection
,
122 ctx
->ModelView
.inv
);
124 case GL_SPOT_EXPONENT
:
125 if (params
[0]<0.0 || params
[0]>128.0) {
126 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
129 if (ctx
->Light
.Light
[l
].SpotExponent
!= params
[0]) {
130 ctx
->Light
.Light
[l
].SpotExponent
= params
[0];
131 gl_compute_spot_exp_table( &ctx
->Light
.Light
[l
] );
135 if ((params
[0]<0.0 || params
[0]>90.0) && params
[0]!=180.0) {
136 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
139 ctx
->Light
.Light
[l
].SpotCutoff
= params
[0];
140 ctx
->Light
.Light
[l
].CosCutoff
= cos(params
[0]*DEG2RAD
);
141 if (ctx
->Light
.Light
[l
].CosCutoff
< 0)
142 ctx
->Light
.Light
[l
].CosCutoff
= 0;
144 case GL_CONSTANT_ATTENUATION
:
146 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
149 ctx
->Light
.Light
[l
].ConstantAttenuation
= params
[0];
151 case GL_LINEAR_ATTENUATION
:
153 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
156 ctx
->Light
.Light
[l
].LinearAttenuation
= params
[0];
158 case GL_QUADRATIC_ATTENUATION
:
160 gl_error( ctx
, GL_INVALID_VALUE
, "glLight" );
163 ctx
->Light
.Light
[l
].QuadraticAttenuation
= params
[0];
166 gl_error( ctx
, GL_INVALID_ENUM
, "glLight" );
170 ctx
->NewState
|= NEW_LIGHTING
;
175 void gl_GetLightfv( GLcontext
*ctx
,
176 GLenum light
, GLenum pname
, GLfloat
*params
)
178 GLint l
= (GLint
) (light
- GL_LIGHT0
);
180 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
182 if (l
<0 || l
>=MAX_LIGHTS
) {
183 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
189 COPY_4V( params
, ctx
->Light
.Light
[l
].Ambient
);
192 COPY_4V( params
, ctx
->Light
.Light
[l
].Diffuse
);
195 COPY_4V( params
, ctx
->Light
.Light
[l
].Specular
);
198 COPY_4V( params
, ctx
->Light
.Light
[l
].EyePosition
);
200 case GL_SPOT_DIRECTION
:
201 COPY_3V( params
, ctx
->Light
.Light
[l
].EyeDirection
);
203 case GL_SPOT_EXPONENT
:
204 params
[0] = ctx
->Light
.Light
[l
].SpotExponent
;
207 params
[0] = ctx
->Light
.Light
[l
].SpotCutoff
;
209 case GL_CONSTANT_ATTENUATION
:
210 params
[0] = ctx
->Light
.Light
[l
].ConstantAttenuation
;
212 case GL_LINEAR_ATTENUATION
:
213 params
[0] = ctx
->Light
.Light
[l
].LinearAttenuation
;
215 case GL_QUADRATIC_ATTENUATION
:
216 params
[0] = ctx
->Light
.Light
[l
].QuadraticAttenuation
;
219 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightfv" );
226 void gl_GetLightiv( GLcontext
*ctx
, GLenum light
, GLenum pname
, GLint
*params
)
228 GLint l
= (GLint
) (light
- GL_LIGHT0
);
230 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetLight");
232 if (l
<0 || l
>=MAX_LIGHTS
) {
233 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
239 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[0]);
240 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[1]);
241 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[2]);
242 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Ambient
[3]);
245 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[0]);
246 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[1]);
247 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[2]);
248 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Diffuse
[3]);
251 params
[0] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[0]);
252 params
[1] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[1]);
253 params
[2] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[2]);
254 params
[3] = FLOAT_TO_INT(ctx
->Light
.Light
[l
].Specular
[3]);
257 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[0];
258 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[1];
259 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[2];
260 params
[3] = (GLint
) ctx
->Light
.Light
[l
].EyePosition
[3];
262 case GL_SPOT_DIRECTION
:
263 params
[0] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[0];
264 params
[1] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[1];
265 params
[2] = (GLint
) ctx
->Light
.Light
[l
].EyeDirection
[2];
267 case GL_SPOT_EXPONENT
:
268 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotExponent
;
271 params
[0] = (GLint
) ctx
->Light
.Light
[l
].SpotCutoff
;
273 case GL_CONSTANT_ATTENUATION
:
274 params
[0] = (GLint
) ctx
->Light
.Light
[l
].ConstantAttenuation
;
276 case GL_LINEAR_ATTENUATION
:
277 params
[0] = (GLint
) ctx
->Light
.Light
[l
].LinearAttenuation
;
279 case GL_QUADRATIC_ATTENUATION
:
280 params
[0] = (GLint
) ctx
->Light
.Light
[l
].QuadraticAttenuation
;
283 gl_error( ctx
, GL_INVALID_ENUM
, "glGetLightiv" );
290 /**********************************************************************/
291 /*** Light Model ***/
292 /**********************************************************************/
295 void gl_LightModelfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
297 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glLightModel");
300 case GL_LIGHT_MODEL_AMBIENT
:
301 COPY_4V( ctx
->Light
.Model
.Ambient
, params
);
303 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
305 ctx
->Light
.Model
.LocalViewer
= GL_FALSE
;
307 ctx
->Light
.Model
.LocalViewer
= GL_TRUE
;
309 case GL_LIGHT_MODEL_TWO_SIDE
:
311 ctx
->Light
.Model
.TwoSide
= GL_FALSE
;
313 ctx
->Light
.Model
.TwoSide
= GL_TRUE
;
315 case GL_LIGHT_MODEL_COLOR_CONTROL
:
316 ctx
->TriangleCaps
&= ~DD_SEPERATE_SPECULAR
;
317 if (params
[0] == (GLfloat
) GL_SINGLE_COLOR
)
318 ctx
->Light
.Model
.ColorControl
= GL_SINGLE_COLOR
;
319 else if (params
[0] == (GLfloat
) GL_SEPARATE_SPECULAR_COLOR
) {
320 ctx
->Light
.Model
.ColorControl
= GL_SEPARATE_SPECULAR_COLOR
;
321 ctx
->TriangleCaps
|= DD_SEPERATE_SPECULAR
;
323 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel(param)" );
326 gl_error( ctx
, GL_INVALID_ENUM
, "glLightModel" );
329 ctx
->NewState
|= NEW_LIGHTING
;
335 /********** MATERIAL **********/
339 * Given a face and pname value (ala glColorMaterial), compute a bitmask
340 * of the targeted material values.
342 GLuint
gl_material_bitmask( GLcontext
*ctx
, GLenum face
, GLenum pname
,
348 /* Make a bitmask indicating what material attribute(s) we're updating */
351 bitmask
|= FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
;
354 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
357 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
360 bitmask
|= FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
;
363 bitmask
|= FRONT_SHININESS_BIT
| BACK_SHININESS_BIT
;
365 case GL_AMBIENT_AND_DIFFUSE
:
366 bitmask
|= FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
;
367 bitmask
|= FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
;
369 case GL_COLOR_INDEXES
:
370 bitmask
|= FRONT_INDEXES_BIT
| BACK_INDEXES_BIT
;
373 gl_error( ctx
, GL_INVALID_ENUM
, where
);
377 if (face
==GL_FRONT
) {
378 bitmask
&= FRONT_MATERIAL_BITS
;
380 else if (face
==GL_BACK
) {
381 bitmask
&= BACK_MATERIAL_BITS
;
383 else if (face
!= GL_FRONT_AND_BACK
) {
384 gl_error( ctx
, GL_INVALID_ENUM
, where
);
388 if (bitmask
& ~legal
) {
389 gl_error( ctx
, GL_INVALID_ENUM
, where
);
402 * Check if the global material has to be updated with info that was
403 * associated with a vertex via glMaterial.
404 * This function is used when any material values get changed between
405 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
406 * when GL_COLOR_MATERIAL is enabled.
408 * KW: Added code here to keep the precomputed variables uptodate.
409 * This means we can use the faster shade functions when using
410 * GL_COLOR_MATERIAL, and we can also now use the precomputed
411 * values in the slower shading functions, which further offsets
412 * the cost of doing this here.
414 void gl_update_material( GLcontext
*ctx
,
415 struct gl_material
*src
,
418 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
421 if (ctx
->Light
.ColorMaterialEnabled
)
422 bitmask
&= ~ctx
->Light
.ColorMaterialBitmask
;
427 if (bitmask
& FRONT_AMBIENT_BIT
) {
428 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
429 SUB_3V( tmp
, src
[0].Ambient
, mat
->Ambient
);
430 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], ctx
->Light
.Model
.Ambient
, tmp
);
431 foreach (light
, list
) {
432 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
434 COPY_4FV( mat
->Ambient
, src
[0].Ambient
);
436 if (bitmask
& BACK_AMBIENT_BIT
) {
437 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
438 SUB_3V( tmp
, src
[1].Ambient
, mat
->Ambient
);
439 ACC_SCALE_3V( ctx
->Light
.BaseColor
[1], ctx
->Light
.Model
.Ambient
, tmp
);
440 foreach (light
, list
) {
441 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
443 COPY_4FV( mat
->Ambient
, src
[1].Ambient
);
445 if (bitmask
& FRONT_DIFFUSE_BIT
) {
446 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
447 SUB_3V( tmp
, src
[0].Diffuse
, mat
->Diffuse
);
448 foreach (light
, list
) {
449 ACC_SCALE_3V( light
->MatDiffuse
[0], light
->Diffuse
, tmp
);
451 COPY_4FV( mat
->Diffuse
, src
[0].Diffuse
);
452 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[0], mat
->Diffuse
[3]);
454 if (bitmask
& BACK_DIFFUSE_BIT
) {
455 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
456 SUB_3V( tmp
, src
[1].Diffuse
, mat
->Diffuse
);
457 foreach (light
, list
) {
458 ACC_SCALE_3V( light
->MatDiffuse
[1], light
->Diffuse
, tmp
);
460 COPY_4FV( mat
->Diffuse
, src
[1].Diffuse
);
461 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[1], mat
->Diffuse
[3]);
463 if (bitmask
& FRONT_SPECULAR_BIT
) {
464 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
465 SUB_3V( tmp
, src
[0].Specular
, mat
->Specular
);
466 foreach (light
, list
) {
467 if (light
->Flags
& LIGHT_SPECULAR
) {
468 ACC_SCALE_3V( light
->MatSpecular
[0], light
->Specular
, tmp
);
469 light
->IsMatSpecular
[0] =
470 (LEN_SQUARED_3FV(light
->MatSpecular
[0]) > 1e-16);
473 COPY_4FV( mat
->Specular
, src
[0].Specular
);
475 if (bitmask
& BACK_SPECULAR_BIT
) {
476 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
477 SUB_3V( tmp
, src
[1].Specular
, mat
->Specular
);
478 foreach (light
, list
) {
479 if (light
->Flags
& LIGHT_SPECULAR
) {
480 ACC_SCALE_3V( light
->MatSpecular
[1], light
->Specular
, tmp
);
481 light
->IsMatSpecular
[1] =
482 (LEN_SQUARED_3FV(light
->MatSpecular
[1]) > 1e-16);
485 COPY_4FV( mat
->Specular
, src
[1].Specular
);
487 if (bitmask
& FRONT_EMISSION_BIT
) {
488 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
489 SUB_3V( tmp
, src
[0].Emission
, mat
->Emission
);
490 ACC_3V( ctx
->Light
.BaseColor
[0], tmp
);
491 COPY_4FV( mat
->Emission
, src
[0].Emission
);
493 if (bitmask
& BACK_EMISSION_BIT
) {
494 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
495 SUB_3V( tmp
, src
[1].Emission
, mat
->Emission
);
496 ACC_3V( ctx
->Light
.BaseColor
[1], tmp
);
497 COPY_4FV( mat
->Emission
, src
[1].Emission
);
499 if (bitmask
& FRONT_SHININESS_BIT
) {
500 GLfloat shininess
= ctx
->Light
.Material
[0].Shininess
= src
[0].Shininess
;
501 gl_compute_shine_table( ctx
, 0, shininess
);
502 gl_compute_shine_table( ctx
, 2, shininess
* .5 );
504 if (bitmask
& BACK_SHININESS_BIT
) {
505 GLfloat shininess
= ctx
->Light
.Material
[1].Shininess
= src
[1].Shininess
;
506 gl_compute_shine_table( ctx
, 1, shininess
);
507 gl_compute_shine_table( ctx
, 3, shininess
* .5 );
509 if (bitmask
& FRONT_INDEXES_BIT
) {
510 ctx
->Light
.Material
[0].AmbientIndex
= src
[0].AmbientIndex
;
511 ctx
->Light
.Material
[0].DiffuseIndex
= src
[0].DiffuseIndex
;
512 ctx
->Light
.Material
[0].SpecularIndex
= src
[0].SpecularIndex
;
514 if (bitmask
& BACK_INDEXES_BIT
) {
515 ctx
->Light
.Material
[1].AmbientIndex
= src
[1].AmbientIndex
;
516 ctx
->Light
.Material
[1].DiffuseIndex
= src
[1].DiffuseIndex
;
517 ctx
->Light
.Material
[1].SpecularIndex
= src
[1].SpecularIndex
;
527 void gl_update_color_material( GLcontext
*ctx
,
528 const GLubyte rgba
[4] )
530 struct gl_light
*light
, *list
= &ctx
->Light
.EnabledList
;
531 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
532 GLfloat tmp
[4], color
[4];
534 UBYTE_RGBA_TO_FLOAT_RGBA( color
, rgba
);
536 if (bitmask
& FRONT_AMBIENT_BIT
) {
537 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
538 SUB_3V( tmp
, color
, mat
->Ambient
);
539 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], ctx
->Light
.Model
.Ambient
, tmp
);
540 foreach (light
, list
) {
541 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
543 COPY_4FV( mat
->Ambient
, color
);
546 if (bitmask
& BACK_AMBIENT_BIT
) {
547 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
548 SUB_3V( tmp
, color
, mat
->Ambient
);
549 ACC_SCALE_3V( ctx
->Light
.BaseColor
[1], ctx
->Light
.Model
.Ambient
, tmp
);
550 foreach (light
, list
) {
551 ACC_SCALE_3V( ctx
->Light
.BaseColor
[0], light
->Ambient
, tmp
);
553 COPY_4FV( mat
->Ambient
, color
);
556 if (bitmask
& FRONT_DIFFUSE_BIT
) {
557 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
558 SUB_3V( tmp
, color
, mat
->Diffuse
);
559 foreach (light
, list
) {
560 ACC_SCALE_3V( light
->MatDiffuse
[0], light
->Diffuse
, tmp
);
562 COPY_4FV( mat
->Diffuse
, color
);
563 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[0], mat
->Diffuse
[3]);
566 if (bitmask
& BACK_DIFFUSE_BIT
) {
567 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
568 SUB_3V( tmp
, color
, mat
->Diffuse
);
569 foreach (light
, list
) {
570 ACC_SCALE_3V( light
->MatDiffuse
[1], light
->Diffuse
, tmp
);
572 COPY_4FV( mat
->Diffuse
, color
);
573 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[1], mat
->Diffuse
[3]);
576 if (bitmask
& FRONT_SPECULAR_BIT
) {
577 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
578 SUB_3V( tmp
, color
, mat
->Specular
);
579 foreach (light
, list
) {
580 if (light
->Flags
& LIGHT_SPECULAR
) {
581 ACC_SCALE_3V( light
->MatSpecular
[0], light
->Specular
, tmp
);
582 light
->IsMatSpecular
[0] =
583 (LEN_SQUARED_3FV(light
->MatSpecular
[0]) > 1e-16);
586 COPY_4FV( mat
->Specular
, color
);
588 if (bitmask
& BACK_SPECULAR_BIT
) {
589 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
590 SUB_3V( tmp
, color
, mat
->Specular
);
591 foreach (light
, list
) {
592 if (light
->Flags
& LIGHT_SPECULAR
) {
593 ACC_SCALE_3V( light
->MatSpecular
[1], light
->Specular
, tmp
);
594 light
->IsMatSpecular
[1] =
595 (LEN_SQUARED_3FV(light
->MatSpecular
[1]) > 1e-16);
598 COPY_4FV( mat
->Specular
, color
);
600 if (bitmask
& FRONT_EMISSION_BIT
) {
601 struct gl_material
*mat
= &ctx
->Light
.Material
[0];
602 SUB_3V( tmp
, color
, mat
->Emission
);
603 ACC_3V( ctx
->Light
.BaseColor
[0], tmp
);
604 COPY_4FV( mat
->Emission
, color
);
606 if (bitmask
& BACK_EMISSION_BIT
) {
607 struct gl_material
*mat
= &ctx
->Light
.Material
[1];
608 SUB_3V( tmp
, color
, mat
->Emission
);
609 ACC_3V( ctx
->Light
.BaseColor
[1], tmp
);
610 COPY_4FV( mat
->Emission
, color
);
617 void gl_ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
620 GLuint legal
= (FRONT_EMISSION_BIT
| BACK_EMISSION_BIT
|
621 FRONT_SPECULAR_BIT
| BACK_SPECULAR_BIT
|
622 FRONT_DIFFUSE_BIT
| BACK_DIFFUSE_BIT
|
623 FRONT_AMBIENT_BIT
| BACK_AMBIENT_BIT
);
625 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glColorMaterial");
627 bitmask
= gl_material_bitmask( ctx
, face
, mode
, legal
, "glColorMaterial" );
630 ctx
->Light
.ColorMaterialBitmask
= bitmask
;
631 ctx
->Light
.ColorMaterialFace
= face
;
632 ctx
->Light
.ColorMaterialMode
= mode
;
638 /* KW: This is now called directly (ie by name) from the glMaterial*
641 void gl_Materialfv( GLcontext
*ctx
,
642 GLenum face
, GLenum pname
, const GLfloat
*params
)
644 struct immediate
*IM
;
645 struct gl_material
*mat
;
649 bitmask
= gl_material_bitmask( ctx
, face
, pname
, ~0, "gl_Materialfv" );
656 if (!(IM
->Flag
[count
] & VERT_MATERIAL
)) {
657 IM
->Flag
[count
] |= VERT_MATERIAL
;
658 IM
->MaterialMask
[count
] = 0;
661 IM
->MaterialMask
[count
] |= bitmask
;
662 mat
= IM
->Material
[count
];
663 IM
->LastMaterial
= count
;
665 if (bitmask
& FRONT_AMBIENT_BIT
) {
666 COPY_4FV( mat
[0].Ambient
, params
);
668 if (bitmask
& BACK_AMBIENT_BIT
) {
669 COPY_4FV( mat
[1].Ambient
, params
);
671 if (bitmask
& FRONT_DIFFUSE_BIT
) {
672 COPY_4FV( mat
[0].Diffuse
, params
);
674 if (bitmask
& BACK_DIFFUSE_BIT
) {
675 COPY_4FV( mat
[1].Diffuse
, params
);
677 if (bitmask
& FRONT_SPECULAR_BIT
) {
678 COPY_4FV( mat
[0].Specular
, params
);
680 if (bitmask
& BACK_SPECULAR_BIT
) {
681 COPY_4FV( mat
[1].Specular
, params
);
683 if (bitmask
& FRONT_EMISSION_BIT
) {
684 COPY_4FV( mat
[0].Emission
, params
);
686 if (bitmask
& BACK_EMISSION_BIT
) {
687 COPY_4FV( mat
[1].Emission
, params
);
689 if (bitmask
& FRONT_SHININESS_BIT
) {
690 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
691 mat
[0].Shininess
= shininess
;
693 if (bitmask
& BACK_SHININESS_BIT
) {
694 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
695 mat
[1].Shininess
= shininess
;
697 if (bitmask
& FRONT_INDEXES_BIT
) {
698 mat
[0].AmbientIndex
= params
[0];
699 mat
[0].DiffuseIndex
= params
[1];
700 mat
[0].SpecularIndex
= params
[2];
702 if (bitmask
& BACK_INDEXES_BIT
) {
703 mat
[1].AmbientIndex
= params
[0];
704 mat
[1].DiffuseIndex
= params
[1];
705 mat
[1].SpecularIndex
= params
[2];
712 void gl_GetMaterialfv( GLcontext
*ctx
,
713 GLenum face
, GLenum pname
, GLfloat
*params
)
717 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialfv");
719 if (face
==GL_FRONT
) {
722 else if (face
==GL_BACK
) {
726 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(face)" );
731 COPY_4FV( params
, ctx
->Light
.Material
[f
].Ambient
);
734 COPY_4FV( params
, ctx
->Light
.Material
[f
].Diffuse
);
737 COPY_4FV( params
, ctx
->Light
.Material
[f
].Specular
);
740 COPY_4FV( params
, ctx
->Light
.Material
[f
].Emission
);
743 *params
= ctx
->Light
.Material
[f
].Shininess
;
745 case GL_COLOR_INDEXES
:
746 params
[0] = ctx
->Light
.Material
[f
].AmbientIndex
;
747 params
[1] = ctx
->Light
.Material
[f
].DiffuseIndex
;
748 params
[2] = ctx
->Light
.Material
[f
].SpecularIndex
;
751 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
757 void gl_GetMaterialiv( GLcontext
*ctx
,
758 GLenum face
, GLenum pname
, GLint
*params
)
762 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetMaterialiv");
764 if (face
==GL_FRONT
) {
767 else if (face
==GL_BACK
) {
771 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialiv(face)" );
776 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[0] );
777 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[1] );
778 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[2] );
779 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Ambient
[3] );
782 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[0] );
783 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[1] );
784 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[2] );
785 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Diffuse
[3] );
788 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[0] );
789 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[1] );
790 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[2] );
791 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Specular
[3] );
794 params
[0] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[0] );
795 params
[1] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[1] );
796 params
[2] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[2] );
797 params
[3] = FLOAT_TO_INT( ctx
->Light
.Material
[f
].Emission
[3] );
800 *params
= ROUNDF( ctx
->Light
.Material
[f
].Shininess
);
802 case GL_COLOR_INDEXES
:
803 params
[0] = ROUNDF( ctx
->Light
.Material
[f
].AmbientIndex
);
804 params
[1] = ROUNDF( ctx
->Light
.Material
[f
].DiffuseIndex
);
805 params
[2] = ROUNDF( ctx
->Light
.Material
[f
].SpecularIndex
);
808 gl_error( ctx
, GL_INVALID_ENUM
, "glGetMaterialfv(pname)" );
815 /**********************************************************************/
816 /***** Lighting computation *****/
817 /**********************************************************************/
822 * When two-sided lighting is enabled we compute the color (or index)
823 * for both the front and back side of the primitive. Then, when the
824 * orientation of the facet is later learned, we can determine which
825 * color (or index) to use for rendering.
827 * KW: We now know orientation in advance and only shade for
828 * the side or sides which are actually required.
832 * V = vertex position
833 * P = light source position
838 * // light at infinity
839 * IF local_viewer THEN
840 * VP_inf_norm = unit vector from V to P // Precompute
843 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
848 * Normalize( v ) = normalized vector v
849 * Magnitude( v ) = length of vector v
855 * Whenever the spotlight exponent for a light changes we must call
856 * this function to recompute the exponent lookup table.
858 void gl_compute_spot_exp_table( struct gl_light
*l
)
861 double exponent
= l
->SpotExponent
;
865 l
->SpotExpTable
[0][0] = 0.0;
867 for (i
=EXP_TABLE_SIZE
-1;i
>0;i
--) {
869 tmp
= pow(i
/(double)(EXP_TABLE_SIZE
-1), exponent
);
870 if (tmp
< FLT_MIN
*100.0) {
875 l
->SpotExpTable
[i
][0] = tmp
;
877 for (i
=0;i
<EXP_TABLE_SIZE
-1;i
++) {
878 l
->SpotExpTable
[i
][1] = l
->SpotExpTable
[i
+1][0] - l
->SpotExpTable
[i
][0];
880 l
->SpotExpTable
[EXP_TABLE_SIZE
-1][1] = 0.0;
886 /* Calculate a new shine table. Doing this here saves a branch in
887 * lighting, and the cost of doing it early may be partially offset
888 * by keeping a MRU cache of shine tables for various shine values.
890 static void compute_shine_table( struct gl_shine_tab
*tab
, GLfloat shininess
)
893 GLfloat
*m
= tab
->tab
;
896 if (shininess
== 0) {
897 for (i
= 1 ; i
<= SHINE_TABLE_SIZE
; i
++)
900 for (i
= 1 ; i
<= SHINE_TABLE_SIZE
; i
++) {
901 double t
= pow( i
/(GLfloat
)SHINE_TABLE_SIZE
, shininess
);
903 if (t
> 1e-20) m
[i
] = t
;
907 tab
->shininess
= shininess
;
910 #define DISTSQR(a,b) ((a-b)*(a-b))
912 void gl_compute_shine_table( GLcontext
*ctx
, GLuint i
, GLfloat shininess
)
914 struct gl_shine_tab
*list
= ctx
->ShineTabList
;
915 struct gl_shine_tab
*s
;
918 if ( DISTSQR(s
->shininess
, shininess
) < 1e-4 )
924 if (s
->refcount
== 0) break;
926 compute_shine_table( s
, shininess
);
929 ctx
->ShineTable
[i
]->refcount
--;
930 ctx
->ShineTable
[i
] = s
;
931 move_to_tail( list
, s
);
938 void gl_reinit_light_attrib( GLcontext
*ctx
, struct gl_light_attrib
*l
)
942 if (ctx
->ShineTable
[0]->shininess
!= l
->Material
[0].Shininess
) {
943 gl_compute_shine_table( ctx
, 0, l
->Material
[0].Shininess
);
944 gl_compute_shine_table( ctx
, 2, l
->Material
[0].Shininess
* .5 );
947 if (ctx
->ShineTable
[1]->shininess
!= l
->Material
[1].Shininess
) {
948 gl_compute_shine_table( ctx
, 1, l
->Material
[1].Shininess
);
949 gl_compute_shine_table( ctx
, 3, l
->Material
[1].Shininess
* .5 );
952 make_empty_list( &l
->EnabledList
);
953 for (i
= 0 ; i
< MAX_LIGHTS
; i
++) {
954 if (l
->Light
[i
].Enabled
)
955 insert_at_tail( &l
->EnabledList
, &l
->Light
[i
] );
962 * Examine current lighting parameters to determine if the optimized lighting
963 * function can be used.
964 * Also, precompute some lighting values such as the products of light
965 * source and material ambient, diffuse and specular coefficients.
967 void gl_update_lighting( GLcontext
*ctx
)
969 struct gl_light
*light
;
971 ctx
->Light
.Flags
= 0;
973 foreach(light
, &ctx
->Light
.EnabledList
) {
977 if (light
->EyePosition
[3] != 0.0F
)
978 light
->Flags
|= LIGHT_POSITIONAL
;
980 if (LEN_SQUARED_3FV(light
->Specular
) > 1e-16)
981 light
->Flags
|= LIGHT_SPECULAR
;
983 if (light
->SpotCutoff
!= 180.0F
)
984 light
->Flags
|= LIGHT_SPOT
;
986 ctx
->Light
.Flags
|= light
->Flags
;
989 ctx
->Light
.NeedVertices
=
990 ((ctx
->Light
.Flags
& (LIGHT_POSITIONAL
|LIGHT_SPOT
)) ||
991 (ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) ||
992 (ctx
->Light
.Model
.LocalViewer
&& (ctx
->Light
.Flags
& LIGHT_SPECULAR
)));
995 /* Precompute some shading values.
997 if (ctx
->Visual
->RGBAflag
)
999 GLuint sides
= ((ctx
->TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
) ? 2 : 1);
1001 for (side
=0; side
< sides
; side
++) {
1002 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1004 COPY_3V(ctx
->Light
.BaseColor
[side
], mat
->Emission
);
1005 ACC_SCALE_3V(ctx
->Light
.BaseColor
[side
],
1006 ctx
->Light
.Model
.Ambient
,
1009 FLOAT_COLOR_TO_UBYTE_COLOR(ctx
->Light
.BaseAlpha
[side
],
1010 ctx
->Light
.Material
[side
].Diffuse
[3] );
1013 foreach (light
, &ctx
->Light
.EnabledList
) {
1014 for (side
=0; side
< sides
; side
++) {
1015 struct gl_material
*mat
= &ctx
->Light
.Material
[side
];
1016 SCALE_3V( light
->MatDiffuse
[side
], light
->Diffuse
, mat
->Diffuse
);
1017 SCALE_3V( light
->MatAmbient
[side
], light
->Ambient
, mat
->Ambient
);
1018 ACC_3V( ctx
->Light
.BaseColor
[side
], light
->MatAmbient
[side
] );
1019 if (light
->Flags
& LIGHT_SPECULAR
)
1021 SCALE_3V( light
->MatSpecular
[side
], light
->Specular
,
1023 light
->IsMatSpecular
[side
] =
1024 (LEN_SQUARED_3FV(light
->MatSpecular
[side
]) > 1e-16);
1027 light
->IsMatSpecular
[side
] = 0;
1033 static GLfloat ci
[3] = { .30, .59, .11 };
1035 foreach(light
, &ctx
->Light
.EnabledList
) {
1036 light
->dli
= DOT3(ci
, light
->Diffuse
);
1037 light
->sli
= DOT3(ci
, light
->Specular
);
1042 /* Need to seriously restrict the circumstances under which these
1043 * calc's are performed.
1045 void gl_compute_light_positions( GLcontext
*ctx
)
1047 struct gl_light
*light
;
1049 if (ctx
->Light
.NeedVertices
&& !ctx
->Light
.Model
.LocalViewer
) {
1050 GLfloat eye_z
[3] = { 0, 0, 1 };
1051 if (!ctx
->NeedEyeCoords
) {
1052 TRANSFORM_NORMAL( ctx
->EyeZDir
, eye_z
, ctx
->ModelView
.m
);
1054 COPY_3V( ctx
->EyeZDir
, eye_z
);
1058 foreach (light
, &ctx
->Light
.EnabledList
) {
1060 if (!ctx
->NeedEyeCoords
) {
1061 TRANSFORM_POINT( light
->Position
, ctx
->ModelView
.inv
,
1062 light
->EyePosition
);
1064 COPY_4FV( light
->Position
, light
->EyePosition
);
1067 if (!(light
->Flags
& LIGHT_POSITIONAL
))
1069 /* VP (VP) = Normalize( Position ) */
1070 COPY_3V( light
->VP_inf_norm
, light
->Position
);
1071 NORMALIZE_3FV( light
->VP_inf_norm
);
1073 if (!ctx
->Light
.Model
.LocalViewer
)
1075 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1076 ADD_3V( light
->h_inf_norm
, light
->VP_inf_norm
, ctx
->EyeZDir
);
1077 NORMALIZE_3FV( light
->h_inf_norm
);
1080 light
->VP_inf_spot_attenuation
= 1.0;
1083 if (light
->Flags
& LIGHT_SPOT
)
1085 if (ctx
->NeedEyeNormals
) {
1086 COPY_3V( light
->NormDirection
, light
->EyeDirection
);
1088 TRANSFORM_NORMAL( light
->NormDirection
,
1089 light
->EyeDirection
,
1093 NORMALIZE_3FV( light
->NormDirection
);
1096 /* Unlikely occurrance?
1098 if (!(light
->Flags
& LIGHT_POSITIONAL
)) {
1099 GLfloat PV_dot_dir
= - DOT3(light
->VP_inf_norm
,
1100 light
->NormDirection
);
1102 if (PV_dot_dir
> light
->CosCutoff
) {
1103 double x
= PV_dot_dir
* (EXP_TABLE_SIZE
-1);
1105 light
->VP_inf_spot_attenuation
=
1106 (light
->SpotExpTable
[k
][0] +
1107 (x
-k
)*light
->SpotExpTable
[k
][1]);
1110 light
->VP_inf_spot_attenuation
= 0;
1120 void gl_update_normal_transform( GLcontext
*ctx
)
1122 GLuint new_flag
= 0;
1123 normal_func
*last
= ctx
->NormalTransform
;
1125 ctx
->vb_rescale_factor
= 1.0;
1127 if (ctx
->NeedEyeCoords
) {
1128 if (ctx
->NeedNormals
) {
1129 GLuint transform
= NORM_TRANSFORM_NO_ROT
;
1131 if (ctx
->ModelView
.flags
& (MAT_FLAG_GENERAL
|
1133 MAT_FLAG_GENERAL_3D
|
1134 MAT_FLAG_PERSPECTIVE
))
1135 transform
= NORM_TRANSFORM
;
1138 new_flag
= ctx
->NewState
& NEW_MODELVIEW
;
1139 ctx
->vb_rescale_factor
= ctx
->rescale_factor
;
1141 if (ctx
->Transform
.Normalize
)
1143 ctx
->NormalTransform
= gl_normal_tab
[transform
| NORM_NORMALIZE
];
1145 else if (ctx
->Transform
.RescaleNormals
&&
1146 ctx
->rescale_factor
!= 1.0)
1148 ctx
->NormalTransform
= gl_normal_tab
[transform
| NORM_RESCALE
];
1152 ctx
->NormalTransform
= gl_normal_tab
[transform
];
1155 ctx
->NormalTransform
= 0;
1159 if (ctx
->NeedNormals
) {
1160 ctx
->vb_rescale_factor
= 1.0/ctx
->rescale_factor
;
1162 if (ctx
->Transform
.Normalize
)
1164 ctx
->NormalTransform
= gl_normal_tab
[NORM_NORMALIZE
];
1166 else if (!ctx
->Transform
.RescaleNormals
&&
1167 ctx
->rescale_factor
!= 1.0)
1169 ctx
->NormalTransform
= gl_normal_tab
[NORM_RESCALE
];
1173 ctx
->NormalTransform
= 0;
1176 ctx
->NormalTransform
= 0;
1180 if (last
!= ctx
->NormalTransform
|| new_flag
)
1181 ctx
->NewState
|= NEW_NORMAL_TRANSFORM
;