blob: 3e7b5a3781bb98dae1e94b6277a8f81f2f37820c [file] [log] [blame]
Brian Paulde82d062000-06-26 23:37:46 +00001/* $Id: light.c,v 1.14 2000/06/26 23:37:46 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00005 * Version: 3.3
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paul16a9efe2000-01-13 00:29:02 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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"
jtgafb833d1999-08-19 00:55:39 +000032#include "context.h"
33#include "enums.h"
34#include "light.h"
35#include "macros.h"
36#include "matrix.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"
40#include "types.h"
41#include "vb.h"
42#include "xform.h"
jtgafb833d1999-08-19 00:55:39 +000043#endif
44
45
Brian Paul075398b2000-01-31 23:33:53 +000046/* XXX this is a bit of a hack needed for compilation within XFree86 */
47#ifndef FLT_MIN
48#define FLT_MIN 1e-37
49#endif
50
jtgafb833d1999-08-19 00:55:39 +000051
Brian Paulfbd8f211999-11-11 01:22:25 +000052void
53_mesa_ShadeModel( GLenum mode )
jtgafb833d1999-08-19 00:55:39 +000054{
Brian Paulfbd8f211999-11-11 01:22:25 +000055 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +000056 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel");
57
58 if (MESA_VERBOSE & VERBOSE_API)
59 fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode));
60
Brian Paulfbd8f211999-11-11 01:22:25 +000061 if (mode == GL_FLAT || mode == GL_SMOOTH) {
Brian Paul8acb3a11999-11-22 18:58:53 +000062 if (ctx->Light.ShadeModel != mode) {
Brian Paulfbd8f211999-11-11 01:22:25 +000063 ctx->Light.ShadeModel = mode;
Brian Paul8acb3a11999-11-22 18:58:53 +000064 if (ctx->Light.ShadeModel == GL_FLAT)
65 SET_BITS(ctx->TriangleCaps, DD_FLATSHADE);
66 else
67 CLEAR_BITS(ctx->TriangleCaps, DD_FLATSHADE);
Brian Paulfbd8f211999-11-11 01:22:25 +000068 ctx->NewState |= NEW_RASTER_OPS;
69 if (ctx->Driver.ShadeModel)
70 (*ctx->Driver.ShadeModel)( ctx, mode );
Keith Whitwell1bf9dfa1999-09-18 20:41:22 +000071 }
Brian Paulfbd8f211999-11-11 01:22:25 +000072 }
73 else {
Keith Whitwell1bf9dfa1999-09-18 20:41:22 +000074 gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
jtgafb833d1999-08-19 00:55:39 +000075 }
jtgafb833d1999-08-19 00:55:39 +000076}
77
78
79
Brian Paulfbd8f211999-11-11 01:22:25 +000080void
81_mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
jtgafb833d1999-08-19 00:55:39 +000082{
Brian Paulfbd8f211999-11-11 01:22:25 +000083 _mesa_Lightfv( light, pname, &param );
84}
jtgafb833d1999-08-19 00:55:39 +000085
Brian Paulfbd8f211999-11-11 01:22:25 +000086
87void
88_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
89{
90 GET_CURRENT_CONTEXT(ctx);
91 GLint l;
92 GLint nParams;
jtgafb833d1999-08-19 00:55:39 +000093
94 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight");
95
96 l = (GLint) (light - GL_LIGHT0);
97
Brian Paulfbd8f211999-11-11 01:22:25 +000098 if (l < 0 || l >= MAX_LIGHTS) {
jtgafb833d1999-08-19 00:55:39 +000099 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
100 return;
101 }
102
103 switch (pname) {
104 case GL_AMBIENT:
105 COPY_4V( ctx->Light.Light[l].Ambient, params );
Brian Paulfbd8f211999-11-11 01:22:25 +0000106 nParams = 4;
jtgafb833d1999-08-19 00:55:39 +0000107 break;
108 case GL_DIFFUSE:
109 COPY_4V( ctx->Light.Light[l].Diffuse, params );
Brian Paulfbd8f211999-11-11 01:22:25 +0000110 nParams = 4;
jtgafb833d1999-08-19 00:55:39 +0000111 break;
112 case GL_SPECULAR:
113 COPY_4V( ctx->Light.Light[l].Specular, params );
Brian Paulfbd8f211999-11-11 01:22:25 +0000114 nParams = 4;
jtgafb833d1999-08-19 00:55:39 +0000115 break;
116 case GL_POSITION:
117 /* transform position by ModelView matrix */
118 TRANSFORM_POINT( ctx->Light.Light[l].EyePosition,
119 ctx->ModelView.m,
120 params );
Brian Paulfbd8f211999-11-11 01:22:25 +0000121 nParams = 4;
jtgafb833d1999-08-19 00:55:39 +0000122 break;
123 case GL_SPOT_DIRECTION:
124 /* transform direction by inverse modelview */
125 if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
126 gl_matrix_analyze( &ctx->ModelView );
127 }
128 TRANSFORM_NORMAL( ctx->Light.Light[l].EyeDirection,
129 params,
130 ctx->ModelView.inv );
Brian Paulfbd8f211999-11-11 01:22:25 +0000131 nParams = 3;
jtgafb833d1999-08-19 00:55:39 +0000132 break;
133 case GL_SPOT_EXPONENT:
134 if (params[0]<0.0 || params[0]>128.0) {
135 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
136 return;
137 }
138 if (ctx->Light.Light[l].SpotExponent != params[0]) {
139 ctx->Light.Light[l].SpotExponent = params[0];
140 gl_compute_spot_exp_table( &ctx->Light.Light[l] );
141 }
Brian Paulfbd8f211999-11-11 01:22:25 +0000142 nParams = 1;
jtgafb833d1999-08-19 00:55:39 +0000143 break;
144 case GL_SPOT_CUTOFF:
145 if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
146 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
147 return;
148 }
149 ctx->Light.Light[l].SpotCutoff = params[0];
150 ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
151 if (ctx->Light.Light[l].CosCutoff < 0)
152 ctx->Light.Light[l].CosCutoff = 0;
Brian Paulfbd8f211999-11-11 01:22:25 +0000153 nParams = 1;
jtgafb833d1999-08-19 00:55:39 +0000154 break;
155 case GL_CONSTANT_ATTENUATION:
156 if (params[0]<0.0) {
157 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
158 return;
159 }
160 ctx->Light.Light[l].ConstantAttenuation = params[0];
Brian Paulfbd8f211999-11-11 01:22:25 +0000161 nParams = 1;
jtgafb833d1999-08-19 00:55:39 +0000162 break;
163 case GL_LINEAR_ATTENUATION:
164 if (params[0]<0.0) {
165 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
166 return;
167 }
168 ctx->Light.Light[l].LinearAttenuation = params[0];
Brian Paulfbd8f211999-11-11 01:22:25 +0000169 nParams = 1;
jtgafb833d1999-08-19 00:55:39 +0000170 break;
171 case GL_QUADRATIC_ATTENUATION:
172 if (params[0]<0.0) {
173 gl_error( ctx, GL_INVALID_VALUE, "glLight" );
174 return;
175 }
176 ctx->Light.Light[l].QuadraticAttenuation = params[0];
Brian Paulfbd8f211999-11-11 01:22:25 +0000177 nParams = 1;
jtgafb833d1999-08-19 00:55:39 +0000178 break;
179 default:
180 gl_error( ctx, GL_INVALID_ENUM, "glLight" );
Brian Paulfbd8f211999-11-11 01:22:25 +0000181 return;
jtgafb833d1999-08-19 00:55:39 +0000182 }
183
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000184 if (ctx->Driver.Lightfv)
Brian Paulfbd8f211999-11-11 01:22:25 +0000185 ctx->Driver.Lightfv( ctx, light, pname, params, nParams );
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000186
jtgafb833d1999-08-19 00:55:39 +0000187 ctx->NewState |= NEW_LIGHTING;
188}
189
190
Brian Paulfbd8f211999-11-11 01:22:25 +0000191void
192_mesa_Lighti( GLenum light, GLenum pname, GLint param )
jtgafb833d1999-08-19 00:55:39 +0000193{
Brian Paulfbd8f211999-11-11 01:22:25 +0000194 _mesa_Lightiv( light, pname, &param );
195}
196
197
198void
199_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
200{
201 GLfloat fparam[4];
202
203 switch (pname) {
204 case GL_AMBIENT:
205 case GL_DIFFUSE:
206 case GL_SPECULAR:
207 fparam[0] = INT_TO_FLOAT( params[0] );
208 fparam[1] = INT_TO_FLOAT( params[1] );
209 fparam[2] = INT_TO_FLOAT( params[2] );
210 fparam[3] = INT_TO_FLOAT( params[3] );
211 break;
212 case GL_POSITION:
213 fparam[0] = (GLfloat) params[0];
214 fparam[1] = (GLfloat) params[1];
215 fparam[2] = (GLfloat) params[2];
216 fparam[3] = (GLfloat) params[3];
217 break;
218 case GL_SPOT_DIRECTION:
219 fparam[0] = (GLfloat) params[0];
220 fparam[1] = (GLfloat) params[1];
221 fparam[2] = (GLfloat) params[2];
222 break;
223 case GL_SPOT_EXPONENT:
224 case GL_SPOT_CUTOFF:
225 case GL_CONSTANT_ATTENUATION:
226 case GL_LINEAR_ATTENUATION:
227 case GL_QUADRATIC_ATTENUATION:
228 fparam[0] = (GLfloat) params[0];
229 break;
230 default:
231 /* error will be caught later in gl_Lightfv */
232 ;
233 }
234
235 _mesa_Lightfv( light, pname, fparam );
236}
237
238
239
240void
241_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
242{
243 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000244 GLint l = (GLint) (light - GL_LIGHT0);
245
246 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
247
248 if (l<0 || l>=MAX_LIGHTS) {
249 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
250 return;
251 }
252
253 switch (pname) {
254 case GL_AMBIENT:
255 COPY_4V( params, ctx->Light.Light[l].Ambient );
256 break;
257 case GL_DIFFUSE:
258 COPY_4V( params, ctx->Light.Light[l].Diffuse );
259 break;
260 case GL_SPECULAR:
261 COPY_4V( params, ctx->Light.Light[l].Specular );
262 break;
263 case GL_POSITION:
264 COPY_4V( params, ctx->Light.Light[l].EyePosition );
265 break;
266 case GL_SPOT_DIRECTION:
267 COPY_3V( params, ctx->Light.Light[l].EyeDirection );
268 break;
269 case GL_SPOT_EXPONENT:
270 params[0] = ctx->Light.Light[l].SpotExponent;
271 break;
272 case GL_SPOT_CUTOFF:
273 params[0] = ctx->Light.Light[l].SpotCutoff;
274 break;
275 case GL_CONSTANT_ATTENUATION:
276 params[0] = ctx->Light.Light[l].ConstantAttenuation;
277 break;
278 case GL_LINEAR_ATTENUATION:
279 params[0] = ctx->Light.Light[l].LinearAttenuation;
280 break;
281 case GL_QUADRATIC_ATTENUATION:
282 params[0] = ctx->Light.Light[l].QuadraticAttenuation;
283 break;
284 default:
285 gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
286 break;
287 }
288}
289
290
291
Brian Paulfbd8f211999-11-11 01:22:25 +0000292void
293_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
jtgafb833d1999-08-19 00:55:39 +0000294{
Brian Paulfbd8f211999-11-11 01:22:25 +0000295 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000296 GLint l = (GLint) (light - GL_LIGHT0);
297
298 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
299
300 if (l<0 || l>=MAX_LIGHTS) {
301 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
302 return;
303 }
304
305 switch (pname) {
306 case GL_AMBIENT:
307 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
308 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
309 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
310 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
311 break;
312 case GL_DIFFUSE:
313 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
314 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
315 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
316 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
317 break;
318 case GL_SPECULAR:
319 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
320 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
321 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
322 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
323 break;
324 case GL_POSITION:
325 params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
326 params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
327 params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
328 params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
329 break;
330 case GL_SPOT_DIRECTION:
331 params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
332 params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
333 params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
334 break;
335 case GL_SPOT_EXPONENT:
336 params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
337 break;
338 case GL_SPOT_CUTOFF:
339 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
340 break;
341 case GL_CONSTANT_ATTENUATION:
342 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
343 break;
344 case GL_LINEAR_ATTENUATION:
345 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
346 break;
347 case GL_QUADRATIC_ATTENUATION:
348 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
349 break;
350 default:
351 gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
352 break;
353 }
354}
355
356
357
358/**********************************************************************/
359/*** Light Model ***/
360/**********************************************************************/
361
362
Brian Paulfbd8f211999-11-11 01:22:25 +0000363void
364_mesa_LightModelfv( GLenum pname, const GLfloat *params )
jtgafb833d1999-08-19 00:55:39 +0000365{
Brian Paulfbd8f211999-11-11 01:22:25 +0000366 GET_CURRENT_CONTEXT(ctx);
367 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModelfv");
jtgafb833d1999-08-19 00:55:39 +0000368
369 switch (pname) {
370 case GL_LIGHT_MODEL_AMBIENT:
371 COPY_4V( ctx->Light.Model.Ambient, params );
372 break;
373 case GL_LIGHT_MODEL_LOCAL_VIEWER:
374 if (params[0]==0.0)
375 ctx->Light.Model.LocalViewer = GL_FALSE;
376 else
377 ctx->Light.Model.LocalViewer = GL_TRUE;
378 break;
379 case GL_LIGHT_MODEL_TWO_SIDE:
380 if (params[0]==0.0)
381 ctx->Light.Model.TwoSide = GL_FALSE;
382 else
383 ctx->Light.Model.TwoSide = GL_TRUE;
384 break;
385 case GL_LIGHT_MODEL_COLOR_CONTROL:
Brian Paulf3f9b771999-10-19 20:32:40 +0000386 if (params[0] == (GLfloat) GL_SINGLE_COLOR) {
jtgafb833d1999-08-19 00:55:39 +0000387 ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
Brian Paul8acb3a11999-11-22 18:58:53 +0000388 CLEAR_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000389 }
jtgafb833d1999-08-19 00:55:39 +0000390 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
391 ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
Brian Paul8acb3a11999-11-22 18:58:53 +0000392 SET_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000393 }
394 else {
jtgafb833d1999-08-19 00:55:39 +0000395 gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
Brian Paulf3f9b771999-10-19 20:32:40 +0000396 }
397 ctx->NewState |= NEW_RASTER_OPS;
jtgafb833d1999-08-19 00:55:39 +0000398 break;
399 default:
400 gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
401 break;
402 }
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000403
404 if (ctx->Driver.LightModelfv)
405 ctx->Driver.LightModelfv( ctx, pname, params );
406
jtgafb833d1999-08-19 00:55:39 +0000407 ctx->NewState |= NEW_LIGHTING;
408}
409
410
Brian Paulfbd8f211999-11-11 01:22:25 +0000411void
412_mesa_LightModeliv( GLenum pname, const GLint *params )
413{
414 GLfloat fparam[4];
415 GET_CURRENT_CONTEXT(ctx);
416 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModeliv");
417
418 switch (pname) {
419 case GL_LIGHT_MODEL_AMBIENT:
420 fparam[0] = INT_TO_FLOAT( params[0] );
421 fparam[1] = INT_TO_FLOAT( params[1] );
422 fparam[2] = INT_TO_FLOAT( params[2] );
423 fparam[3] = INT_TO_FLOAT( params[3] );
424 break;
425 case GL_LIGHT_MODEL_LOCAL_VIEWER:
426 case GL_LIGHT_MODEL_TWO_SIDE:
427 case GL_LIGHT_MODEL_COLOR_CONTROL:
428 fparam[0] = (GLfloat) params[0];
429 break;
430 default:
431 /* Error will be caught later in gl_LightModelfv */
432 ;
433 }
434 _mesa_LightModelfv( pname, fparam );
435}
436
437
438void
439_mesa_LightModeli( GLenum pname, GLint param )
440{
441 _mesa_LightModeliv( pname, &param );
442}
443
444
445void
446_mesa_LightModelf( GLenum pname, GLfloat param )
447{
448 _mesa_LightModelfv( pname, &param );
449}
450
jtgafb833d1999-08-19 00:55:39 +0000451
452
453/********** MATERIAL **********/
454
455
456/*
457 * Given a face and pname value (ala glColorMaterial), compute a bitmask
458 * of the targeted material values.
459 */
460GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
461 GLuint legal,
462 const char *where )
463{
464 GLuint bitmask = 0;
465
466 /* Make a bitmask indicating what material attribute(s) we're updating */
467 switch (pname) {
468 case GL_EMISSION:
469 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
470 break;
471 case GL_AMBIENT:
472 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
473 break;
474 case GL_DIFFUSE:
475 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
476 break;
477 case GL_SPECULAR:
478 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
479 break;
480 case GL_SHININESS:
481 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
482 break;
483 case GL_AMBIENT_AND_DIFFUSE:
484 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
485 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
486 break;
487 case GL_COLOR_INDEXES:
488 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
489 break;
490 default:
491 gl_error( ctx, GL_INVALID_ENUM, where );
492 return 0;
493 }
494
495 if (face==GL_FRONT) {
496 bitmask &= FRONT_MATERIAL_BITS;
497 }
498 else if (face==GL_BACK) {
499 bitmask &= BACK_MATERIAL_BITS;
500 }
501 else if (face != GL_FRONT_AND_BACK) {
502 gl_error( ctx, GL_INVALID_ENUM, where );
503 return 0;
504 }
505
506 if (bitmask & ~legal) {
507 gl_error( ctx, GL_INVALID_ENUM, where );
508 return 0;
509 }
510
511 return bitmask;
512}
513
514
515
jtgafb833d1999-08-19 00:55:39 +0000516/*
517 * Check if the global material has to be updated with info that was
518 * associated with a vertex via glMaterial.
519 * This function is used when any material values get changed between
520 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
521 * when GL_COLOR_MATERIAL is enabled.
522 *
Brian Paulde82d062000-06-26 23:37:46 +0000523 * src[0] is front material, src[1] is back material
524 *
jtgafb833d1999-08-19 00:55:39 +0000525 * KW: Added code here to keep the precomputed variables uptodate.
526 * This means we can use the faster shade functions when using
527 * GL_COLOR_MATERIAL, and we can also now use the precomputed
528 * values in the slower shading functions, which further offsets
529 * the cost of doing this here.
530 */
531void gl_update_material( GLcontext *ctx,
Brian Paulde82d062000-06-26 23:37:46 +0000532 const struct gl_material src[2],
jtgafb833d1999-08-19 00:55:39 +0000533 GLuint bitmask )
534{
535 struct gl_light *light, *list = &ctx->Light.EnabledList;
jtgafb833d1999-08-19 00:55:39 +0000536
537 if (ctx->Light.ColorMaterialEnabled)
538 bitmask &= ~ctx->Light.ColorMaterialBitmask;
539
Keith Whitwell06ac5921999-11-10 06:29:44 +0000540 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000541 fprintf(stderr, "gl_update_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000542
jtgafb833d1999-08-19 00:55:39 +0000543 if (!bitmask)
544 return;
545
Brian Paulde82d062000-06-26 23:37:46 +0000546 /* update material emission */
547 if (bitmask & FRONT_EMISSION_BIT) {
548 struct gl_material *mat = &ctx->Light.Material[0];
549 COPY_4FV( mat->Emission, src[0].Emission );
550 }
551 if (bitmask & BACK_EMISSION_BIT) {
552 struct gl_material *mat = &ctx->Light.Material[1];
553 COPY_4FV( mat->Emission, src[1].Emission );
554 }
555
556 /* update material ambience */
jtgafb833d1999-08-19 00:55:39 +0000557 if (bitmask & FRONT_AMBIENT_BIT) {
558 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000559 COPY_4FV( mat->Ambient, src[0].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000560 foreach (light, list) {
561 SCALE_3V( light->MatAmbient[0], light->Ambient, src[0].Ambient);
562 }
jtgafb833d1999-08-19 00:55:39 +0000563 }
564 if (bitmask & BACK_AMBIENT_BIT) {
565 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000566 COPY_4FV( mat->Ambient, src[1].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000567 foreach (light, list) {
568 SCALE_3V( light->MatAmbient[1], light->Ambient, src[1].Ambient);
569 }
jtgafb833d1999-08-19 00:55:39 +0000570 }
Brian Paulde82d062000-06-26 23:37:46 +0000571
572 /* update BaseColor = emission + scene's ambience * material's ambience */
573 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
574 struct gl_material *mat = &ctx->Light.Material[0];
575 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
576 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
577 }
578 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
579 struct gl_material *mat = &ctx->Light.Material[1];
580 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
581 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
582 }
583
584 /* update material diffuse values */
jtgafb833d1999-08-19 00:55:39 +0000585 if (bitmask & FRONT_DIFFUSE_BIT) {
586 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000587 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000588 SUB_3V( tmp, src[0].Diffuse, mat->Diffuse );
589 foreach (light, list) {
590 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
591 }
592 COPY_4FV( mat->Diffuse, src[0].Diffuse );
593 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
594 }
595 if (bitmask & BACK_DIFFUSE_BIT) {
596 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000597 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000598 SUB_3V( tmp, src[1].Diffuse, mat->Diffuse );
599 foreach (light, list) {
600 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
601 }
602 COPY_4FV( mat->Diffuse, src[1].Diffuse );
603 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
604 }
Brian Paulde82d062000-06-26 23:37:46 +0000605
606 /* update material specular values */
jtgafb833d1999-08-19 00:55:39 +0000607 if (bitmask & FRONT_SPECULAR_BIT) {
608 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000609 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000610 SUB_3V( tmp, src[0].Specular, mat->Specular );
611 foreach (light, list) {
612 if (light->Flags & LIGHT_SPECULAR) {
613 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
614 light->IsMatSpecular[0] =
615 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
616 }
617 }
618 COPY_4FV( mat->Specular, src[0].Specular );
619 }
620 if (bitmask & BACK_SPECULAR_BIT) {
621 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000622 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000623 SUB_3V( tmp, src[1].Specular, mat->Specular );
624 foreach (light, list) {
625 if (light->Flags & LIGHT_SPECULAR) {
626 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
627 light->IsMatSpecular[1] =
628 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
629 }
630 }
631 COPY_4FV( mat->Specular, src[1].Specular );
632 }
Brian Paulde82d062000-06-26 23:37:46 +0000633
jtgafb833d1999-08-19 00:55:39 +0000634 if (bitmask & FRONT_SHININESS_BIT) {
635 GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess;
636 gl_compute_shine_table( ctx, 0, shininess );
637 gl_compute_shine_table( ctx, 2, shininess * .5 );
638 }
639 if (bitmask & BACK_SHININESS_BIT) {
640 GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess;
641 gl_compute_shine_table( ctx, 1, shininess );
642 gl_compute_shine_table( ctx, 3, shininess * .5 );
643 }
Brian Paulde82d062000-06-26 23:37:46 +0000644
jtgafb833d1999-08-19 00:55:39 +0000645 if (bitmask & FRONT_INDEXES_BIT) {
646 ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
647 ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
648 ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
649 }
650 if (bitmask & BACK_INDEXES_BIT) {
651 ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
652 ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
653 ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
654 }
655
Keith Whitwell06ac5921999-11-10 06:29:44 +0000656 if (0)
657 {
658 struct gl_material *mat = &ctx->Light.Material[0];
659 fprintf(stderr, "update_mat emission : %f %f %f\n",
660 mat->Emission[0],
661 mat->Emission[1],
662 mat->Emission[2]);
663 fprintf(stderr, "update_mat specular : %f %f %f\n",
664 mat->Specular[0],
665 mat->Specular[1],
666 mat->Specular[2]);
667 fprintf(stderr, "update_mat diffuse : %f %f %f\n",
668 mat->Diffuse[0],
669 mat->Diffuse[1],
670 mat->Diffuse[2]);
671 fprintf(stderr, "update_mat ambient : %f %f %f\n",
672 mat->Ambient[0],
673 mat->Ambient[1],
674 mat->Ambient[2]);
675 }
jtgafb833d1999-08-19 00:55:39 +0000676}
677
678
679
680
Brian Paulde82d062000-06-26 23:37:46 +0000681/*
682 * Update the current materials from the given rgba color
683 * according to the bitmask in ColorMaterialBitmask, which is
684 * set by glColorMaterial().
685 */
jtgafb833d1999-08-19 00:55:39 +0000686void gl_update_color_material( GLcontext *ctx,
687 const GLubyte rgba[4] )
688{
689 struct gl_light *light, *list = &ctx->Light.EnabledList;
690 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
Brian Paulde82d062000-06-26 23:37:46 +0000691 GLfloat color[4];
jtgafb833d1999-08-19 00:55:39 +0000692
693 UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
Brian Paulfbd8f211999-11-11 01:22:25 +0000694
Keith Whitwell06ac5921999-11-10 06:29:44 +0000695 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000696 fprintf(stderr, "gl_update_color_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000697
Brian Paulde82d062000-06-26 23:37:46 +0000698 /* update emissive colors */
699 if (bitmask & FRONT_EMISSION_BIT) {
700 struct gl_material *mat = &ctx->Light.Material[0];
701 COPY_4FV( mat->Emission, color );
702 }
Brian Paulfbd8f211999-11-11 01:22:25 +0000703
Brian Paulde82d062000-06-26 23:37:46 +0000704 if (bitmask & BACK_EMISSION_BIT) {
705 struct gl_material *mat = &ctx->Light.Material[1];
706 COPY_4FV( mat->Emission, color );
707 }
708
709 /* update light->MatAmbient = light's ambient * material's ambient */
jtgafb833d1999-08-19 00:55:39 +0000710 if (bitmask & FRONT_AMBIENT_BIT) {
711 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000712 foreach (light, list) {
Brian Paulde82d062000-06-26 23:37:46 +0000713 SCALE_3V( light->MatAmbient[0], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000714 }
715 COPY_4FV( mat->Ambient, color );
716 }
717
718 if (bitmask & BACK_AMBIENT_BIT) {
719 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000720 foreach (light, list) {
Brian Paulde82d062000-06-26 23:37:46 +0000721 SCALE_3V( light->MatAmbient[1], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000722 }
723 COPY_4FV( mat->Ambient, color );
724 }
725
Brian Paulde82d062000-06-26 23:37:46 +0000726 /* update BaseColor = emission + scene's ambience * material's ambience */
727 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
728 struct gl_material *mat = &ctx->Light.Material[0];
729 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
730 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
731 }
732
733 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
734 struct gl_material *mat = &ctx->Light.Material[1];
735 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
736 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
737 }
738
739 /* update light->MatDiffuse = light's diffuse * material's diffuse */
jtgafb833d1999-08-19 00:55:39 +0000740 if (bitmask & FRONT_DIFFUSE_BIT) {
741 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000742 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000743 SUB_3V( tmp, color, mat->Diffuse );
744 foreach (light, list) {
745 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
746 }
747 COPY_4FV( mat->Diffuse, color );
748 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
749 }
750
751 if (bitmask & BACK_DIFFUSE_BIT) {
752 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000753 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000754 SUB_3V( tmp, color, mat->Diffuse );
755 foreach (light, list) {
756 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
757 }
758 COPY_4FV( mat->Diffuse, color );
759 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
760 }
761
Brian Paulde82d062000-06-26 23:37:46 +0000762 /* update light->MatSpecular = light's specular * material's specular */
jtgafb833d1999-08-19 00:55:39 +0000763 if (bitmask & FRONT_SPECULAR_BIT) {
764 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000765 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000766 SUB_3V( tmp, color, mat->Specular );
767 foreach (light, list) {
768 if (light->Flags & LIGHT_SPECULAR) {
769 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
770 light->IsMatSpecular[0] =
771 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
772 }
773 }
774 COPY_4FV( mat->Specular, color );
775 }
Brian Paulde82d062000-06-26 23:37:46 +0000776
jtgafb833d1999-08-19 00:55:39 +0000777 if (bitmask & BACK_SPECULAR_BIT) {
778 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000779 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000780 SUB_3V( tmp, color, mat->Specular );
781 foreach (light, list) {
782 if (light->Flags & LIGHT_SPECULAR) {
783 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
784 light->IsMatSpecular[1] =
785 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
786 }
787 }
788 COPY_4FV( mat->Specular, color );
789 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000790
791 if (0)
792 {
793 struct gl_material *mat = &ctx->Light.Material[0];
794 fprintf(stderr, "update_color_mat emission : %f %f %f\n",
795 mat->Emission[0],
796 mat->Emission[1],
797 mat->Emission[2]);
798 fprintf(stderr, "update_color_mat specular : %f %f %f\n",
799 mat->Specular[0],
800 mat->Specular[1],
801 mat->Specular[2]);
802 fprintf(stderr, "update_color_mat diffuse : %f %f %f\n",
803 mat->Diffuse[0],
804 mat->Diffuse[1],
805 mat->Diffuse[2]);
806 fprintf(stderr, "update_color_mat ambient : %f %f %f\n",
807 mat->Ambient[0],
808 mat->Ambient[1],
809 mat->Ambient[2]);
810 }
jtgafb833d1999-08-19 00:55:39 +0000811}
812
813
814
815
Brian Paulfbd8f211999-11-11 01:22:25 +0000816void
817_mesa_ColorMaterial( GLenum face, GLenum mode )
jtgafb833d1999-08-19 00:55:39 +0000818{
Brian Paulfbd8f211999-11-11 01:22:25 +0000819 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000820 GLuint bitmask;
821 GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
822 FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
823 FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
824 FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
825
826 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
827
Keith Whitwell06ac5921999-11-10 06:29:44 +0000828 if (MESA_VERBOSE&VERBOSE_API)
829 fprintf(stderr, "glColorMaterial %s %s\n",
830 gl_lookup_enum_by_nr(face),
831 gl_lookup_enum_by_nr(mode));
832
jtgafb833d1999-08-19 00:55:39 +0000833 bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
834
835 if (bitmask != 0) {
836 ctx->Light.ColorMaterialBitmask = bitmask;
837 ctx->Light.ColorMaterialFace = face;
838 ctx->Light.ColorMaterialMode = mode;
839 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000840
841 if (ctx->Light.ColorMaterialEnabled)
842 gl_update_color_material( ctx, ctx->Current.ByteColor );
jtgafb833d1999-08-19 00:55:39 +0000843}
844
845
846
Brian Paulfbd8f211999-11-11 01:22:25 +0000847
848void
849_mesa_Materialf( GLenum face, GLenum pname, GLfloat param )
850{
851 _mesa_Materialfv( face, pname, &param );
852}
853
854
jtgafb833d1999-08-19 00:55:39 +0000855/* KW: This is now called directly (ie by name) from the glMaterial*
856 * API functions.
857 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000858void
859_mesa_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
jtgafb833d1999-08-19 00:55:39 +0000860{
Brian Paulfbd8f211999-11-11 01:22:25 +0000861 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000862 struct immediate *IM;
863 struct gl_material *mat;
864 GLuint bitmask;
865 GLuint count;
866
867 bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" );
868 if (bitmask == 0)
869 return;
870
871 IM = ctx->input;
872 count = IM->Count;
873
Keith Whitwelld4714731999-10-19 18:37:02 +0000874 if (!IM->Material) {
875 IM->Material =
876 (struct gl_material (*)[2]) MALLOC( sizeof(struct gl_material) *
877 VB_SIZE * 2 );
878 IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * VB_SIZE );
879 }
880
881
jtgafb833d1999-08-19 00:55:39 +0000882 if (!(IM->Flag[count] & VERT_MATERIAL)) {
883 IM->Flag[count] |= VERT_MATERIAL;
Keith Whitwelld4714731999-10-19 18:37:02 +0000884 IM->MaterialMask[count] = 0;
jtgafb833d1999-08-19 00:55:39 +0000885 }
886
Brian Paulfbd8f211999-11-11 01:22:25 +0000887
jtgafb833d1999-08-19 00:55:39 +0000888 IM->MaterialMask[count] |= bitmask;
889 mat = IM->Material[count];
jtgafb833d1999-08-19 00:55:39 +0000890
891 if (bitmask & FRONT_AMBIENT_BIT) {
892 COPY_4FV( mat[0].Ambient, params );
893 }
894 if (bitmask & BACK_AMBIENT_BIT) {
895 COPY_4FV( mat[1].Ambient, params );
896 }
897 if (bitmask & FRONT_DIFFUSE_BIT) {
898 COPY_4FV( mat[0].Diffuse, params );
899 }
900 if (bitmask & BACK_DIFFUSE_BIT) {
901 COPY_4FV( mat[1].Diffuse, params );
902 }
903 if (bitmask & FRONT_SPECULAR_BIT) {
904 COPY_4FV( mat[0].Specular, params );
905 }
906 if (bitmask & BACK_SPECULAR_BIT) {
907 COPY_4FV( mat[1].Specular, params );
908 }
909 if (bitmask & FRONT_EMISSION_BIT) {
910 COPY_4FV( mat[0].Emission, params );
911 }
912 if (bitmask & BACK_EMISSION_BIT) {
913 COPY_4FV( mat[1].Emission, params );
914 }
915 if (bitmask & FRONT_SHININESS_BIT) {
916 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
917 mat[0].Shininess = shininess;
918 }
919 if (bitmask & BACK_SHININESS_BIT) {
920 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
921 mat[1].Shininess = shininess;
922 }
923 if (bitmask & FRONT_INDEXES_BIT) {
924 mat[0].AmbientIndex = params[0];
925 mat[0].DiffuseIndex = params[1];
926 mat[0].SpecularIndex = params[2];
927 }
928 if (bitmask & BACK_INDEXES_BIT) {
929 mat[1].AmbientIndex = params[0];
930 mat[1].DiffuseIndex = params[1];
931 mat[1].SpecularIndex = params[2];
932 }
933}
934
935
Brian Paulfbd8f211999-11-11 01:22:25 +0000936void
937_mesa_Materiali(GLenum face, GLenum pname, GLint param )
jtgafb833d1999-08-19 00:55:39 +0000938{
Brian Paulfbd8f211999-11-11 01:22:25 +0000939 _mesa_Materialiv(face, pname, &param);
940}
941
942
943void
944_mesa_Materialiv(GLenum face, GLenum pname, const GLint *params )
945{
946 GLfloat fparam[4];
947 switch (pname) {
948 case GL_AMBIENT:
949 case GL_DIFFUSE:
950 case GL_SPECULAR:
951 case GL_EMISSION:
952 case GL_AMBIENT_AND_DIFFUSE:
953 fparam[0] = INT_TO_FLOAT( params[0] );
954 fparam[1] = INT_TO_FLOAT( params[1] );
955 fparam[2] = INT_TO_FLOAT( params[2] );
956 fparam[3] = INT_TO_FLOAT( params[3] );
957 break;
958 case GL_SHININESS:
959 fparam[0] = (GLfloat) params[0];
960 break;
961 case GL_COLOR_INDEXES:
962 fparam[0] = (GLfloat) params[0];
963 fparam[1] = (GLfloat) params[1];
964 fparam[2] = (GLfloat) params[2];
965 break;
966 default:
967 /* Error will be caught later in gl_Materialfv */
968 ;
969 }
970 _mesa_Materialfv(face, pname, fparam);
971}
972
973
974void
975_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
976{
977 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000978 GLuint f;
979
980 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
981
982 if (face==GL_FRONT) {
983 f = 0;
984 }
985 else if (face==GL_BACK) {
986 f = 1;
987 }
988 else {
989 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
990 return;
991 }
992 switch (pname) {
993 case GL_AMBIENT:
994 COPY_4FV( params, ctx->Light.Material[f].Ambient );
995 break;
996 case GL_DIFFUSE:
997 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
998 break;
999 case GL_SPECULAR:
1000 COPY_4FV( params, ctx->Light.Material[f].Specular );
1001 break;
1002 case GL_EMISSION:
1003 COPY_4FV( params, ctx->Light.Material[f].Emission );
1004 break;
1005 case GL_SHININESS:
1006 *params = ctx->Light.Material[f].Shininess;
1007 break;
1008 case GL_COLOR_INDEXES:
1009 params[0] = ctx->Light.Material[f].AmbientIndex;
1010 params[1] = ctx->Light.Material[f].DiffuseIndex;
1011 params[2] = ctx->Light.Material[f].SpecularIndex;
1012 break;
1013 default:
1014 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1015 }
1016}
1017
1018
1019
Brian Paulfbd8f211999-11-11 01:22:25 +00001020void
1021_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
jtgafb833d1999-08-19 00:55:39 +00001022{
Brian Paulfbd8f211999-11-11 01:22:25 +00001023 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001024 GLuint f;
1025
1026 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
1027
1028 if (face==GL_FRONT) {
1029 f = 0;
1030 }
1031 else if (face==GL_BACK) {
1032 f = 1;
1033 }
1034 else {
1035 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
1036 return;
1037 }
1038 switch (pname) {
1039 case GL_AMBIENT:
1040 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
1041 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
1042 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
1043 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
1044 break;
1045 case GL_DIFFUSE:
1046 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
1047 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
1048 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
1049 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
1050 break;
1051 case GL_SPECULAR:
1052 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
1053 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
1054 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
1055 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
1056 break;
1057 case GL_EMISSION:
1058 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
1059 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
1060 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
1061 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
1062 break;
1063 case GL_SHININESS:
1064 *params = ROUNDF( ctx->Light.Material[f].Shininess );
1065 break;
1066 case GL_COLOR_INDEXES:
1067 params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
1068 params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
1069 params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
1070 break;
1071 default:
1072 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1073 }
1074}
1075
1076
1077
1078
1079/**********************************************************************/
1080/***** Lighting computation *****/
1081/**********************************************************************/
1082
1083
1084/*
1085 * Notes:
1086 * When two-sided lighting is enabled we compute the color (or index)
1087 * for both the front and back side of the primitive. Then, when the
1088 * orientation of the facet is later learned, we can determine which
1089 * color (or index) to use for rendering.
1090 *
1091 * KW: We now know orientation in advance and only shade for
1092 * the side or sides which are actually required.
1093 *
1094 * Variables:
1095 * n = normal vector
1096 * V = vertex position
1097 * P = light source position
1098 * Pe = (0,0,0,1)
1099 *
1100 * Precomputed:
1101 * IF P[3]==0 THEN
1102 * // light at infinity
1103 * IF local_viewer THEN
1104 * VP_inf_norm = unit vector from V to P // Precompute
1105 * ELSE
1106 * // eye at infinity
1107 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1108 * ENDIF
1109 * ENDIF
1110 *
1111 * Functions:
1112 * Normalize( v ) = normalized vector v
1113 * Magnitude( v ) = length of vector v
1114 */
1115
1116
1117
1118/*
1119 * Whenever the spotlight exponent for a light changes we must call
1120 * this function to recompute the exponent lookup table.
1121 */
1122void gl_compute_spot_exp_table( struct gl_light *l )
1123{
1124 int i;
1125 double exponent = l->SpotExponent;
1126 double tmp = 0;
1127 int clamp = 0;
1128
1129 l->SpotExpTable[0][0] = 0.0;
1130
1131 for (i=EXP_TABLE_SIZE-1;i>0;i--) {
1132 if (clamp == 0) {
1133 tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
1134 if (tmp < FLT_MIN*100.0) {
1135 tmp = 0.0;
1136 clamp = 1;
1137 }
1138 }
1139 l->SpotExpTable[i][0] = tmp;
1140 }
1141 for (i=0;i<EXP_TABLE_SIZE-1;i++) {
1142 l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
1143 }
1144 l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
1145}
1146
1147
1148
1149
1150/* Calculate a new shine table. Doing this here saves a branch in
1151 * lighting, and the cost of doing it early may be partially offset
1152 * by keeping a MRU cache of shine tables for various shine values.
1153 */
1154static void compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
1155{
1156 int i;
1157 GLfloat *m = tab->tab;
1158
1159 m[0] = 0;
1160 if (shininess == 0) {
1161 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
1162 m[i] = 1;
1163 } else {
1164 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++) {
1165 double t = pow( i/(GLfloat)SHINE_TABLE_SIZE, shininess );
1166 m[i] = 0;
1167 if (t > 1e-20) m[i] = t;
1168 }
1169 }
1170
1171 tab->shininess = shininess;
1172}
1173
1174#define DISTSQR(a,b) ((a-b)*(a-b))
1175
1176void gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
1177{
1178 struct gl_shine_tab *list = ctx->ShineTabList;
1179 struct gl_shine_tab *s;
1180
1181 foreach(s, list)
1182 if ( DISTSQR(s->shininess, shininess) < 1e-4 )
1183 break;
1184
1185 if (s == list)
1186 {
1187 foreach(s, list)
1188 if (s->refcount == 0) break;
1189
1190 compute_shine_table( s, shininess );
1191 }
1192
1193 ctx->ShineTable[i]->refcount--;
1194 ctx->ShineTable[i] = s;
1195 move_to_tail( list, s );
1196 s->refcount++;
1197}
1198
1199
1200
Brian Paul16a9efe2000-01-13 00:29:02 +00001201#if 0
1202static void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
jtgafb833d1999-08-19 00:55:39 +00001203{
1204 GLuint i;
1205
1206 if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) {
1207 gl_compute_shine_table( ctx, 0, l->Material[0].Shininess );
1208 gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 );
1209 }
1210
1211 if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) {
1212 gl_compute_shine_table( ctx, 1, l->Material[1].Shininess );
1213 gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 );
1214 }
1215
1216 make_empty_list( &l->EnabledList );
1217 for (i = 0 ; i < MAX_LIGHTS ; i++) {
1218 if (l->Light[i].Enabled)
1219 insert_at_tail( &l->EnabledList, &l->Light[i] );
1220 }
1221}
Brian Paul16a9efe2000-01-13 00:29:02 +00001222#endif
jtgafb833d1999-08-19 00:55:39 +00001223
1224
1225/*
1226 * Examine current lighting parameters to determine if the optimized lighting
1227 * function can be used.
1228 * Also, precompute some lighting values such as the products of light
1229 * source and material ambient, diffuse and specular coefficients.
1230 */
1231void gl_update_lighting( GLcontext *ctx )
1232{
1233 struct gl_light *light;
1234
1235 ctx->Light.Flags = 0;
1236
1237 foreach(light, &ctx->Light.EnabledList) {
1238
1239 light->Flags = 0;
1240
1241 if (light->EyePosition[3] != 0.0F)
1242 light->Flags |= LIGHT_POSITIONAL;
1243
1244 if (LEN_SQUARED_3FV(light->Specular) > 1e-16)
1245 light->Flags |= LIGHT_SPECULAR;
1246
1247 if (light->SpotCutoff != 180.0F)
1248 light->Flags |= LIGHT_SPOT;
1249
1250 ctx->Light.Flags |= light->Flags;
1251 }
1252
1253 ctx->Light.NeedVertices =
1254 ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
1255 (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) ||
1256 (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR)));
1257
1258
1259 /* Precompute some shading values.
1260 */
1261 if (ctx->Visual->RGBAflag)
1262 {
1263 GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1);
1264 GLuint side;
1265 for (side=0; side < sides; side++) {
1266 struct gl_material *mat = &ctx->Light.Material[side];
1267
1268 COPY_3V(ctx->Light.BaseColor[side], mat->Emission);
1269 ACC_SCALE_3V(ctx->Light.BaseColor[side],
1270 ctx->Light.Model.Ambient,
1271 mat->Ambient);
1272
1273 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side],
1274 ctx->Light.Material[side].Diffuse[3] );
1275 }
1276
1277 foreach (light, &ctx->Light.EnabledList) {
1278 for (side=0; side< sides; side++) {
1279 struct gl_material *mat = &ctx->Light.Material[side];
1280 SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse );
1281 SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient );
1282 ACC_3V( ctx->Light.BaseColor[side], light->MatAmbient[side] );
1283 if (light->Flags & LIGHT_SPECULAR)
1284 {
1285 SCALE_3V( light->MatSpecular[side], light->Specular,
1286 mat->Specular);
1287 light->IsMatSpecular[side] =
1288 (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16);
1289 }
1290 else
1291 light->IsMatSpecular[side] = 0;
1292 }
1293 }
1294 }
1295 else
1296 {
1297 static GLfloat ci[3] = { .30, .59, .11 };
1298
1299 foreach(light, &ctx->Light.EnabledList) {
1300 light->dli = DOT3(ci, light->Diffuse);
1301 light->sli = DOT3(ci, light->Specular);
1302 }
1303 }
1304}
1305
1306/* Need to seriously restrict the circumstances under which these
1307 * calc's are performed.
1308 */
1309void gl_compute_light_positions( GLcontext *ctx )
1310{
1311 struct gl_light *light;
1312
Brian Paulde82d062000-06-26 23:37:46 +00001313 if (1 /*ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer*/) {
1314 static const GLfloat eye_z[3] = { 0, 0, 1 };
1315 if (ctx->NeedEyeCoords) {
jtgafb833d1999-08-19 00:55:39 +00001316 COPY_3V( ctx->EyeZDir, eye_z );
1317 }
Brian Paulde82d062000-06-26 23:37:46 +00001318 else {
1319 TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m );
1320 }
jtgafb833d1999-08-19 00:55:39 +00001321 }
1322
1323 foreach (light, &ctx->Light.EnabledList) {
1324
Brian Paulde82d062000-06-26 23:37:46 +00001325 if (ctx->NeedEyeCoords) {
jtgafb833d1999-08-19 00:55:39 +00001326 COPY_4FV( light->Position, light->EyePosition );
1327 }
Brian Paulde82d062000-06-26 23:37:46 +00001328 else {
1329 TRANSFORM_POINT( light->Position, ctx->ModelView.inv,
1330 light->EyePosition );
1331 }
jtgafb833d1999-08-19 00:55:39 +00001332
Brian Paulde82d062000-06-26 23:37:46 +00001333 if (!(light->Flags & LIGHT_POSITIONAL)) {
jtgafb833d1999-08-19 00:55:39 +00001334 /* VP (VP) = Normalize( Position ) */
1335 COPY_3V( light->VP_inf_norm, light->Position );
1336 NORMALIZE_3FV( light->VP_inf_norm );
1337
Brian Paulde82d062000-06-26 23:37:46 +00001338 if (!ctx->Light.Model.LocalViewer) {
jtgafb833d1999-08-19 00:55:39 +00001339 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1340 ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir);
1341 NORMALIZE_3FV( light->h_inf_norm );
1342 }
jtgafb833d1999-08-19 00:55:39 +00001343 light->VP_inf_spot_attenuation = 1.0;
1344 }
1345
Brian Paulde82d062000-06-26 23:37:46 +00001346 if (light->Flags & LIGHT_SPOT) {
jtgafb833d1999-08-19 00:55:39 +00001347 if (ctx->NeedEyeNormals) {
1348 COPY_3V( light->NormDirection, light->EyeDirection );
Brian Paulde82d062000-06-26 23:37:46 +00001349 }
1350 else {
jtgafb833d1999-08-19 00:55:39 +00001351 TRANSFORM_NORMAL( light->NormDirection,
1352 light->EyeDirection,
1353 ctx->ModelView.m);
1354 }
1355
1356 NORMALIZE_3FV( light->NormDirection );
1357
1358
1359 /* Unlikely occurrance?
1360 */
1361 if (!(light->Flags & LIGHT_POSITIONAL)) {
1362 GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm,
1363 light->NormDirection);
1364
1365 if (PV_dot_dir > light->CosCutoff) {
1366 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1367 int k = (int) x;
1368 light->VP_inf_spot_attenuation =
1369 (light->SpotExpTable[k][0] +
1370 (x-k)*light->SpotExpTable[k][1]);
1371 }
Brian Paulde82d062000-06-26 23:37:46 +00001372 else {
jtgafb833d1999-08-19 00:55:39 +00001373 light->VP_inf_spot_attenuation = 0;
Brian Paulde82d062000-06-26 23:37:46 +00001374 }
jtgafb833d1999-08-19 00:55:39 +00001375 }
1376 }
1377 }
1378}
1379
1380
1381
1382
1383
1384void gl_update_normal_transform( GLcontext *ctx )
1385{
1386 GLuint new_flag = 0;
1387 normal_func *last = ctx->NormalTransform;
1388
1389 ctx->vb_rescale_factor = 1.0;
1390
1391 if (ctx->NeedEyeCoords) {
1392 if (ctx->NeedNormals) {
1393 GLuint transform = NORM_TRANSFORM_NO_ROT;
1394
1395 if (ctx->ModelView.flags & (MAT_FLAG_GENERAL |
1396 MAT_FLAG_ROTATION |
1397 MAT_FLAG_GENERAL_3D |
1398 MAT_FLAG_PERSPECTIVE))
1399 transform = NORM_TRANSFORM;
1400
1401
1402 new_flag = ctx->NewState & NEW_MODELVIEW;
1403 ctx->vb_rescale_factor = ctx->rescale_factor;
1404
1405 if (ctx->Transform.Normalize)
1406 {
1407 ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE];
1408 }
1409 else if (ctx->Transform.RescaleNormals &&
1410 ctx->rescale_factor != 1.0)
1411 {
1412 ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE];
1413 }
1414 else
1415 {
1416 ctx->NormalTransform = gl_normal_tab[transform];
1417 }
1418 } else {
1419 ctx->NormalTransform = 0;
1420 }
1421 }
1422 else {
1423 if (ctx->NeedNormals) {
1424 ctx->vb_rescale_factor = 1.0/ctx->rescale_factor;
1425
1426 if (ctx->Transform.Normalize)
1427 {
1428 ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE];
1429 }
1430 else if (!ctx->Transform.RescaleNormals &&
1431 ctx->rescale_factor != 1.0)
1432 {
1433 ctx->NormalTransform = gl_normal_tab[NORM_RESCALE];
1434 }
1435 else
1436 {
1437 ctx->NormalTransform = 0;
1438 }
1439 } else {
1440 ctx->NormalTransform = 0;
1441 }
1442 }
1443
1444 if (last != ctx->NormalTransform || new_flag)
1445 ctx->NewState |= NEW_NORMAL_TRANSFORM;
1446}
1447