blob: 07571cd9656c3438ee563bf5061a1c0a3c569198 [file] [log] [blame]
Keith Whitwell9aff6cf2000-11-24 15:21:59 +00001/* $Id: light.c,v 1.29 2000/11/24 15:21:59 keithw Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paulba643a22000-10-28 18:34:48 +00005 * Version: 3.5
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00006 *
Brian Paul16a9efe2000-01-13 00:29:02 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00008 *
jtgafb833d1999-08-19 00:55:39 +00009 * 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:
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000015 *
jtgafb833d1999-08-19 00:55:39 +000016 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000018 *
jtgafb833d1999-08-19 00:55:39 +000019 * 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.
25 */
26
27
jtgafb833d1999-08-19 00:55:39 +000028#ifdef PC_HEADER
29#include "all.h"
30#else
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
Brian Paulc893a012000-10-28 20:41:13 +000032#include "colormac.h"
jtgafb833d1999-08-19 00:55:39 +000033#include "context.h"
34#include "enums.h"
35#include "light.h"
36#include "macros.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000037#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000038#include "mmath.h"
39#include "simple_list.h"
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000040#include "mtypes.h"
Keith Whitwell23caf202000-11-16 21:05:34 +000041
42#include "math/m_xform.h"
43#include "math/m_matrix.h"
jtgafb833d1999-08-19 00:55:39 +000044#endif
45
46
Brian Paul075398b2000-01-31 23:33:53 +000047/* XXX this is a bit of a hack needed for compilation within XFree86 */
48#ifndef FLT_MIN
49#define FLT_MIN 1e-37
50#endif
51
jtgafb833d1999-08-19 00:55:39 +000052
Brian Paulfbd8f211999-11-11 01:22:25 +000053void
54_mesa_ShadeModel( GLenum mode )
jtgafb833d1999-08-19 00:55:39 +000055{
Brian Paulfbd8f211999-11-11 01:22:25 +000056 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +000057 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel");
58
59 if (MESA_VERBOSE & VERBOSE_API)
60 fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode));
61
Brian Paulfbd8f211999-11-11 01:22:25 +000062 if (mode == GL_FLAT || mode == GL_SMOOTH) {
Brian Paul8acb3a11999-11-22 18:58:53 +000063 if (ctx->Light.ShadeModel != mode) {
Brian Paulfbd8f211999-11-11 01:22:25 +000064 ctx->Light.ShadeModel = mode;
Brian Paul8acb3a11999-11-22 18:58:53 +000065 if (ctx->Light.ShadeModel == GL_FLAT)
Keith Whitwell14940c42000-11-05 18:40:57 +000066 SET_BITS(ctx->_TriangleCaps, DD_FLATSHADE);
Brian Paul8acb3a11999-11-22 18:58:53 +000067 else
Keith Whitwell14940c42000-11-05 18:40:57 +000068 CLEAR_BITS(ctx->_TriangleCaps, DD_FLATSHADE);
Keith Whitwella96308c2000-10-30 13:31:59 +000069
70 ctx->NewState |= _NEW_LIGHT;
71
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000072 if (ctx->Driver.ShadeModel)
Brian Paulfbd8f211999-11-11 01:22:25 +000073 (*ctx->Driver.ShadeModel)( ctx, mode );
Keith Whitwell1bf9dfa1999-09-18 20:41:22 +000074 }
Brian Paulfbd8f211999-11-11 01:22:25 +000075 }
76 else {
Keith Whitwell1bf9dfa1999-09-18 20:41:22 +000077 gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
jtgafb833d1999-08-19 00:55:39 +000078 }
jtgafb833d1999-08-19 00:55:39 +000079}
80
81
82
Brian Paulfbd8f211999-11-11 01:22:25 +000083void
84_mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
jtgafb833d1999-08-19 00:55:39 +000085{
Brian Paulfbd8f211999-11-11 01:22:25 +000086 _mesa_Lightfv( light, pname, &param );
87}
jtgafb833d1999-08-19 00:55:39 +000088
Brian Paulfbd8f211999-11-11 01:22:25 +000089
90void
91_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
92{
93 GET_CURRENT_CONTEXT(ctx);
Keith Whitwell1e1aac02000-11-13 20:02:56 +000094 GLint i = (GLint) (light - GL_LIGHT0);
95 struct gl_light *l = &ctx->Light.Light[i];
jtgafb833d1999-08-19 00:55:39 +000096
97 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight");
98
Keith Whitwell1e1aac02000-11-13 20:02:56 +000099 if (i < 0 || i >= MAX_LIGHTS) {
jtgafb833d1999-08-19 00:55:39 +0000100 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
101 return;
102 }
103
104 switch (pname) {
105 case GL_AMBIENT:
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000106 COPY_4V( l->Ambient, params );
jtgafb833d1999-08-19 00:55:39 +0000107 break;
108 case GL_DIFFUSE:
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000109 COPY_4V( l->Diffuse, params );
jtgafb833d1999-08-19 00:55:39 +0000110 break;
111 case GL_SPECULAR:
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000112 COPY_4V( l->Specular, params );
jtgafb833d1999-08-19 00:55:39 +0000113 break;
114 case GL_POSITION:
115 /* transform position by ModelView matrix */
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000116 TRANSFORM_POINT( l->EyePosition, ctx->ModelView.m, params );
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000117 if (l->EyePosition[3] != 0.0F)
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000118 l->_Flags |= LIGHT_POSITIONAL;
119 else
120 l->_Flags &= ~LIGHT_POSITIONAL;
jtgafb833d1999-08-19 00:55:39 +0000121 break;
122 case GL_SPOT_DIRECTION:
123 /* transform direction by inverse modelview */
124 if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
Keith Whitwellad2ac212000-11-24 10:25:05 +0000125 _math_matrix_analyse( &ctx->ModelView );
jtgafb833d1999-08-19 00:55:39 +0000126 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000127 TRANSFORM_NORMAL( l->EyeDirection, params, ctx->ModelView.inv );
jtgafb833d1999-08-19 00:55:39 +0000128 break;
129 case GL_SPOT_EXPONENT:
130 if (params[0]<0.0 || params[0]>128.0) {
131 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
132 return;
133 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000134 if (l->SpotExponent != params[0]) {
135 l->SpotExponent = params[0];
136 gl_compute_spot_exp_table( l );
jtgafb833d1999-08-19 00:55:39 +0000137 }
138 break;
139 case GL_SPOT_CUTOFF:
140 if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
141 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
142 return;
143 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000144 l->SpotCutoff = params[0];
145 l->_CosCutoff = cos(params[0]*DEG2RAD);
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000146 if (l->_CosCutoff < 0)
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000147 l->_CosCutoff = 0;
148 if (l->SpotCutoff != 180.0F)
149 l->_Flags |= LIGHT_SPOT;
150 else
151 l->_Flags &= ~LIGHT_SPOT;
jtgafb833d1999-08-19 00:55:39 +0000152 break;
153 case GL_CONSTANT_ATTENUATION:
154 if (params[0]<0.0) {
155 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
156 return;
157 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000158 l->ConstantAttenuation = params[0];
jtgafb833d1999-08-19 00:55:39 +0000159 break;
160 case GL_LINEAR_ATTENUATION:
161 if (params[0]<0.0) {
162 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
163 return;
164 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000165 l->LinearAttenuation = params[0];
jtgafb833d1999-08-19 00:55:39 +0000166 break;
167 case GL_QUADRATIC_ATTENUATION:
168 if (params[0]<0.0) {
169 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
170 return;
171 }
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000172 l->QuadraticAttenuation = params[0];
jtgafb833d1999-08-19 00:55:39 +0000173 break;
174 default:
175 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
Brian Paulfbd8f211999-11-11 01:22:25 +0000176 return;
jtgafb833d1999-08-19 00:55:39 +0000177 }
178
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000179 if (ctx->Driver.Lightfv)
Keith Whitwell1e1aac02000-11-13 20:02:56 +0000180 ctx->Driver.Lightfv( ctx, light, pname, params );
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000181
Keith Whitwella96308c2000-10-30 13:31:59 +0000182 ctx->NewState |= _NEW_LIGHT;
jtgafb833d1999-08-19 00:55:39 +0000183}
184
185
Brian Paulfbd8f211999-11-11 01:22:25 +0000186void
187_mesa_Lighti( GLenum light, GLenum pname, GLint param )
jtgafb833d1999-08-19 00:55:39 +0000188{
Brian Paulfbd8f211999-11-11 01:22:25 +0000189 _mesa_Lightiv( light, pname, &param );
190}
191
192
193void
194_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
195{
196 GLfloat fparam[4];
197
198 switch (pname) {
199 case GL_AMBIENT:
200 case GL_DIFFUSE:
201 case GL_SPECULAR:
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] );
206 break;
207 case GL_POSITION:
208 fparam[0] = (GLfloat) params[0];
209 fparam[1] = (GLfloat) params[1];
210 fparam[2] = (GLfloat) params[2];
211 fparam[3] = (GLfloat) params[3];
212 break;
213 case GL_SPOT_DIRECTION:
214 fparam[0] = (GLfloat) params[0];
215 fparam[1] = (GLfloat) params[1];
216 fparam[2] = (GLfloat) params[2];
217 break;
218 case GL_SPOT_EXPONENT:
219 case GL_SPOT_CUTOFF:
220 case GL_CONSTANT_ATTENUATION:
221 case GL_LINEAR_ATTENUATION:
222 case GL_QUADRATIC_ATTENUATION:
223 fparam[0] = (GLfloat) params[0];
224 break;
225 default:
226 /* error will be caught later in gl_Lightfv */
227 ;
228 }
229
230 _mesa_Lightfv( light, pname, fparam );
231}
232
233
234
235void
236_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
237{
238 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000239 GLint l = (GLint) (light - GL_LIGHT0);
240
241 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
242
243 if (l<0 || l>=MAX_LIGHTS) {
244 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
245 return;
246 }
247
248 switch (pname) {
249 case GL_AMBIENT:
250 COPY_4V( params, ctx->Light.Light[l].Ambient );
251 break;
252 case GL_DIFFUSE:
253 COPY_4V( params, ctx->Light.Light[l].Diffuse );
254 break;
255 case GL_SPECULAR:
256 COPY_4V( params, ctx->Light.Light[l].Specular );
257 break;
258 case GL_POSITION:
259 COPY_4V( params, ctx->Light.Light[l].EyePosition );
260 break;
261 case GL_SPOT_DIRECTION:
262 COPY_3V( params, ctx->Light.Light[l].EyeDirection );
263 break;
264 case GL_SPOT_EXPONENT:
265 params[0] = ctx->Light.Light[l].SpotExponent;
266 break;
267 case GL_SPOT_CUTOFF:
268 params[0] = ctx->Light.Light[l].SpotCutoff;
269 break;
270 case GL_CONSTANT_ATTENUATION:
271 params[0] = ctx->Light.Light[l].ConstantAttenuation;
272 break;
273 case GL_LINEAR_ATTENUATION:
274 params[0] = ctx->Light.Light[l].LinearAttenuation;
275 break;
276 case GL_QUADRATIC_ATTENUATION:
277 params[0] = ctx->Light.Light[l].QuadraticAttenuation;
278 break;
279 default:
280 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
281 break;
282 }
283}
284
285
286
Brian Paulfbd8f211999-11-11 01:22:25 +0000287void
288_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
jtgafb833d1999-08-19 00:55:39 +0000289{
Brian Paulfbd8f211999-11-11 01:22:25 +0000290 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000291 GLint l = (GLint) (light - GL_LIGHT0);
292
293 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
294
295 if (l<0 || l>=MAX_LIGHTS) {
296 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
297 return;
298 }
299
300 switch (pname) {
301 case GL_AMBIENT:
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]);
306 break;
307 case GL_DIFFUSE:
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]);
312 break;
313 case GL_SPECULAR:
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]);
318 break;
319 case GL_POSITION:
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];
324 break;
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];
329 break;
330 case GL_SPOT_EXPONENT:
331 params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
332 break;
333 case GL_SPOT_CUTOFF:
334 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
335 break;
336 case GL_CONSTANT_ATTENUATION:
337 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
338 break;
339 case GL_LINEAR_ATTENUATION:
340 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
341 break;
342 case GL_QUADRATIC_ATTENUATION:
343 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
344 break;
345 default:
346 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
347 break;
348 }
349}
350
351
352
353/**********************************************************************/
354/*** Light Model ***/
355/**********************************************************************/
356
357
Brian Paulfbd8f211999-11-11 01:22:25 +0000358void
359_mesa_LightModelfv( GLenum pname, const GLfloat *params )
jtgafb833d1999-08-19 00:55:39 +0000360{
Brian Paulfbd8f211999-11-11 01:22:25 +0000361 GET_CURRENT_CONTEXT(ctx);
362 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModelfv");
jtgafb833d1999-08-19 00:55:39 +0000363
364 switch (pname) {
365 case GL_LIGHT_MODEL_AMBIENT:
366 COPY_4V( ctx->Light.Model.Ambient, params );
367 break;
368 case GL_LIGHT_MODEL_LOCAL_VIEWER:
369 if (params[0]==0.0)
370 ctx->Light.Model.LocalViewer = GL_FALSE;
371 else
372 ctx->Light.Model.LocalViewer = GL_TRUE;
373 break;
374 case GL_LIGHT_MODEL_TWO_SIDE:
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000375 if (params[0]==0.0)
jtgafb833d1999-08-19 00:55:39 +0000376 ctx->Light.Model.TwoSide = GL_FALSE;
377 else
378 ctx->Light.Model.TwoSide = GL_TRUE;
379 break;
380 case GL_LIGHT_MODEL_COLOR_CONTROL:
Brian Paulf3f9b771999-10-19 20:32:40 +0000381 if (params[0] == (GLfloat) GL_SINGLE_COLOR) {
jtgafb833d1999-08-19 00:55:39 +0000382 ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
Keith Whitwellfe5d67d2000-10-27 16:44:40 +0000383 if (!ctx->Fog.ColorSumEnabled)
Keith Whitwell14940c42000-11-05 18:40:57 +0000384 CLEAR_BITS(ctx->_TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000385 }
jtgafb833d1999-08-19 00:55:39 +0000386 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
387 ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
Keith Whitwell14940c42000-11-05 18:40:57 +0000388 SET_BITS(ctx->_TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000389 }
390 else {
jtgafb833d1999-08-19 00:55:39 +0000391 gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
Brian Paulf3f9b771999-10-19 20:32:40 +0000392 }
jtgafb833d1999-08-19 00:55:39 +0000393 break;
394 default:
395 gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
396 break;
397 }
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000398
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000399 if (ctx->Driver.LightModelfv)
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000400 ctx->Driver.LightModelfv( ctx, pname, params );
401
Keith Whitwella96308c2000-10-30 13:31:59 +0000402 ctx->NewState |= _NEW_LIGHT;
jtgafb833d1999-08-19 00:55:39 +0000403}
404
405
Brian Paulfbd8f211999-11-11 01:22:25 +0000406void
407_mesa_LightModeliv( GLenum pname, const GLint *params )
408{
409 GLfloat fparam[4];
410 GET_CURRENT_CONTEXT(ctx);
411 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModeliv");
412
413 switch (pname) {
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] );
419 break;
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];
424 break;
425 default:
426 /* Error will be caught later in gl_LightModelfv */
427 ;
428 }
429 _mesa_LightModelfv( pname, fparam );
430}
431
432
433void
434_mesa_LightModeli( GLenum pname, GLint param )
435{
436 _mesa_LightModeliv( pname, &param );
437}
438
439
440void
441_mesa_LightModelf( GLenum pname, GLfloat param )
442{
443 _mesa_LightModelfv( pname, &param );
444}
445
jtgafb833d1999-08-19 00:55:39 +0000446
447
448/********** MATERIAL **********/
449
450
451/*
452 * Given a face and pname value (ala glColorMaterial), compute a bitmask
453 * of the targeted material values.
454 */
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000455GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
jtgafb833d1999-08-19 00:55:39 +0000456 GLuint legal,
457 const char *where )
458{
459 GLuint bitmask = 0;
460
461 /* Make a bitmask indicating what material attribute(s) we're updating */
462 switch (pname) {
463 case GL_EMISSION:
464 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
465 break;
466 case GL_AMBIENT:
467 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
468 break;
469 case GL_DIFFUSE:
470 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
471 break;
472 case GL_SPECULAR:
473 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
474 break;
475 case GL_SHININESS:
476 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
477 break;
478 case GL_AMBIENT_AND_DIFFUSE:
479 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
480 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
481 break;
482 case GL_COLOR_INDEXES:
483 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
484 break;
485 default:
486 gl_error( ctx, GL_INVALID_ENUM, where );
487 return 0;
488 }
489
490 if (face==GL_FRONT) {
491 bitmask &= FRONT_MATERIAL_BITS;
492 }
493 else if (face==GL_BACK) {
494 bitmask &= BACK_MATERIAL_BITS;
495 }
496 else if (face != GL_FRONT_AND_BACK) {
497 gl_error( ctx, GL_INVALID_ENUM, where );
498 return 0;
499 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000500
jtgafb833d1999-08-19 00:55:39 +0000501 if (bitmask & ~legal) {
502 gl_error( ctx, GL_INVALID_ENUM, where );
503 return 0;
504 }
505
506 return bitmask;
507}
508
509
510
jtgafb833d1999-08-19 00:55:39 +0000511/*
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.
517 *
Brian Paulde82d062000-06-26 23:37:46 +0000518 * src[0] is front material, src[1] is back material
519 *
jtgafb833d1999-08-19 00:55:39 +0000520 * KW: Added code here to keep the precomputed variables uptodate.
521 * This means we can use the faster shade functions when using
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000522 * GL_COLOR_MATERIAL, and we can also now use the precomputed
jtgafb833d1999-08-19 00:55:39 +0000523 * values in the slower shading functions, which further offsets
524 * the cost of doing this here.
525 */
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000526void gl_update_material( GLcontext *ctx,
527 const struct gl_material src[2],
jtgafb833d1999-08-19 00:55:39 +0000528 GLuint bitmask )
529{
530 struct gl_light *light, *list = &ctx->Light.EnabledList;
jtgafb833d1999-08-19 00:55:39 +0000531
532 if (ctx->Light.ColorMaterialEnabled)
533 bitmask &= ~ctx->Light.ColorMaterialBitmask;
534
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000535 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000536 fprintf(stderr, "gl_update_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000537
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000538 if (!bitmask)
jtgafb833d1999-08-19 00:55:39 +0000539 return;
540
Brian Paulde82d062000-06-26 23:37:46 +0000541 /* 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 );
545 }
546 if (bitmask & BACK_EMISSION_BIT) {
547 struct gl_material *mat = &ctx->Light.Material[1];
548 COPY_4FV( mat->Emission, src[1].Emission );
549 }
550
551 /* update material ambience */
jtgafb833d1999-08-19 00:55:39 +0000552 if (bitmask & FRONT_AMBIENT_BIT) {
553 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000554 COPY_4FV( mat->Ambient, src[0].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000555 foreach (light, list) {
Keith Whitwell14940c42000-11-05 18:40:57 +0000556 SCALE_3V( light->_MatAmbient[0], light->Ambient, src[0].Ambient);
Brian Paulde82d062000-06-26 23:37:46 +0000557 }
jtgafb833d1999-08-19 00:55:39 +0000558 }
559 if (bitmask & BACK_AMBIENT_BIT) {
560 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000561 COPY_4FV( mat->Ambient, src[1].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000562 foreach (light, list) {
Keith Whitwell14940c42000-11-05 18:40:57 +0000563 SCALE_3V( light->_MatAmbient[1], light->Ambient, src[1].Ambient);
Brian Paulde82d062000-06-26 23:37:46 +0000564 }
jtgafb833d1999-08-19 00:55:39 +0000565 }
Brian Paulde82d062000-06-26 23:37:46 +0000566
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];
Keith Whitwell14940c42000-11-05 18:40:57 +0000570 COPY_3V( ctx->Light._BaseColor[0], mat->Emission );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000571 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat->Ambient,
572 ctx->Light.Model.Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000573 }
574 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
575 struct gl_material *mat = &ctx->Light.Material[1];
Keith Whitwell14940c42000-11-05 18:40:57 +0000576 COPY_3V( ctx->Light._BaseColor[1], mat->Emission );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000577 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat->Ambient,
578 ctx->Light.Model.Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000579 }
580
581 /* update material diffuse values */
jtgafb833d1999-08-19 00:55:39 +0000582 if (bitmask & FRONT_DIFFUSE_BIT) {
583 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000584 COPY_4FV( mat->Diffuse, src[0].Diffuse );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000585 foreach (light, list) {
586 SCALE_3V( light->_MatDiffuse[0], light->Diffuse, mat->Diffuse );
587 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000588 FLOAT_COLOR_TO_CHAN(ctx->Light._BaseAlpha[0], mat->Diffuse[3]);
jtgafb833d1999-08-19 00:55:39 +0000589 }
590 if (bitmask & BACK_DIFFUSE_BIT) {
591 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000592 COPY_4FV( mat->Diffuse, src[1].Diffuse );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000593 foreach (light, list) {
594 SCALE_3V( light->_MatDiffuse[1], light->Diffuse, mat->Diffuse );
595 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000596 FLOAT_COLOR_TO_CHAN(ctx->Light._BaseAlpha[1], mat->Diffuse[3]);
jtgafb833d1999-08-19 00:55:39 +0000597 }
Brian Paulde82d062000-06-26 23:37:46 +0000598
599 /* update material specular values */
jtgafb833d1999-08-19 00:55:39 +0000600 if (bitmask & FRONT_SPECULAR_BIT) {
601 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000602 COPY_4FV( mat->Specular, src[0].Specular );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000603 foreach (light, list) {
Keith Whitwell9aff6cf2000-11-24 15:21:59 +0000604 SCALE_3V( light->_MatSpecular[0], light->Specular, mat->Specular);
Keith Whitwellad2ac212000-11-24 10:25:05 +0000605 }
jtgafb833d1999-08-19 00:55:39 +0000606 }
607 if (bitmask & BACK_SPECULAR_BIT) {
608 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000609 COPY_4FV( mat->Specular, src[1].Specular );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000610 foreach (light, list) {
Keith Whitwell9aff6cf2000-11-24 15:21:59 +0000611 SCALE_3V( light->_MatSpecular[1], light->Specular, mat->Specular);
Keith Whitwellad2ac212000-11-24 10:25:05 +0000612 }
jtgafb833d1999-08-19 00:55:39 +0000613 }
Brian Paulde82d062000-06-26 23:37:46 +0000614
jtgafb833d1999-08-19 00:55:39 +0000615 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 );
619 }
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 );
624 }
Brian Paulde82d062000-06-26 23:37:46 +0000625
jtgafb833d1999-08-19 00:55:39 +0000626 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;
630 }
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;
635 }
636
Keith Whitwell06ac5921999-11-10 06:29:44 +0000637 if (0)
638 {
639 struct gl_material *mat = &ctx->Light.Material[0];
640 fprintf(stderr, "update_mat emission : %f %f %f\n",
641 mat->Emission[0],
642 mat->Emission[1],
643 mat->Emission[2]);
644 fprintf(stderr, "update_mat specular : %f %f %f\n",
645 mat->Specular[0],
646 mat->Specular[1],
647 mat->Specular[2]);
648 fprintf(stderr, "update_mat diffuse : %f %f %f\n",
649 mat->Diffuse[0],
650 mat->Diffuse[1],
651 mat->Diffuse[2]);
652 fprintf(stderr, "update_mat ambient : %f %f %f\n",
653 mat->Ambient[0],
654 mat->Ambient[1],
655 mat->Ambient[2]);
656 }
jtgafb833d1999-08-19 00:55:39 +0000657}
658
659
660
661
Brian Paulde82d062000-06-26 23:37:46 +0000662/*
663 * Update the current materials from the given rgba color
664 * according to the bitmask in ColorMaterialBitmask, which is
665 * set by glColorMaterial().
666 */
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000667void gl_update_color_material( GLcontext *ctx,
Brian Paulba643a22000-10-28 18:34:48 +0000668 const GLchan rgba[4] )
jtgafb833d1999-08-19 00:55:39 +0000669{
670 struct gl_light *light, *list = &ctx->Light.EnabledList;
671 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
Brian Paulde82d062000-06-26 23:37:46 +0000672 GLfloat color[4];
jtgafb833d1999-08-19 00:55:39 +0000673
Brian Paulc893a012000-10-28 20:41:13 +0000674 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]);
678
Keith Whitwell06ac5921999-11-10 06:29:44 +0000679 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000680 fprintf(stderr, "gl_update_color_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000681
Brian Paulde82d062000-06-26 23:37:46 +0000682 /* update emissive colors */
683 if (bitmask & FRONT_EMISSION_BIT) {
684 struct gl_material *mat = &ctx->Light.Material[0];
685 COPY_4FV( mat->Emission, color );
686 }
Brian Paulfbd8f211999-11-11 01:22:25 +0000687
Brian Paulde82d062000-06-26 23:37:46 +0000688 if (bitmask & BACK_EMISSION_BIT) {
689 struct gl_material *mat = &ctx->Light.Material[1];
690 COPY_4FV( mat->Emission, color );
691 }
692
Keith Whitwell14940c42000-11-05 18:40:57 +0000693 /* update light->_MatAmbient = light's ambient * material's ambient */
jtgafb833d1999-08-19 00:55:39 +0000694 if (bitmask & FRONT_AMBIENT_BIT) {
695 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000696 foreach (light, list) {
Keith Whitwell14940c42000-11-05 18:40:57 +0000697 SCALE_3V( light->_MatAmbient[0], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000698 }
699 COPY_4FV( mat->Ambient, color );
700 }
701
702 if (bitmask & BACK_AMBIENT_BIT) {
703 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000704 foreach (light, list) {
Keith Whitwell14940c42000-11-05 18:40:57 +0000705 SCALE_3V( light->_MatAmbient[1], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000706 }
707 COPY_4FV( mat->Ambient, color );
708 }
709
Brian Paulde82d062000-06-26 23:37:46 +0000710 /* 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];
Keith Whitwell14940c42000-11-05 18:40:57 +0000713 COPY_3V( ctx->Light._BaseColor[0], mat->Emission );
714 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000715 }
716
717 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
718 struct gl_material *mat = &ctx->Light.Material[1];
Keith Whitwell14940c42000-11-05 18:40:57 +0000719 COPY_3V( ctx->Light._BaseColor[1], mat->Emission );
720 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000721 }
722
Keith Whitwell14940c42000-11-05 18:40:57 +0000723 /* update light->_MatDiffuse = light's diffuse * material's diffuse */
jtgafb833d1999-08-19 00:55:39 +0000724 if (bitmask & FRONT_DIFFUSE_BIT) {
725 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000726 COPY_4FV( mat->Diffuse, color );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000727 foreach (light, list) {
728 SCALE_3V( light->_MatDiffuse[0], light->Diffuse, mat->Diffuse );
729 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000730 FLOAT_COLOR_TO_CHAN(ctx->Light._BaseAlpha[0], mat->Diffuse[3]);
jtgafb833d1999-08-19 00:55:39 +0000731 }
732
733 if (bitmask & BACK_DIFFUSE_BIT) {
734 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000735 COPY_4FV( mat->Diffuse, color );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000736 foreach (light, list) {
737 SCALE_3V( light->_MatDiffuse[1], light->Diffuse, mat->Diffuse );
738 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000739 FLOAT_COLOR_TO_CHAN(ctx->Light._BaseAlpha[1], mat->Diffuse[3]);
jtgafb833d1999-08-19 00:55:39 +0000740 }
741
Keith Whitwell14940c42000-11-05 18:40:57 +0000742 /* update light->_MatSpecular = light's specular * material's specular */
jtgafb833d1999-08-19 00:55:39 +0000743 if (bitmask & FRONT_SPECULAR_BIT) {
744 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000745 COPY_4FV( mat->Specular, color );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000746 foreach (light, list) {
747 ACC_SCALE_3V( light->_MatSpecular[0], light->Specular, mat->Specular);
748 }
jtgafb833d1999-08-19 00:55:39 +0000749 }
Brian Paulde82d062000-06-26 23:37:46 +0000750
jtgafb833d1999-08-19 00:55:39 +0000751 if (bitmask & BACK_SPECULAR_BIT) {
752 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000753 COPY_4FV( mat->Specular, color );
Keith Whitwellad2ac212000-11-24 10:25:05 +0000754 foreach (light, list) {
755 ACC_SCALE_3V( light->_MatSpecular[1], light->Specular, mat->Specular);
756 }
jtgafb833d1999-08-19 00:55:39 +0000757 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000758
759 if (0)
760 {
761 struct gl_material *mat = &ctx->Light.Material[0];
762 fprintf(stderr, "update_color_mat emission : %f %f %f\n",
763 mat->Emission[0],
764 mat->Emission[1],
765 mat->Emission[2]);
766 fprintf(stderr, "update_color_mat specular : %f %f %f\n",
767 mat->Specular[0],
768 mat->Specular[1],
769 mat->Specular[2]);
770 fprintf(stderr, "update_color_mat diffuse : %f %f %f\n",
771 mat->Diffuse[0],
772 mat->Diffuse[1],
773 mat->Diffuse[2]);
774 fprintf(stderr, "update_color_mat ambient : %f %f %f\n",
775 mat->Ambient[0],
776 mat->Ambient[1],
777 mat->Ambient[2]);
778 }
jtgafb833d1999-08-19 00:55:39 +0000779}
780
781
782
783
Brian Paulfbd8f211999-11-11 01:22:25 +0000784void
785_mesa_ColorMaterial( GLenum face, GLenum mode )
jtgafb833d1999-08-19 00:55:39 +0000786{
Brian Paulfbd8f211999-11-11 01:22:25 +0000787 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000788 GLuint bitmask;
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);
793
794 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
795
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000796 if (MESA_VERBOSE&VERBOSE_API)
797 fprintf(stderr, "glColorMaterial %s %s\n",
Keith Whitwell06ac5921999-11-10 06:29:44 +0000798 gl_lookup_enum_by_nr(face),
799 gl_lookup_enum_by_nr(mode));
800
jtgafb833d1999-08-19 00:55:39 +0000801 bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
802
803 if (bitmask != 0) {
804 ctx->Light.ColorMaterialBitmask = bitmask;
805 ctx->Light.ColorMaterialFace = face;
806 ctx->Light.ColorMaterialMode = mode;
807 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000808
Keith Whitwell23caf202000-11-16 21:05:34 +0000809 if (ctx->Light.ColorMaterialEnabled) {
810 FLUSH_TNL( ctx, FLUSH_UPDATE_CURRENT );
Brian Paul19300532000-10-29 19:02:23 +0000811 gl_update_color_material( ctx, ctx->Current.Color );
Keith Whitwell23caf202000-11-16 21:05:34 +0000812 }
Keith Whitwella96308c2000-10-30 13:31:59 +0000813
814 ctx->NewState |= _NEW_LIGHT;
jtgafb833d1999-08-19 00:55:39 +0000815}
816
817
818
Brian Paulfbd8f211999-11-11 01:22:25 +0000819
Brian Paulfbd8f211999-11-11 01:22:25 +0000820
821void
822_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
823{
824 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000825 GLuint f;
826
827 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
828
829 if (face==GL_FRONT) {
830 f = 0;
831 }
832 else if (face==GL_BACK) {
833 f = 1;
834 }
835 else {
836 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
837 return;
838 }
839 switch (pname) {
840 case GL_AMBIENT:
841 COPY_4FV( params, ctx->Light.Material[f].Ambient );
842 break;
843 case GL_DIFFUSE:
844 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
845 break;
846 case GL_SPECULAR:
847 COPY_4FV( params, ctx->Light.Material[f].Specular );
848 break;
849 case GL_EMISSION:
850 COPY_4FV( params, ctx->Light.Material[f].Emission );
851 break;
852 case GL_SHININESS:
853 *params = ctx->Light.Material[f].Shininess;
854 break;
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;
859 break;
860 default:
861 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
862 }
863}
864
865
866
Brian Paulfbd8f211999-11-11 01:22:25 +0000867void
868_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
jtgafb833d1999-08-19 00:55:39 +0000869{
Brian Paulfbd8f211999-11-11 01:22:25 +0000870 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000871 GLuint f;
872
873 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
874
875 if (face==GL_FRONT) {
876 f = 0;
877 }
878 else if (face==GL_BACK) {
879 f = 1;
880 }
881 else {
882 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
883 return;
884 }
885 switch (pname) {
886 case GL_AMBIENT:
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] );
891 break;
892 case GL_DIFFUSE:
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] );
897 break;
898 case GL_SPECULAR:
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] );
903 break;
904 case GL_EMISSION:
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] );
909 break;
910 case GL_SHININESS:
911 *params = ROUNDF( ctx->Light.Material[f].Shininess );
912 break;
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 );
917 break;
918 default:
919 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
920 }
921}
922
923
924
925
926/**********************************************************************/
927/***** Lighting computation *****/
928/**********************************************************************/
929
930
931/*
932 * Notes:
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.
937 *
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000938 * KW: We now know orientation in advance and only shade for
jtgafb833d1999-08-19 00:55:39 +0000939 * the side or sides which are actually required.
940 *
941 * Variables:
942 * n = normal vector
943 * V = vertex position
944 * P = light source position
945 * Pe = (0,0,0,1)
946 *
947 * Precomputed:
948 * IF P[3]==0 THEN
949 * // light at infinity
950 * IF local_viewer THEN
Keith Whitwell14940c42000-11-05 18:40:57 +0000951 * _VP_inf_norm = unit vector from V to P // Precompute
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000952 * ELSE
jtgafb833d1999-08-19 00:55:39 +0000953 * // eye at infinity
Keith Whitwell14940c42000-11-05 18:40:57 +0000954 * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
jtgafb833d1999-08-19 00:55:39 +0000955 * ENDIF
956 * ENDIF
957 *
958 * Functions:
959 * Normalize( v ) = normalized vector v
960 * Magnitude( v ) = length of vector v
961 */
962
963
964
965/*
966 * Whenever the spotlight exponent for a light changes we must call
967 * this function to recompute the exponent lookup table.
968 */
Brian Paula0faa7f2000-07-18 16:55:56 +0000969void
970gl_compute_spot_exp_table( struct gl_light *l )
jtgafb833d1999-08-19 00:55:39 +0000971{
Brian Paula0faa7f2000-07-18 16:55:56 +0000972 GLint i;
973 GLdouble exponent = l->SpotExponent;
974 GLdouble tmp = 0;
975 GLint clamp = 0;
jtgafb833d1999-08-19 00:55:39 +0000976
Keith Whitwell14940c42000-11-05 18:40:57 +0000977 l->_SpotExpTable[0][0] = 0.0;
jtgafb833d1999-08-19 00:55:39 +0000978
Brian Paula0faa7f2000-07-18 16:55:56 +0000979 for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
jtgafb833d1999-08-19 00:55:39 +0000980 if (clamp == 0) {
Brian Paula0faa7f2000-07-18 16:55:56 +0000981 tmp = pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
982 if (tmp < FLT_MIN * 100.0) {
jtgafb833d1999-08-19 00:55:39 +0000983 tmp = 0.0;
984 clamp = 1;
985 }
986 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000987 l->_SpotExpTable[i][0] = tmp;
jtgafb833d1999-08-19 00:55:39 +0000988 }
Brian Paula0faa7f2000-07-18 16:55:56 +0000989 for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
Keith Whitwell14940c42000-11-05 18:40:57 +0000990 l->_SpotExpTable[i][1] = l->_SpotExpTable[i+1][0] - l->_SpotExpTable[i][0];
jtgafb833d1999-08-19 00:55:39 +0000991 }
Keith Whitwell14940c42000-11-05 18:40:57 +0000992 l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
jtgafb833d1999-08-19 00:55:39 +0000993}
994
995
996
997
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.
1001 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001002static void
1003compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
jtgafb833d1999-08-19 00:55:39 +00001004{
Brian Paula0faa7f2000-07-18 16:55:56 +00001005 GLint i;
jtgafb833d1999-08-19 00:55:39 +00001006 GLfloat *m = tab->tab;
1007
Brian Paula0faa7f2000-07-18 16:55:56 +00001008 m[0] = 0.0;
1009 if (shininess == 0.0) {
jtgafb833d1999-08-19 00:55:39 +00001010 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
Brian Paula0faa7f2000-07-18 16:55:56 +00001011 m[i] = 1.0;
1012 }
1013 else {
1014 for (i = 1 ; i < SHINE_TABLE_SIZE ; i++) {
1015 GLdouble t = pow(i / (GLfloat) (SHINE_TABLE_SIZE - 1), shininess);
1016 if (t > 1e-20)
1017 m[i] = t;
1018 else
1019 m[i] = 0.0;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001020 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001021 m[SHINE_TABLE_SIZE] = 1.0;
jtgafb833d1999-08-19 00:55:39 +00001022 }
1023
1024 tab->shininess = shininess;
1025}
1026
jtgafb833d1999-08-19 00:55:39 +00001027
Brian Paula0faa7f2000-07-18 16:55:56 +00001028void
1029gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
jtgafb833d1999-08-19 00:55:39 +00001030{
Brian Paula0faa7f2000-07-18 16:55:56 +00001031#define DISTSQR(a,b) ((a-b)*(a-b))
Keith Whitwell14940c42000-11-05 18:40:57 +00001032 struct gl_shine_tab *list = ctx->_ShineTabList;
jtgafb833d1999-08-19 00:55:39 +00001033 struct gl_shine_tab *s;
1034
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001035 foreach(s, list)
1036 if ( DISTSQR(s->shininess, shininess) < 1e-4 )
jtgafb833d1999-08-19 00:55:39 +00001037 break;
1038
Brian Paula0faa7f2000-07-18 16:55:56 +00001039 if (s == list) {
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001040 foreach(s, list)
Brian Paula0faa7f2000-07-18 16:55:56 +00001041 if (s->refcount == 0)
1042 break;
jtgafb833d1999-08-19 00:55:39 +00001043
1044 compute_shine_table( s, shininess );
1045 }
1046
Keith Whitwell14940c42000-11-05 18:40:57 +00001047 ctx->_ShineTable[i]->refcount--;
1048 ctx->_ShineTable[i] = s;
jtgafb833d1999-08-19 00:55:39 +00001049 move_to_tail( list, s );
1050 s->refcount++;
Brian Paula0faa7f2000-07-18 16:55:56 +00001051#undef DISTSQR
jtgafb833d1999-08-19 00:55:39 +00001052}
1053
1054
1055
jtgafb833d1999-08-19 00:55:39 +00001056
1057/*
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.
1062 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001063void
1064gl_update_lighting( GLcontext *ctx )
jtgafb833d1999-08-19 00:55:39 +00001065{
1066 struct gl_light *light;
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001067 ctx->_TriangleCaps &= ~(DD_TRI_LIGHT_TWOSIDE|DD_LIGHTING_CULL);
1068 ctx->_NeedEyeCoords &= ~NEED_EYE_LIGHT;
1069 ctx->_NeedNormals &= ~NEED_NORMALS_LIGHT;
Keith Whitwell14940c42000-11-05 18:40:57 +00001070 ctx->Light._Flags = 0;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001071
1072 if (!ctx->Light.Enabled)
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001073 return;
1074
1075 ctx->_NeedNormals |= NEED_NORMALS_LIGHT;
1076
1077 if (ctx->Light.Model.TwoSide)
1078 ctx->_TriangleCaps |= (DD_TRI_LIGHT_TWOSIDE|DD_LIGHTING_CULL);
jtgafb833d1999-08-19 00:55:39 +00001079
1080 foreach(light, &ctx->Light.EnabledList) {
Keith Whitwell14940c42000-11-05 18:40:57 +00001081 ctx->Light._Flags |= light->_Flags;
jtgafb833d1999-08-19 00:55:39 +00001082 }
1083
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001084 ctx->Light._NeedVertices =
Keith Whitwell14940c42000-11-05 18:40:57 +00001085 ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001086 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
1087 ctx->Light.Model.LocalViewer);
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001088
1089 if ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
1090 ctx->Light.Model.LocalViewer)
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001091 ctx->_NeedEyeCoords |= NEED_EYE_LIGHT;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001092
1093
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001094 /* XXX: This test is overkill & needs to be fixed both for software and
1095 * hardware t&l drivers. The above should be sufficient & should
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001096 * be tested to verify this.
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001097 */
1098 if (ctx->Light._NeedVertices)
1099 ctx->_NeedEyeCoords |= NEED_EYE_LIGHT;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001100
jtgafb833d1999-08-19 00:55:39 +00001101
1102 /* Precompute some shading values.
1103 */
Brian Paulb1394fa2000-09-26 20:53:53 +00001104 if (ctx->Visual.RGBAflag) {
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001105 GLuint sides = ctx->Light.Model.TwoSide ? 2 : 1;
jtgafb833d1999-08-19 00:55:39 +00001106 GLuint side;
1107 for (side=0; side < sides; side++) {
1108 struct gl_material *mat = &ctx->Light.Material[side];
Brian Paulc535ba52000-06-29 04:56:30 +00001109
Keith Whitwell14940c42000-11-05 18:40:57 +00001110 COPY_3V(ctx->Light._BaseColor[side], mat->Emission);
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001111 ACC_SCALE_3V(ctx->Light._BaseColor[side],
jtgafb833d1999-08-19 00:55:39 +00001112 ctx->Light.Model.Ambient,
1113 mat->Ambient);
1114
Keith Whitwell14940c42000-11-05 18:40:57 +00001115 FLOAT_COLOR_TO_CHAN(ctx->Light._BaseAlpha[side],
Brian Paulc893a012000-10-28 20:41:13 +00001116 ctx->Light.Material[side].Diffuse[3] );
jtgafb833d1999-08-19 00:55:39 +00001117 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001118
1119 foreach (light, &ctx->Light.EnabledList) {
jtgafb833d1999-08-19 00:55:39 +00001120 for (side=0; side< sides; side++) {
Brian Paulc535ba52000-06-29 04:56:30 +00001121 const struct gl_material *mat = &ctx->Light.Material[side];
Keith Whitwell14940c42000-11-05 18:40:57 +00001122 SCALE_3V( light->_MatDiffuse[side], light->Diffuse, mat->Diffuse );
1123 SCALE_3V( light->_MatAmbient[side], light->Ambient, mat->Ambient );
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001124 SCALE_3V( light->_MatSpecular[side], light->Specular,
1125 mat->Specular);
jtgafb833d1999-08-19 00:55:39 +00001126 }
1127 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001128 }
Brian Paulc535ba52000-06-29 04:56:30 +00001129 else {
1130 static const GLfloat ci[3] = { .30, .59, .11 };
jtgafb833d1999-08-19 00:55:39 +00001131 foreach(light, &ctx->Light.EnabledList) {
Keith Whitwell14940c42000-11-05 18:40:57 +00001132 light->_dli = DOT3(ci, light->Diffuse);
1133 light->_sli = DOT3(ci, light->Specular);
jtgafb833d1999-08-19 00:55:39 +00001134 }
1135 }
1136}
1137
Brian Paulc535ba52000-06-29 04:56:30 +00001138
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001139/* _NEW_MODELVIEW
1140 * _NEW_LIGHT
1141 * _TNL_NEW_NEED_EYE_COORDS
1142 *
1143 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
1144 * Also update on lighting space changes.
jtgafb833d1999-08-19 00:55:39 +00001145 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001146void
1147gl_compute_light_positions( GLcontext *ctx )
jtgafb833d1999-08-19 00:55:39 +00001148{
1149 struct gl_light *light;
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001150 static const GLfloat eye_z[3] = { 0, 0, 1 };
jtgafb833d1999-08-19 00:55:39 +00001151
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001152 if (!ctx->Light.Enabled)
1153 return;
1154
1155 if (ctx->_NeedEyeCoords) {
1156 COPY_3V( ctx->_EyeZDir, eye_z );
1157 }
1158 else {
1159 TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelView.m );
1160 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001161
jtgafb833d1999-08-19 00:55:39 +00001162 foreach (light, &ctx->Light.EnabledList) {
1163
Keith Whitwell14940c42000-11-05 18:40:57 +00001164 if (ctx->_NeedEyeCoords) {
1165 COPY_4FV( light->_Position, light->EyePosition );
jtgafb833d1999-08-19 00:55:39 +00001166 }
Brian Paulde82d062000-06-26 23:37:46 +00001167 else {
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001168 TRANSFORM_POINT( light->_Position, ctx->ModelView.inv,
Brian Paulde82d062000-06-26 23:37:46 +00001169 light->EyePosition );
1170 }
jtgafb833d1999-08-19 00:55:39 +00001171
Keith Whitwell14940c42000-11-05 18:40:57 +00001172 if (!(light->_Flags & LIGHT_POSITIONAL)) {
jtgafb833d1999-08-19 00:55:39 +00001173 /* VP (VP) = Normalize( Position ) */
Keith Whitwell14940c42000-11-05 18:40:57 +00001174 COPY_3V( light->_VP_inf_norm, light->_Position );
1175 NORMALIZE_3FV( light->_VP_inf_norm );
jtgafb833d1999-08-19 00:55:39 +00001176
Brian Paulde82d062000-06-26 23:37:46 +00001177 if (!ctx->Light.Model.LocalViewer) {
Keith Whitwell14940c42000-11-05 18:40:57 +00001178 /* _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 );
jtgafb833d1999-08-19 00:55:39 +00001181 }
Keith Whitwell14940c42000-11-05 18:40:57 +00001182 light->_VP_inf_spot_attenuation = 1.0;
jtgafb833d1999-08-19 00:55:39 +00001183 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001184
Keith Whitwell14940c42000-11-05 18:40:57 +00001185 if (light->_Flags & LIGHT_SPOT) {
Keith Whitwell1e1aac02000-11-13 20:02:56 +00001186 if (ctx->_NeedEyeCoords) {
Keith Whitwell14940c42000-11-05 18:40:57 +00001187 COPY_3V( light->_NormDirection, light->EyeDirection );
Brian Paulde82d062000-06-26 23:37:46 +00001188 }
1189 else {
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001190 TRANSFORM_NORMAL( light->_NormDirection,
jtgafb833d1999-08-19 00:55:39 +00001191 light->EyeDirection,
1192 ctx->ModelView.m);
1193 }
1194
Keith Whitwell14940c42000-11-05 18:40:57 +00001195 NORMALIZE_3FV( light->_NormDirection );
jtgafb833d1999-08-19 00:55:39 +00001196
Keith Whitwell14940c42000-11-05 18:40:57 +00001197 if (!(light->_Flags & LIGHT_POSITIONAL)) {
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001198 GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
Keith Whitwell14940c42000-11-05 18:40:57 +00001199 light->_NormDirection);
jtgafb833d1999-08-19 00:55:39 +00001200
Keith Whitwell14940c42000-11-05 18:40:57 +00001201 if (PV_dot_dir > light->_CosCutoff) {
jtgafb833d1999-08-19 00:55:39 +00001202 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1203 int k = (int) x;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00001204 light->_VP_inf_spot_attenuation =
1205 (light->_SpotExpTable[k][0] +
Keith Whitwell14940c42000-11-05 18:40:57 +00001206 (x-k)*light->_SpotExpTable[k][1]);
jtgafb833d1999-08-19 00:55:39 +00001207 }
Brian Paulde82d062000-06-26 23:37:46 +00001208 else {
Keith Whitwell14940c42000-11-05 18:40:57 +00001209 light->_VP_inf_spot_attenuation = 0;
Brian Paulde82d062000-06-26 23:37:46 +00001210 }
jtgafb833d1999-08-19 00:55:39 +00001211 }
1212 }
1213 }
1214}
1215
1216