xref: /reactos/dll/opengl/mesa/light.c (revision 5f2bebf7)
1*5f2bebf7SJérôme Gardou /* $Id: light.c,v 1.14 1997/07/24 01:24:11 brianp Exp $ */
2*5f2bebf7SJérôme Gardou 
3*5f2bebf7SJérôme Gardou /*
4*5f2bebf7SJérôme Gardou  * Mesa 3-D graphics library
5*5f2bebf7SJérôme Gardou  * Version:  2.4
6*5f2bebf7SJérôme Gardou  * Copyright (C) 1995-1997  Brian Paul
7*5f2bebf7SJérôme Gardou  *
8*5f2bebf7SJérôme Gardou  * This library is free software; you can redistribute it and/or
9*5f2bebf7SJérôme Gardou  * modify it under the terms of the GNU Library General Public
10*5f2bebf7SJérôme Gardou  * License as published by the Free Software Foundation; either
11*5f2bebf7SJérôme Gardou  * version 2 of the License, or (at your option) any later version.
12*5f2bebf7SJérôme Gardou  *
13*5f2bebf7SJérôme Gardou  * This library is distributed in the hope that it will be useful,
14*5f2bebf7SJérôme Gardou  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*5f2bebf7SJérôme Gardou  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*5f2bebf7SJérôme Gardou  * Library General Public License for more details.
17*5f2bebf7SJérôme Gardou  *
18*5f2bebf7SJérôme Gardou  * You should have received a copy of the GNU Library General Public
19*5f2bebf7SJérôme Gardou  * License along with this library; if not, write to the Free
20*5f2bebf7SJérôme Gardou  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*5f2bebf7SJérôme Gardou  */
22*5f2bebf7SJérôme Gardou 
23*5f2bebf7SJérôme Gardou 
24*5f2bebf7SJérôme Gardou /*
25*5f2bebf7SJérôme Gardou  * $Log: light.c,v $
26*5f2bebf7SJérôme Gardou  * Revision 1.14  1997/07/24 01:24:11  brianp
27*5f2bebf7SJérôme Gardou  * changed precompiled header symbol from PCH to PC_HEADER
28*5f2bebf7SJérôme Gardou  *
29*5f2bebf7SJérôme Gardou  * Revision 1.13  1997/06/20 04:15:43  brianp
30*5f2bebf7SJérôme Gardou  * optimized changing of SHININESS (Henk Kok)
31*5f2bebf7SJérôme Gardou  *
32*5f2bebf7SJérôme Gardou  * Revision 1.12  1997/05/28 03:25:26  brianp
33*5f2bebf7SJérôme Gardou  * added precompiled header (PCH) support
34*5f2bebf7SJérôme Gardou  *
35*5f2bebf7SJérôme Gardou  * Revision 1.11  1997/05/01 01:38:57  brianp
36*5f2bebf7SJérôme Gardou  * now use NORMALIZE_3FV() macro from mmath.h
37*5f2bebf7SJérôme Gardou  *
38*5f2bebf7SJérôme Gardou  * Revision 1.10  1997/04/20 20:28:49  brianp
39*5f2bebf7SJérôme Gardou  * replaced abort() with gl_problem()
40*5f2bebf7SJérôme Gardou  *
41*5f2bebf7SJérôme Gardou  * Revision 1.9  1997/04/07 02:59:17  brianp
42*5f2bebf7SJérôme Gardou  * small optimization to setting of shininess and spot exponent
43*5f2bebf7SJérôme Gardou  *
44*5f2bebf7SJérôme Gardou  * Revision 1.8  1997/04/01 04:09:31  brianp
45*5f2bebf7SJérôme Gardou  * misc code clean-ups.  moved shading code to shade.c
46*5f2bebf7SJérôme Gardou  *
47*5f2bebf7SJérôme Gardou  * Revision 1.7  1997/03/11 00:37:39  brianp
48*5f2bebf7SJérôme Gardou  * spotlight factor now effects ambient lighting
49*5f2bebf7SJérôme Gardou  *
50*5f2bebf7SJérôme Gardou  * Revision 1.6  1996/12/18 20:02:07  brianp
51*5f2bebf7SJérôme Gardou  * glColorMaterial() and glMaterial() should finally work right!
52*5f2bebf7SJérôme Gardou  *
53*5f2bebf7SJérôme Gardou  * Revision 1.5  1996/12/07 10:22:41  brianp
54*5f2bebf7SJérôme Gardou  * gl_Materialfv() now calls gl_set_material() if GL_COLOR_MATERIAL disabled
55*5f2bebf7SJérôme Gardou  * implemented gl_GetLightiv()
56*5f2bebf7SJérôme Gardou  *
57*5f2bebf7SJérôme Gardou  * Revision 1.4  1996/11/08 04:39:23  brianp
58*5f2bebf7SJérôme Gardou  * new gl_compute_spot_exp_table() contributed by Randy Frank
59*5f2bebf7SJérôme Gardou  *
60*5f2bebf7SJérôme Gardou  * Revision 1.3  1996/09/27 01:27:55  brianp
61*5f2bebf7SJérôme Gardou  * removed unused variables
62*5f2bebf7SJérôme Gardou  *
63*5f2bebf7SJérôme Gardou  * Revision 1.2  1996/09/15 14:18:10  brianp
64*5f2bebf7SJérôme Gardou  * now use GLframebuffer and GLvisual
65*5f2bebf7SJérôme Gardou  *
66*5f2bebf7SJérôme Gardou  * Revision 1.1  1996/09/13 01:38:16  brianp
67*5f2bebf7SJérôme Gardou  * Initial revision
68*5f2bebf7SJérôme Gardou  *
69*5f2bebf7SJérôme Gardou  */
70*5f2bebf7SJérôme Gardou 
71*5f2bebf7SJérôme Gardou 
72*5f2bebf7SJérôme Gardou #ifdef PC_HEADER
73*5f2bebf7SJérôme Gardou #include "all.h"
74*5f2bebf7SJérôme Gardou #else
75*5f2bebf7SJérôme Gardou #include <assert.h>
76*5f2bebf7SJérôme Gardou #include <float.h>
77*5f2bebf7SJérôme Gardou #include <math.h>
78*5f2bebf7SJérôme Gardou #include <stdlib.h>
79*5f2bebf7SJérôme Gardou #include "context.h"
80*5f2bebf7SJérôme Gardou #include "light.h"
81*5f2bebf7SJérôme Gardou #include "dlist.h"
82*5f2bebf7SJérôme Gardou #include "macros.h"
83*5f2bebf7SJérôme Gardou #include "matrix.h"
84*5f2bebf7SJérôme Gardou #include "mmath.h"
85*5f2bebf7SJérôme Gardou #include "types.h"
86*5f2bebf7SJérôme Gardou #include "vb.h"
87*5f2bebf7SJérôme Gardou #include "xform.h"
88*5f2bebf7SJérôme Gardou #endif
89*5f2bebf7SJérôme Gardou 
90*5f2bebf7SJérôme Gardou 
91*5f2bebf7SJérôme Gardou 
gl_ShadeModel(GLcontext * ctx,GLenum mode)92*5f2bebf7SJérôme Gardou void gl_ShadeModel( GLcontext *ctx, GLenum mode )
93*5f2bebf7SJérôme Gardou {
94*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
95*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glShadeModel" );
96*5f2bebf7SJérôme Gardou       return;
97*5f2bebf7SJérôme Gardou    }
98*5f2bebf7SJérôme Gardou 
99*5f2bebf7SJérôme Gardou    switch (mode) {
100*5f2bebf7SJérôme Gardou       case GL_FLAT:
101*5f2bebf7SJérôme Gardou       case GL_SMOOTH:
102*5f2bebf7SJérôme Gardou          if (ctx->Light.ShadeModel!=mode) {
103*5f2bebf7SJérôme Gardou             ctx->Light.ShadeModel = mode;
104*5f2bebf7SJérôme Gardou             ctx->NewState |= NEW_RASTER_OPS;
105*5f2bebf7SJérôme Gardou          }
106*5f2bebf7SJérôme Gardou          break;
107*5f2bebf7SJérôme Gardou       default:
108*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
109*5f2bebf7SJérôme Gardou    }
110*5f2bebf7SJérôme Gardou }
111*5f2bebf7SJérôme Gardou 
112*5f2bebf7SJérôme Gardou 
113*5f2bebf7SJérôme Gardou 
gl_Lightfv(GLcontext * ctx,GLenum light,GLenum pname,const GLfloat * params,GLint nparams)114*5f2bebf7SJérôme Gardou void gl_Lightfv( GLcontext *ctx,
115*5f2bebf7SJérôme Gardou                  GLenum light, GLenum pname, const GLfloat *params,
116*5f2bebf7SJérôme Gardou                  GLint nparams )
117*5f2bebf7SJérôme Gardou {
118*5f2bebf7SJérôme Gardou    GLint l;
119*5f2bebf7SJérôme Gardou 
120*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
121*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glShadeModel" );
122*5f2bebf7SJérôme Gardou       return;
123*5f2bebf7SJérôme Gardou    }
124*5f2bebf7SJérôme Gardou 
125*5f2bebf7SJérôme Gardou    l = (GLint) (light - GL_LIGHT0);
126*5f2bebf7SJérôme Gardou 
127*5f2bebf7SJérôme Gardou    if (l<0 || l>=MAX_LIGHTS) {
128*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glLight" );
129*5f2bebf7SJérôme Gardou       return;
130*5f2bebf7SJérôme Gardou    }
131*5f2bebf7SJérôme Gardou 
132*5f2bebf7SJérôme Gardou    switch (pname) {
133*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
134*5f2bebf7SJérôme Gardou          COPY_4V( ctx->Light.Light[l].Ambient, params );
135*5f2bebf7SJérôme Gardou          break;
136*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
137*5f2bebf7SJérôme Gardou          COPY_4V( ctx->Light.Light[l].Diffuse, params );
138*5f2bebf7SJérôme Gardou          break;
139*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
140*5f2bebf7SJérôme Gardou          COPY_4V( ctx->Light.Light[l].Specular, params );
141*5f2bebf7SJérôme Gardou          break;
142*5f2bebf7SJérôme Gardou       case GL_POSITION:
143*5f2bebf7SJérôme Gardou 	 /* transform position by ModelView matrix */
144*5f2bebf7SJérôme Gardou 	 TRANSFORM_POINT( ctx->Light.Light[l].Position, ctx->ModelViewMatrix,
145*5f2bebf7SJérôme Gardou                           params );
146*5f2bebf7SJérôme Gardou          break;
147*5f2bebf7SJérôme Gardou       case GL_SPOT_DIRECTION:
148*5f2bebf7SJérôme Gardou 	 /* transform direction by inverse modelview */
149*5f2bebf7SJérôme Gardou          {
150*5f2bebf7SJérôme Gardou             GLfloat direction[4];
151*5f2bebf7SJérôme Gardou             direction[0] = params[0];
152*5f2bebf7SJérôme Gardou             direction[1] = params[1];
153*5f2bebf7SJérôme Gardou             direction[2] = params[2];
154*5f2bebf7SJérôme Gardou             direction[3] = 0.0;
155*5f2bebf7SJérôme Gardou             if (ctx->NewModelViewMatrix) {
156*5f2bebf7SJérôme Gardou                gl_analyze_modelview_matrix( ctx );
157*5f2bebf7SJérôme Gardou             }
158*5f2bebf7SJérôme Gardou             gl_transform_vector( ctx->Light.Light[l].Direction,
159*5f2bebf7SJérôme Gardou                                  direction, ctx->ModelViewInv);
160*5f2bebf7SJérôme Gardou          }
161*5f2bebf7SJérôme Gardou          break;
162*5f2bebf7SJérôme Gardou       case GL_SPOT_EXPONENT:
163*5f2bebf7SJérôme Gardou          if (params[0]<0.0 || params[0]>128.0) {
164*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
165*5f2bebf7SJérôme Gardou             return;
166*5f2bebf7SJérôme Gardou          }
167*5f2bebf7SJérôme Gardou          if (ctx->Light.Light[l].SpotExponent != params[0]) {
168*5f2bebf7SJérôme Gardou             ctx->Light.Light[l].SpotExponent = params[0];
169*5f2bebf7SJérôme Gardou             gl_compute_spot_exp_table( &ctx->Light.Light[l] );
170*5f2bebf7SJérôme Gardou          }
171*5f2bebf7SJérôme Gardou          break;
172*5f2bebf7SJérôme Gardou       case GL_SPOT_CUTOFF:
173*5f2bebf7SJérôme Gardou          if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
174*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
175*5f2bebf7SJérôme Gardou             return;
176*5f2bebf7SJérôme Gardou          }
177*5f2bebf7SJérôme Gardou          ctx->Light.Light[l].SpotCutoff = params[0];
178*5f2bebf7SJérôme Gardou          ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
179*5f2bebf7SJérôme Gardou          break;
180*5f2bebf7SJérôme Gardou       case GL_CONSTANT_ATTENUATION:
181*5f2bebf7SJérôme Gardou          if (params[0]<0.0) {
182*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
183*5f2bebf7SJérôme Gardou             return;
184*5f2bebf7SJérôme Gardou          }
185*5f2bebf7SJérôme Gardou          ctx->Light.Light[l].ConstantAttenuation = params[0];
186*5f2bebf7SJérôme Gardou          break;
187*5f2bebf7SJérôme Gardou       case GL_LINEAR_ATTENUATION:
188*5f2bebf7SJérôme Gardou          if (params[0]<0.0) {
189*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
190*5f2bebf7SJérôme Gardou             return;
191*5f2bebf7SJérôme Gardou          }
192*5f2bebf7SJérôme Gardou          ctx->Light.Light[l].LinearAttenuation = params[0];
193*5f2bebf7SJérôme Gardou          break;
194*5f2bebf7SJérôme Gardou       case GL_QUADRATIC_ATTENUATION:
195*5f2bebf7SJérôme Gardou          if (params[0]<0.0) {
196*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
197*5f2bebf7SJérôme Gardou             return;
198*5f2bebf7SJérôme Gardou          }
199*5f2bebf7SJérôme Gardou          ctx->Light.Light[l].QuadraticAttenuation = params[0];
200*5f2bebf7SJérôme Gardou          break;
201*5f2bebf7SJérôme Gardou       default:
202*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glLight" );
203*5f2bebf7SJérôme Gardou          break;
204*5f2bebf7SJérôme Gardou    }
205*5f2bebf7SJérôme Gardou 
206*5f2bebf7SJérôme Gardou    ctx->NewState |= NEW_LIGHTING;
207*5f2bebf7SJérôme Gardou }
208*5f2bebf7SJérôme Gardou 
209*5f2bebf7SJérôme Gardou 
210*5f2bebf7SJérôme Gardou 
gl_GetLightfv(GLcontext * ctx,GLenum light,GLenum pname,GLfloat * params)211*5f2bebf7SJérôme Gardou void gl_GetLightfv( GLcontext *ctx,
212*5f2bebf7SJérôme Gardou                     GLenum light, GLenum pname, GLfloat *params )
213*5f2bebf7SJérôme Gardou {
214*5f2bebf7SJérôme Gardou    GLint l = (GLint) (light - GL_LIGHT0);
215*5f2bebf7SJérôme Gardou 
216*5f2bebf7SJérôme Gardou    if (l<0 || l>=MAX_LIGHTS) {
217*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
218*5f2bebf7SJérôme Gardou       return;
219*5f2bebf7SJérôme Gardou    }
220*5f2bebf7SJérôme Gardou 
221*5f2bebf7SJérôme Gardou    switch (pname) {
222*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
223*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Light[l].Ambient );
224*5f2bebf7SJérôme Gardou          break;
225*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
226*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Light[l].Diffuse );
227*5f2bebf7SJérôme Gardou          break;
228*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
229*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Light[l].Specular );
230*5f2bebf7SJérôme Gardou          break;
231*5f2bebf7SJérôme Gardou       case GL_POSITION:
232*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Light[l].Position );
233*5f2bebf7SJérôme Gardou          break;
234*5f2bebf7SJérôme Gardou       case GL_SPOT_DIRECTION:
235*5f2bebf7SJérôme Gardou          COPY_3V( params, ctx->Light.Light[l].Direction );
236*5f2bebf7SJérôme Gardou          break;
237*5f2bebf7SJérôme Gardou       case GL_SPOT_EXPONENT:
238*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].SpotExponent;
239*5f2bebf7SJérôme Gardou          break;
240*5f2bebf7SJérôme Gardou       case GL_SPOT_CUTOFF:
241*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].SpotCutoff;
242*5f2bebf7SJérôme Gardou          break;
243*5f2bebf7SJérôme Gardou       case GL_CONSTANT_ATTENUATION:
244*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].ConstantAttenuation;
245*5f2bebf7SJérôme Gardou          break;
246*5f2bebf7SJérôme Gardou       case GL_LINEAR_ATTENUATION:
247*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].LinearAttenuation;
248*5f2bebf7SJérôme Gardou          break;
249*5f2bebf7SJérôme Gardou       case GL_QUADRATIC_ATTENUATION:
250*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
251*5f2bebf7SJérôme Gardou          break;
252*5f2bebf7SJérôme Gardou       default:
253*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
254*5f2bebf7SJérôme Gardou          break;
255*5f2bebf7SJérôme Gardou    }
256*5f2bebf7SJérôme Gardou }
257*5f2bebf7SJérôme Gardou 
258*5f2bebf7SJérôme Gardou 
259*5f2bebf7SJérôme Gardou 
gl_GetLightiv(GLcontext * ctx,GLenum light,GLenum pname,GLint * params)260*5f2bebf7SJérôme Gardou void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
261*5f2bebf7SJérôme Gardou {
262*5f2bebf7SJérôme Gardou    GLint l = (GLint) (light - GL_LIGHT0);
263*5f2bebf7SJérôme Gardou 
264*5f2bebf7SJérôme Gardou    if (l<0 || l>=MAX_LIGHTS) {
265*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
266*5f2bebf7SJérôme Gardou       return;
267*5f2bebf7SJérôme Gardou    }
268*5f2bebf7SJérôme Gardou 
269*5f2bebf7SJérôme Gardou    switch (pname) {
270*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
271*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
272*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
273*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
274*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
275*5f2bebf7SJérôme Gardou          break;
276*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
277*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
278*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
279*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
280*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
281*5f2bebf7SJérôme Gardou          break;
282*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
283*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
284*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
285*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
286*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
287*5f2bebf7SJérôme Gardou          break;
288*5f2bebf7SJérôme Gardou       case GL_POSITION:
289*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].Position[0];
290*5f2bebf7SJérôme Gardou          params[1] = ctx->Light.Light[l].Position[1];
291*5f2bebf7SJérôme Gardou          params[2] = ctx->Light.Light[l].Position[2];
292*5f2bebf7SJérôme Gardou          params[3] = ctx->Light.Light[l].Position[3];
293*5f2bebf7SJérôme Gardou          break;
294*5f2bebf7SJérôme Gardou       case GL_SPOT_DIRECTION:
295*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].Direction[0];
296*5f2bebf7SJérôme Gardou          params[1] = ctx->Light.Light[l].Direction[1];
297*5f2bebf7SJérôme Gardou          params[2] = ctx->Light.Light[l].Direction[2];
298*5f2bebf7SJérôme Gardou          break;
299*5f2bebf7SJérôme Gardou       case GL_SPOT_EXPONENT:
300*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].SpotExponent;
301*5f2bebf7SJérôme Gardou          break;
302*5f2bebf7SJérôme Gardou       case GL_SPOT_CUTOFF:
303*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].SpotCutoff;
304*5f2bebf7SJérôme Gardou          break;
305*5f2bebf7SJérôme Gardou       case GL_CONSTANT_ATTENUATION:
306*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].ConstantAttenuation;
307*5f2bebf7SJérôme Gardou          break;
308*5f2bebf7SJérôme Gardou       case GL_LINEAR_ATTENUATION:
309*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].LinearAttenuation;
310*5f2bebf7SJérôme Gardou          break;
311*5f2bebf7SJérôme Gardou       case GL_QUADRATIC_ATTENUATION:
312*5f2bebf7SJérôme Gardou          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
313*5f2bebf7SJérôme Gardou          break;
314*5f2bebf7SJérôme Gardou       default:
315*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
316*5f2bebf7SJérôme Gardou          break;
317*5f2bebf7SJérôme Gardou    }
318*5f2bebf7SJérôme Gardou }
319*5f2bebf7SJérôme Gardou 
320*5f2bebf7SJérôme Gardou 
321*5f2bebf7SJérôme Gardou 
322*5f2bebf7SJérôme Gardou /**********************************************************************/
323*5f2bebf7SJérôme Gardou /***                        Light Model                             ***/
324*5f2bebf7SJérôme Gardou /**********************************************************************/
325*5f2bebf7SJérôme Gardou 
326*5f2bebf7SJérôme Gardou 
gl_LightModelfv(GLcontext * ctx,GLenum pname,const GLfloat * params)327*5f2bebf7SJérôme Gardou void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
328*5f2bebf7SJérôme Gardou {
329*5f2bebf7SJérôme Gardou    switch (pname) {
330*5f2bebf7SJérôme Gardou       case GL_LIGHT_MODEL_AMBIENT:
331*5f2bebf7SJérôme Gardou          COPY_4V( ctx->Light.Model.Ambient, params );
332*5f2bebf7SJérôme Gardou          break;
333*5f2bebf7SJérôme Gardou       case GL_LIGHT_MODEL_LOCAL_VIEWER:
334*5f2bebf7SJérôme Gardou          if (params[0]==0.0)
335*5f2bebf7SJérôme Gardou             ctx->Light.Model.LocalViewer = GL_FALSE;
336*5f2bebf7SJérôme Gardou          else
337*5f2bebf7SJérôme Gardou             ctx->Light.Model.LocalViewer = GL_TRUE;
338*5f2bebf7SJérôme Gardou          break;
339*5f2bebf7SJérôme Gardou       case GL_LIGHT_MODEL_TWO_SIDE:
340*5f2bebf7SJérôme Gardou          if (params[0]==0.0)
341*5f2bebf7SJérôme Gardou             ctx->Light.Model.TwoSide = GL_FALSE;
342*5f2bebf7SJérôme Gardou          else
343*5f2bebf7SJérôme Gardou             ctx->Light.Model.TwoSide = GL_TRUE;
344*5f2bebf7SJérôme Gardou          break;
345*5f2bebf7SJérôme Gardou       default:
346*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
347*5f2bebf7SJérôme Gardou          break;
348*5f2bebf7SJérôme Gardou    }
349*5f2bebf7SJérôme Gardou    ctx->NewState |= NEW_LIGHTING;
350*5f2bebf7SJérôme Gardou }
351*5f2bebf7SJérôme Gardou 
352*5f2bebf7SJérôme Gardou 
353*5f2bebf7SJérôme Gardou 
354*5f2bebf7SJérôme Gardou 
355*5f2bebf7SJérôme Gardou /********** MATERIAL **********/
356*5f2bebf7SJérôme Gardou 
357*5f2bebf7SJérôme Gardou 
358*5f2bebf7SJérôme Gardou /*
359*5f2bebf7SJérôme Gardou  * Given a face and pname value (ala glColorMaterial), compute a bitmask
360*5f2bebf7SJérôme Gardou  * of the targeted material values.
361*5f2bebf7SJérôme Gardou  */
gl_material_bitmask(GLenum face,GLenum pname)362*5f2bebf7SJérôme Gardou GLuint gl_material_bitmask( GLenum face, GLenum pname )
363*5f2bebf7SJérôme Gardou {
364*5f2bebf7SJérôme Gardou    GLuint bitmask = 0;
365*5f2bebf7SJérôme Gardou 
366*5f2bebf7SJérôme Gardou    /* Make a bitmask indicating what material attribute(s) we're updating */
367*5f2bebf7SJérôme Gardou    switch (pname) {
368*5f2bebf7SJérôme Gardou       case GL_EMISSION:
369*5f2bebf7SJérôme Gardou          bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
370*5f2bebf7SJérôme Gardou          break;
371*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
372*5f2bebf7SJérôme Gardou          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
373*5f2bebf7SJérôme Gardou          break;
374*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
375*5f2bebf7SJérôme Gardou          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
376*5f2bebf7SJérôme Gardou          break;
377*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
378*5f2bebf7SJérôme Gardou          bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
379*5f2bebf7SJérôme Gardou          break;
380*5f2bebf7SJérôme Gardou       case GL_SHININESS:
381*5f2bebf7SJérôme Gardou          bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
382*5f2bebf7SJérôme Gardou          break;
383*5f2bebf7SJérôme Gardou       case GL_AMBIENT_AND_DIFFUSE:
384*5f2bebf7SJérôme Gardou          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
385*5f2bebf7SJérôme Gardou          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
386*5f2bebf7SJérôme Gardou          break;
387*5f2bebf7SJérôme Gardou       case GL_COLOR_INDEXES:
388*5f2bebf7SJérôme Gardou          bitmask |= FRONT_INDEXES_BIT  | BACK_INDEXES_BIT;
389*5f2bebf7SJérôme Gardou          break;
390*5f2bebf7SJérôme Gardou       default:
391*5f2bebf7SJérôme Gardou          gl_problem(NULL, "Bad param in gl_material_bitmask");
392*5f2bebf7SJérôme Gardou          return 0;
393*5f2bebf7SJérôme Gardou    }
394*5f2bebf7SJérôme Gardou 
395*5f2bebf7SJérôme Gardou    ASSERT( face==GL_FRONT || face==GL_BACK || face==GL_FRONT_AND_BACK );
396*5f2bebf7SJérôme Gardou 
397*5f2bebf7SJérôme Gardou    if (face==GL_FRONT) {
398*5f2bebf7SJérôme Gardou       bitmask &= FRONT_MATERIAL_BITS;
399*5f2bebf7SJérôme Gardou    }
400*5f2bebf7SJérôme Gardou    else if (face==GL_BACK) {
401*5f2bebf7SJérôme Gardou       bitmask &= BACK_MATERIAL_BITS;
402*5f2bebf7SJérôme Gardou    }
403*5f2bebf7SJérôme Gardou 
404*5f2bebf7SJérôme Gardou    return bitmask;
405*5f2bebf7SJérôme Gardou }
406*5f2bebf7SJérôme Gardou 
407*5f2bebf7SJérôme Gardou 
408*5f2bebf7SJérôme Gardou 
409*5f2bebf7SJérôme Gardou /*
410*5f2bebf7SJérôme Gardou  * This is called by glColor() when GL_COLOR_MATERIAL is enabled and
411*5f2bebf7SJérôme Gardou  * called by glMaterial() when GL_COLOR_MATERIAL is disabled.
412*5f2bebf7SJérôme Gardou  */
gl_set_material(GLcontext * ctx,GLuint bitmask,const GLfloat * params)413*5f2bebf7SJérôme Gardou void gl_set_material( GLcontext *ctx, GLuint bitmask, const GLfloat *params )
414*5f2bebf7SJérôme Gardou {
415*5f2bebf7SJérôme Gardou    struct gl_material *mat;
416*5f2bebf7SJérôme Gardou 
417*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
418*5f2bebf7SJérôme Gardou       struct vertex_buffer *VB = ctx->VB;
419*5f2bebf7SJérôme Gardou       /* Save per-vertex material changes in the Vertex Buffer.
420*5f2bebf7SJérôme Gardou        * The update_material function will eventually update the global
421*5f2bebf7SJérôme Gardou        * ctx->Light.Material values.
422*5f2bebf7SJérôme Gardou        */
423*5f2bebf7SJérôme Gardou       mat = VB->Material[VB->Count];
424*5f2bebf7SJérôme Gardou       VB->MaterialMask[VB->Count] |= bitmask;
425*5f2bebf7SJérôme Gardou       VB->MonoMaterial = GL_FALSE;
426*5f2bebf7SJérôme Gardou    }
427*5f2bebf7SJérôme Gardou    else {
428*5f2bebf7SJérôme Gardou       /* just update the global material property */
429*5f2bebf7SJérôme Gardou       mat = ctx->Light.Material;
430*5f2bebf7SJérôme Gardou       ctx->NewState |= NEW_LIGHTING;
431*5f2bebf7SJérôme Gardou    }
432*5f2bebf7SJérôme Gardou 
433*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_AMBIENT_BIT) {
434*5f2bebf7SJérôme Gardou       COPY_4V( mat[0].Ambient, params );
435*5f2bebf7SJérôme Gardou    }
436*5f2bebf7SJérôme Gardou    if (bitmask & BACK_AMBIENT_BIT) {
437*5f2bebf7SJérôme Gardou       COPY_4V( mat[1].Ambient, params );
438*5f2bebf7SJérôme Gardou    }
439*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_DIFFUSE_BIT) {
440*5f2bebf7SJérôme Gardou       COPY_4V( mat[0].Diffuse, params );
441*5f2bebf7SJérôme Gardou    }
442*5f2bebf7SJérôme Gardou    if (bitmask & BACK_DIFFUSE_BIT) {
443*5f2bebf7SJérôme Gardou       COPY_4V( mat[1].Diffuse, params );
444*5f2bebf7SJérôme Gardou    }
445*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_SPECULAR_BIT) {
446*5f2bebf7SJérôme Gardou       COPY_4V( mat[0].Specular, params );
447*5f2bebf7SJérôme Gardou    }
448*5f2bebf7SJérôme Gardou    if (bitmask & BACK_SPECULAR_BIT) {
449*5f2bebf7SJérôme Gardou       COPY_4V( mat[1].Specular, params );
450*5f2bebf7SJérôme Gardou    }
451*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_EMISSION_BIT) {
452*5f2bebf7SJérôme Gardou       COPY_4V( mat[0].Emission, params );
453*5f2bebf7SJérôme Gardou    }
454*5f2bebf7SJérôme Gardou    if (bitmask & BACK_EMISSION_BIT) {
455*5f2bebf7SJérôme Gardou       COPY_4V( mat[1].Emission, params );
456*5f2bebf7SJérôme Gardou    }
457*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_SHININESS_BIT) {
458*5f2bebf7SJérôme Gardou       GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
459*5f2bebf7SJérôme Gardou       if (mat[0].Shininess != shininess) {
460*5f2bebf7SJérôme Gardou          mat[0].Shininess = shininess;
461*5f2bebf7SJérôme Gardou          gl_compute_material_shine_table( &mat[0] );
462*5f2bebf7SJérôme Gardou       }
463*5f2bebf7SJérôme Gardou    }
464*5f2bebf7SJérôme Gardou    if (bitmask & BACK_SHININESS_BIT) {
465*5f2bebf7SJérôme Gardou       GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
466*5f2bebf7SJérôme Gardou       if (mat[1].Shininess != shininess) {
467*5f2bebf7SJérôme Gardou          mat[1].Shininess = shininess;
468*5f2bebf7SJérôme Gardou          gl_compute_material_shine_table( &mat[1] );
469*5f2bebf7SJérôme Gardou       }
470*5f2bebf7SJérôme Gardou    }
471*5f2bebf7SJérôme Gardou    if (bitmask & FRONT_INDEXES_BIT) {
472*5f2bebf7SJérôme Gardou       mat[0].AmbientIndex = params[0];
473*5f2bebf7SJérôme Gardou       mat[0].DiffuseIndex = params[1];
474*5f2bebf7SJérôme Gardou       mat[0].SpecularIndex = params[2];
475*5f2bebf7SJérôme Gardou    }
476*5f2bebf7SJérôme Gardou    if (bitmask & BACK_INDEXES_BIT) {
477*5f2bebf7SJérôme Gardou       mat[1].AmbientIndex = params[0];
478*5f2bebf7SJérôme Gardou       mat[1].DiffuseIndex = params[1];
479*5f2bebf7SJérôme Gardou       mat[1].SpecularIndex = params[2];
480*5f2bebf7SJérôme Gardou    }
481*5f2bebf7SJérôme Gardou }
482*5f2bebf7SJérôme Gardou 
483*5f2bebf7SJérôme Gardou 
484*5f2bebf7SJérôme Gardou 
gl_ColorMaterial(GLcontext * ctx,GLenum face,GLenum mode)485*5f2bebf7SJérôme Gardou void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
486*5f2bebf7SJérôme Gardou {
487*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
488*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glColorMaterial" );
489*5f2bebf7SJérôme Gardou       return;
490*5f2bebf7SJérôme Gardou    }
491*5f2bebf7SJérôme Gardou    switch (face) {
492*5f2bebf7SJérôme Gardou       case GL_FRONT:
493*5f2bebf7SJérôme Gardou       case GL_BACK:
494*5f2bebf7SJérôme Gardou       case GL_FRONT_AND_BACK:
495*5f2bebf7SJérôme Gardou          ctx->Light.ColorMaterialFace = face;
496*5f2bebf7SJérôme Gardou          break;
497*5f2bebf7SJérôme Gardou       default:
498*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(face)" );
499*5f2bebf7SJérôme Gardou          return;
500*5f2bebf7SJérôme Gardou    }
501*5f2bebf7SJérôme Gardou    switch (mode) {
502*5f2bebf7SJérôme Gardou       case GL_EMISSION:
503*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
504*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
505*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
506*5f2bebf7SJérôme Gardou       case GL_AMBIENT_AND_DIFFUSE:
507*5f2bebf7SJérôme Gardou          ctx->Light.ColorMaterialMode = mode;
508*5f2bebf7SJérôme Gardou          break;
509*5f2bebf7SJérôme Gardou       default:
510*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(mode)" );
511*5f2bebf7SJérôme Gardou          return;
512*5f2bebf7SJérôme Gardou    }
513*5f2bebf7SJérôme Gardou 
514*5f2bebf7SJérôme Gardou    ctx->Light.ColorMaterialBitmask = gl_material_bitmask( face, mode );
515*5f2bebf7SJérôme Gardou }
516*5f2bebf7SJérôme Gardou 
517*5f2bebf7SJérôme Gardou 
518*5f2bebf7SJérôme Gardou 
519*5f2bebf7SJérôme Gardou /*
520*5f2bebf7SJérôme Gardou  * This is only called via the api_function_table struct or by the
521*5f2bebf7SJérôme Gardou  * display list executor.
522*5f2bebf7SJérôme Gardou  */
gl_Materialfv(GLcontext * ctx,GLenum face,GLenum pname,const GLfloat * params)523*5f2bebf7SJérôme Gardou void gl_Materialfv( GLcontext *ctx,
524*5f2bebf7SJérôme Gardou                     GLenum face, GLenum pname, const GLfloat *params )
525*5f2bebf7SJérôme Gardou {
526*5f2bebf7SJérôme Gardou    GLuint bitmask;
527*5f2bebf7SJérôme Gardou 
528*5f2bebf7SJérôme Gardou    /* error checking */
529*5f2bebf7SJérôme Gardou    if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
530*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glMaterial(face)" );
531*5f2bebf7SJérôme Gardou       return;
532*5f2bebf7SJérôme Gardou    }
533*5f2bebf7SJérôme Gardou    switch (pname) {
534*5f2bebf7SJérôme Gardou       case GL_EMISSION:
535*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
536*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
537*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
538*5f2bebf7SJérôme Gardou       case GL_SHININESS:
539*5f2bebf7SJérôme Gardou       case GL_AMBIENT_AND_DIFFUSE:
540*5f2bebf7SJérôme Gardou       case GL_COLOR_INDEXES:
541*5f2bebf7SJérôme Gardou          /* OK */
542*5f2bebf7SJérôme Gardou          break;
543*5f2bebf7SJérôme Gardou       default:
544*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glMaterial(pname)" );
545*5f2bebf7SJérôme Gardou          return;
546*5f2bebf7SJérôme Gardou    }
547*5f2bebf7SJérôme Gardou 
548*5f2bebf7SJérôme Gardou    /* convert face and pname to a bitmask */
549*5f2bebf7SJérôme Gardou    bitmask = gl_material_bitmask( face, pname );
550*5f2bebf7SJérôme Gardou 
551*5f2bebf7SJérôme Gardou    if (ctx->Light.ColorMaterialEnabled) {
552*5f2bebf7SJérôme Gardou       /* The material values specified by glColorMaterial() can't be */
553*5f2bebf7SJérôme Gardou       /* updated by glMaterial() while GL_COLOR_MATERIAL is enabled! */
554*5f2bebf7SJérôme Gardou       bitmask &= ~ctx->Light.ColorMaterialBitmask;
555*5f2bebf7SJérôme Gardou    }
556*5f2bebf7SJérôme Gardou 
557*5f2bebf7SJérôme Gardou    gl_set_material( ctx, bitmask, params );
558*5f2bebf7SJérôme Gardou }
559*5f2bebf7SJérôme Gardou 
560*5f2bebf7SJérôme Gardou 
561*5f2bebf7SJérôme Gardou 
562*5f2bebf7SJérôme Gardou 
gl_GetMaterialfv(GLcontext * ctx,GLenum face,GLenum pname,GLfloat * params)563*5f2bebf7SJérôme Gardou void gl_GetMaterialfv( GLcontext *ctx,
564*5f2bebf7SJérôme Gardou                        GLenum face, GLenum pname, GLfloat *params )
565*5f2bebf7SJérôme Gardou {
566*5f2bebf7SJérôme Gardou    GLuint f;
567*5f2bebf7SJérôme Gardou 
568*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
569*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialfv" );
570*5f2bebf7SJérôme Gardou       return;
571*5f2bebf7SJérôme Gardou    }
572*5f2bebf7SJérôme Gardou    if (face==GL_FRONT) {
573*5f2bebf7SJérôme Gardou       f = 0;
574*5f2bebf7SJérôme Gardou    }
575*5f2bebf7SJérôme Gardou    else if (face==GL_BACK) {
576*5f2bebf7SJérôme Gardou       f = 1;
577*5f2bebf7SJérôme Gardou    }
578*5f2bebf7SJérôme Gardou    else {
579*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
580*5f2bebf7SJérôme Gardou       return;
581*5f2bebf7SJérôme Gardou    }
582*5f2bebf7SJérôme Gardou    switch (pname) {
583*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
584*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Material[f].Ambient );
585*5f2bebf7SJérôme Gardou          break;
586*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
587*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Material[f].Diffuse );
588*5f2bebf7SJérôme Gardou 	 break;
589*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
590*5f2bebf7SJérôme Gardou          COPY_4V( params, ctx->Light.Material[f].Specular );
591*5f2bebf7SJérôme Gardou 	 break;
592*5f2bebf7SJérôme Gardou       case GL_EMISSION:
593*5f2bebf7SJérôme Gardou 	 COPY_4V( params, ctx->Light.Material[f].Emission );
594*5f2bebf7SJérôme Gardou 	 break;
595*5f2bebf7SJérôme Gardou       case GL_SHININESS:
596*5f2bebf7SJérôme Gardou 	 *params = ctx->Light.Material[f].Shininess;
597*5f2bebf7SJérôme Gardou 	 break;
598*5f2bebf7SJérôme Gardou       case GL_COLOR_INDEXES:
599*5f2bebf7SJérôme Gardou 	 params[0] = ctx->Light.Material[f].AmbientIndex;
600*5f2bebf7SJérôme Gardou 	 params[1] = ctx->Light.Material[f].DiffuseIndex;
601*5f2bebf7SJérôme Gardou 	 params[2] = ctx->Light.Material[f].SpecularIndex;
602*5f2bebf7SJérôme Gardou 	 break;
603*5f2bebf7SJérôme Gardou       default:
604*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
605*5f2bebf7SJérôme Gardou    }
606*5f2bebf7SJérôme Gardou }
607*5f2bebf7SJérôme Gardou 
608*5f2bebf7SJérôme Gardou 
609*5f2bebf7SJérôme Gardou 
gl_GetMaterialiv(GLcontext * ctx,GLenum face,GLenum pname,GLint * params)610*5f2bebf7SJérôme Gardou void gl_GetMaterialiv( GLcontext *ctx,
611*5f2bebf7SJérôme Gardou                        GLenum face, GLenum pname, GLint *params )
612*5f2bebf7SJérôme Gardou {
613*5f2bebf7SJérôme Gardou    GLuint f;
614*5f2bebf7SJérôme Gardou 
615*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
616*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialiv" );
617*5f2bebf7SJérôme Gardou       return;
618*5f2bebf7SJérôme Gardou    }
619*5f2bebf7SJérôme Gardou    if (face==GL_FRONT) {
620*5f2bebf7SJérôme Gardou       f = 0;
621*5f2bebf7SJérôme Gardou    }
622*5f2bebf7SJérôme Gardou    else if (face==GL_BACK) {
623*5f2bebf7SJérôme Gardou       f = 1;
624*5f2bebf7SJérôme Gardou    }
625*5f2bebf7SJérôme Gardou    else {
626*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
627*5f2bebf7SJérôme Gardou       return;
628*5f2bebf7SJérôme Gardou    }
629*5f2bebf7SJérôme Gardou    switch (pname) {
630*5f2bebf7SJérôme Gardou       case GL_AMBIENT:
631*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
632*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
633*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
634*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
635*5f2bebf7SJérôme Gardou          break;
636*5f2bebf7SJérôme Gardou       case GL_DIFFUSE:
637*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
638*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
639*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
640*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
641*5f2bebf7SJérôme Gardou 	 break;
642*5f2bebf7SJérôme Gardou       case GL_SPECULAR:
643*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
644*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
645*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
646*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
647*5f2bebf7SJérôme Gardou 	 break;
648*5f2bebf7SJérôme Gardou       case GL_EMISSION:
649*5f2bebf7SJérôme Gardou          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
650*5f2bebf7SJérôme Gardou          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
651*5f2bebf7SJérôme Gardou          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
652*5f2bebf7SJérôme Gardou          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
653*5f2bebf7SJérôme Gardou 	 break;
654*5f2bebf7SJérôme Gardou       case GL_SHININESS:
655*5f2bebf7SJérôme Gardou          *params = ROUNDF( ctx->Light.Material[f].Shininess );
656*5f2bebf7SJérôme Gardou 	 break;
657*5f2bebf7SJérôme Gardou       case GL_COLOR_INDEXES:
658*5f2bebf7SJérôme Gardou 	 params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
659*5f2bebf7SJérôme Gardou 	 params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
660*5f2bebf7SJérôme Gardou 	 params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
661*5f2bebf7SJérôme Gardou 	 break;
662*5f2bebf7SJérôme Gardou       default:
663*5f2bebf7SJérôme Gardou          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
664*5f2bebf7SJérôme Gardou    }
665*5f2bebf7SJérôme Gardou }
666*5f2bebf7SJérôme Gardou 
667*5f2bebf7SJérôme Gardou 
668*5f2bebf7SJérôme Gardou 
669*5f2bebf7SJérôme Gardou 
670*5f2bebf7SJérôme Gardou /**********************************************************************/
671*5f2bebf7SJérôme Gardou /*****                  Lighting computation                      *****/
672*5f2bebf7SJérôme Gardou /**********************************************************************/
673*5f2bebf7SJérôme Gardou 
674*5f2bebf7SJérôme Gardou 
675*5f2bebf7SJérôme Gardou /*
676*5f2bebf7SJérôme Gardou  * Notes:
677*5f2bebf7SJérôme Gardou  *   When two-sided lighting is enabled we compute the color (or index)
678*5f2bebf7SJérôme Gardou  *   for both the front and back side of the primitive.  Then, when the
679*5f2bebf7SJérôme Gardou  *   orientation of the facet is later learned, we can determine which
680*5f2bebf7SJérôme Gardou  *   color (or index) to use for rendering.
681*5f2bebf7SJérôme Gardou  *
682*5f2bebf7SJérôme Gardou  * Variables:
683*5f2bebf7SJérôme Gardou  *   n = normal vector
684*5f2bebf7SJérôme Gardou  *   V = vertex position
685*5f2bebf7SJérôme Gardou  *   P = light source position
686*5f2bebf7SJérôme Gardou  *   Pe = (0,0,0,1)
687*5f2bebf7SJérôme Gardou  *
688*5f2bebf7SJérôme Gardou  * Precomputed:
689*5f2bebf7SJérôme Gardou  *   IF P[3]==0 THEN
690*5f2bebf7SJérôme Gardou  *       // light at infinity
691*5f2bebf7SJérôme Gardou  *       IF local_viewer THEN
692*5f2bebf7SJérôme Gardou  *           VP_inf_norm = unit vector from V to P      // Precompute
693*5f2bebf7SJérôme Gardou  *       ELSE
694*5f2bebf7SJérôme Gardou  *           // eye at infinity
695*5f2bebf7SJérôme Gardou  *           h_inf_norm = Normalize( VP + <0,0,1> )     // Precompute
696*5f2bebf7SJérôme Gardou  *       ENDIF
697*5f2bebf7SJérôme Gardou  *   ENDIF
698*5f2bebf7SJérôme Gardou  *
699*5f2bebf7SJérôme Gardou  * Functions:
700*5f2bebf7SJérôme Gardou  *   Normalize( v ) = normalized vector v
701*5f2bebf7SJérôme Gardou  *   Magnitude( v ) = length of vector v
702*5f2bebf7SJérôme Gardou  */
703*5f2bebf7SJérôme Gardou 
704*5f2bebf7SJérôme Gardou 
705*5f2bebf7SJérôme Gardou 
706*5f2bebf7SJérôme Gardou /*
707*5f2bebf7SJérôme Gardou  * Whenever the spotlight exponent for a light changes we must call
708*5f2bebf7SJérôme Gardou  * this function to recompute the exponent lookup table.
709*5f2bebf7SJérôme Gardou  */
gl_compute_spot_exp_table(struct gl_light * l)710*5f2bebf7SJérôme Gardou void gl_compute_spot_exp_table( struct gl_light *l )
711*5f2bebf7SJérôme Gardou {
712*5f2bebf7SJérôme Gardou    int i;
713*5f2bebf7SJérôme Gardou    double exponent = l->SpotExponent;
714*5f2bebf7SJérôme Gardou    double tmp;
715*5f2bebf7SJérôme Gardou    int clamp = 0;
716*5f2bebf7SJérôme Gardou 
717*5f2bebf7SJérôme Gardou    l->SpotExpTable[0][0] = 0.0;
718*5f2bebf7SJérôme Gardou 
719*5f2bebf7SJérôme Gardou    for (i=EXP_TABLE_SIZE-1;i>0;i--) {
720*5f2bebf7SJérôme Gardou       if (clamp == 0) {
721*5f2bebf7SJérôme Gardou          tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
722*5f2bebf7SJérôme Gardou          if (tmp < FLT_MIN*100.0) {
723*5f2bebf7SJérôme Gardou             tmp = 0.0;
724*5f2bebf7SJérôme Gardou             clamp = 1;
725*5f2bebf7SJérôme Gardou          }
726*5f2bebf7SJérôme Gardou       }
727*5f2bebf7SJérôme Gardou       l->SpotExpTable[i][0] = tmp;
728*5f2bebf7SJérôme Gardou    }
729*5f2bebf7SJérôme Gardou    for (i=0;i<EXP_TABLE_SIZE-1;i++) {
730*5f2bebf7SJérôme Gardou       l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
731*5f2bebf7SJérôme Gardou    }
732*5f2bebf7SJérôme Gardou    l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
733*5f2bebf7SJérôme Gardou }
734*5f2bebf7SJérôme Gardou 
735*5f2bebf7SJérôme Gardou 
736*5f2bebf7SJérôme Gardou 
737*5f2bebf7SJérôme Gardou /*
738*5f2bebf7SJérôme Gardou  * Whenever the shininess of a material changes we must call this
739*5f2bebf7SJérôme Gardou  * function to recompute the exponential lookup table.
740*5f2bebf7SJérôme Gardou  */
gl_compute_material_shine_table(struct gl_material * m)741*5f2bebf7SJérôme Gardou void gl_compute_material_shine_table( struct gl_material *m )
742*5f2bebf7SJérôme Gardou {
743*5f2bebf7SJérôme Gardou    int i;
744*5f2bebf7SJérôme Gardou 
745*5f2bebf7SJérôme Gardou    m->ShineTable[0] = 0.0F;
746*5f2bebf7SJérôme Gardou    for (i=1;i<SHINE_TABLE_SIZE;i++) {
747*5f2bebf7SJérôme Gardou #if 0
748*5f2bebf7SJérôme Gardou       double x = pow( i/(double)(SHINE_TABLE_SIZE-1), exponent );
749*5f2bebf7SJérôme Gardou       if (x<1.0e-10) {
750*5f2bebf7SJérôme Gardou          m->ShineTable[i] = 0.0F;
751*5f2bebf7SJérôme Gardou       }
752*5f2bebf7SJérôme Gardou       else {
753*5f2bebf7SJérôme Gardou          m->ShineTable[i] = x;
754*5f2bebf7SJérôme Gardou       }
755*5f2bebf7SJérôme Gardou #else
756*5f2bebf7SJérôme Gardou       /* just invalidate the table */
757*5f2bebf7SJérôme Gardou       m->ShineTable[i] = -1.0;
758*5f2bebf7SJérôme Gardou #endif
759*5f2bebf7SJérôme Gardou    }
760*5f2bebf7SJérôme Gardou }
761*5f2bebf7SJérôme Gardou 
762*5f2bebf7SJérôme Gardou 
763*5f2bebf7SJérôme Gardou 
764*5f2bebf7SJérôme Gardou /*
765*5f2bebf7SJérôme Gardou  * Examine current lighting parameters to determine if the optimized lighting
766*5f2bebf7SJérôme Gardou  * function can be used.
767*5f2bebf7SJérôme Gardou  * Also, precompute some lighting values such as the products of light
768*5f2bebf7SJérôme Gardou  * source and material ambient, diffuse and specular coefficients.
769*5f2bebf7SJérôme Gardou  */
gl_update_lighting(GLcontext * ctx)770*5f2bebf7SJérôme Gardou void gl_update_lighting( GLcontext *ctx )
771*5f2bebf7SJérôme Gardou {
772*5f2bebf7SJérôme Gardou    GLint i, side;
773*5f2bebf7SJérôme Gardou    struct gl_light *prev_enabled, *light;
774*5f2bebf7SJérôme Gardou 
775*5f2bebf7SJérôme Gardou    if (!ctx->Light.Enabled) {
776*5f2bebf7SJérôme Gardou       /* If lighting is not enabled, we can skip all this. */
777*5f2bebf7SJérôme Gardou       return;
778*5f2bebf7SJérôme Gardou    }
779*5f2bebf7SJérôme Gardou 
780*5f2bebf7SJérôme Gardou    /* Setup linked list of enabled light sources */
781*5f2bebf7SJérôme Gardou    prev_enabled = NULL;
782*5f2bebf7SJérôme Gardou    ctx->Light.FirstEnabled = NULL;
783*5f2bebf7SJérôme Gardou    for (i=0;i<MAX_LIGHTS;i++) {
784*5f2bebf7SJérôme Gardou       ctx->Light.Light[i].NextEnabled = NULL;
785*5f2bebf7SJérôme Gardou       if (ctx->Light.Light[i].Enabled) {
786*5f2bebf7SJérôme Gardou          if (prev_enabled) {
787*5f2bebf7SJérôme Gardou             prev_enabled->NextEnabled = &ctx->Light.Light[i];
788*5f2bebf7SJérôme Gardou          }
789*5f2bebf7SJérôme Gardou          else {
790*5f2bebf7SJérôme Gardou             ctx->Light.FirstEnabled = &ctx->Light.Light[i];
791*5f2bebf7SJérôme Gardou          }
792*5f2bebf7SJérôme Gardou          prev_enabled = &ctx->Light.Light[i];
793*5f2bebf7SJérôme Gardou       }
794*5f2bebf7SJérôme Gardou    }
795*5f2bebf7SJérôme Gardou 
796*5f2bebf7SJérôme Gardou    /* base color = material_emission + global_ambient * material_ambient */
797*5f2bebf7SJérôme Gardou    for (side=0; side<2; side++) {
798*5f2bebf7SJérôme Gardou       ctx->Light.BaseColor[side][0] = ctx->Light.Material[side].Emission[0]
799*5f2bebf7SJérôme Gardou          + ctx->Light.Model.Ambient[0] * ctx->Light.Material[side].Ambient[0];
800*5f2bebf7SJérôme Gardou       ctx->Light.BaseColor[side][1] = ctx->Light.Material[side].Emission[1]
801*5f2bebf7SJérôme Gardou          + ctx->Light.Model.Ambient[1] * ctx->Light.Material[side].Ambient[1];
802*5f2bebf7SJérôme Gardou       ctx->Light.BaseColor[side][2] = ctx->Light.Material[side].Emission[2]
803*5f2bebf7SJérôme Gardou          + ctx->Light.Model.Ambient[2] * ctx->Light.Material[side].Ambient[2];
804*5f2bebf7SJérôme Gardou       ctx->Light.BaseColor[side][3]
805*5f2bebf7SJérôme Gardou          = MIN2( ctx->Light.Material[side].Diffuse[3], 1.0F );
806*5f2bebf7SJérôme Gardou    }
807*5f2bebf7SJérôme Gardou 
808*5f2bebf7SJérôme Gardou 
809*5f2bebf7SJérôme Gardou    /* Precompute some lighting stuff */
810*5f2bebf7SJérôme Gardou    for (light = ctx->Light.FirstEnabled; light; light = light->NextEnabled) {
811*5f2bebf7SJérôme Gardou       for (side=0; side<2; side++) {
812*5f2bebf7SJérôme Gardou          struct gl_material *mat = &ctx->Light.Material[side];
813*5f2bebf7SJérôme Gardou          /* Add each light's ambient component to base color */
814*5f2bebf7SJérôme Gardou          ctx->Light.BaseColor[side][0] += light->Ambient[0] * mat->Ambient[0];
815*5f2bebf7SJérôme Gardou          ctx->Light.BaseColor[side][1] += light->Ambient[1] * mat->Ambient[1];
816*5f2bebf7SJérôme Gardou          ctx->Light.BaseColor[side][2] += light->Ambient[2] * mat->Ambient[2];
817*5f2bebf7SJérôme Gardou          /* compute product of light's ambient with front material ambient */
818*5f2bebf7SJérôme Gardou          light->MatAmbient[side][0] = light->Ambient[0] * mat->Ambient[0];
819*5f2bebf7SJérôme Gardou          light->MatAmbient[side][1] = light->Ambient[1] * mat->Ambient[1];
820*5f2bebf7SJérôme Gardou          light->MatAmbient[side][2] = light->Ambient[2] * mat->Ambient[2];
821*5f2bebf7SJérôme Gardou          /* compute product of light's diffuse with front material diffuse */
822*5f2bebf7SJérôme Gardou          light->MatDiffuse[side][0] = light->Diffuse[0] * mat->Diffuse[0];
823*5f2bebf7SJérôme Gardou          light->MatDiffuse[side][1] = light->Diffuse[1] * mat->Diffuse[1];
824*5f2bebf7SJérôme Gardou          light->MatDiffuse[side][2] = light->Diffuse[2] * mat->Diffuse[2];
825*5f2bebf7SJérôme Gardou          /* compute product of light's specular with front material specular */
826*5f2bebf7SJérôme Gardou          light->MatSpecular[side][0] = light->Specular[0] * mat->Specular[0];
827*5f2bebf7SJérôme Gardou          light->MatSpecular[side][1] = light->Specular[1] * mat->Specular[1];
828*5f2bebf7SJérôme Gardou          light->MatSpecular[side][2] = light->Specular[2] * mat->Specular[2];
829*5f2bebf7SJérôme Gardou 
830*5f2bebf7SJérôme Gardou          /* VP (VP) = Normalize( Position ) */
831*5f2bebf7SJérôme Gardou          COPY_3V( light->VP_inf_norm, light->Position );
832*5f2bebf7SJérôme Gardou          NORMALIZE_3FV( light->VP_inf_norm );
833*5f2bebf7SJérôme Gardou 
834*5f2bebf7SJérôme Gardou          /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
835*5f2bebf7SJérôme Gardou          COPY_3V( light->h_inf_norm, light->VP_inf_norm );
836*5f2bebf7SJérôme Gardou          light->h_inf_norm[2] += 1.0F;
837*5f2bebf7SJérôme Gardou          NORMALIZE_3FV( light->h_inf_norm );
838*5f2bebf7SJérôme Gardou 
839*5f2bebf7SJérôme Gardou          COPY_3V( light->NormDirection, light->Direction );
840*5f2bebf7SJérôme Gardou          NORMALIZE_3FV( light->NormDirection );
841*5f2bebf7SJérôme Gardou 
842*5f2bebf7SJérôme Gardou          /* Compute color index diffuse and specular light intensities */
843*5f2bebf7SJérôme Gardou          light->dli = 0.30F * light->Diffuse[0]
844*5f2bebf7SJérôme Gardou                     + 0.59F * light->Diffuse[1]
845*5f2bebf7SJérôme Gardou                     + 0.11F * light->Diffuse[2];
846*5f2bebf7SJérôme Gardou          light->sli = 0.30F * light->Specular[0]
847*5f2bebf7SJérôme Gardou                     + 0.59F * light->Specular[1]
848*5f2bebf7SJérôme Gardou                     + 0.11F * light->Specular[2];
849*5f2bebf7SJérôme Gardou 
850*5f2bebf7SJérôme Gardou       } /* loop over materials */
851*5f2bebf7SJérôme Gardou    } /* loop over lights */
852*5f2bebf7SJérôme Gardou 
853*5f2bebf7SJérôme Gardou    /* Determine if the fast lighting function can be used */
854*5f2bebf7SJérôme Gardou    ctx->Light.Fast = GL_TRUE;
855*5f2bebf7SJérôme Gardou    if (    ctx->Light.BaseColor[0][0]<0.0F
856*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[0][1]<0.0F
857*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[0][2]<0.0F
858*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[0][3]<0.0F
859*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[1][0]<0.0F
860*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[1][1]<0.0F
861*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[1][2]<0.0F
862*5f2bebf7SJérôme Gardou         || ctx->Light.BaseColor[1][3]<0.0F
863*5f2bebf7SJérôme Gardou         || ctx->Light.Model.LocalViewer
864*5f2bebf7SJérôme Gardou         || ctx->Light.ColorMaterialEnabled) {
865*5f2bebf7SJérôme Gardou       ctx->Light.Fast = GL_FALSE;
866*5f2bebf7SJérôme Gardou    }
867*5f2bebf7SJérôme Gardou    else {
868*5f2bebf7SJérôme Gardou       for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
869*5f2bebf7SJérôme Gardou          if (   light->Position[3]!=0.0F
870*5f2bebf7SJérôme Gardou              || light->SpotCutoff!=180.0F
871*5f2bebf7SJérôme Gardou              || light->MatDiffuse[0][0]<0.0F
872*5f2bebf7SJérôme Gardou              || light->MatDiffuse[0][1]<0.0F
873*5f2bebf7SJérôme Gardou              || light->MatDiffuse[0][2]<0.0F
874*5f2bebf7SJérôme Gardou              || light->MatSpecular[0][0]<0.0F
875*5f2bebf7SJérôme Gardou              || light->MatSpecular[0][1]<0.0F
876*5f2bebf7SJérôme Gardou              || light->MatSpecular[0][2]<0.0F
877*5f2bebf7SJérôme Gardou              || light->MatDiffuse[1][0]<0.0F
878*5f2bebf7SJérôme Gardou              || light->MatDiffuse[1][1]<0.0F
879*5f2bebf7SJérôme Gardou              || light->MatDiffuse[1][2]<0.0F
880*5f2bebf7SJérôme Gardou              || light->MatSpecular[1][0]<0.0F
881*5f2bebf7SJérôme Gardou              || light->MatSpecular[1][1]<0.0F
882*5f2bebf7SJérôme Gardou              || light->MatSpecular[1][2]<0.0F) {
883*5f2bebf7SJérôme Gardou             ctx->Light.Fast = GL_FALSE;
884*5f2bebf7SJérôme Gardou             break;
885*5f2bebf7SJérôme Gardou          }
886*5f2bebf7SJérôme Gardou       }
887*5f2bebf7SJérôme Gardou    }
888*5f2bebf7SJérôme Gardou }
889