blob: 1ed1178e124f657a33701cdea075e6c65415db54 [file] [log] [blame]
Brian Paulba643a22000-10-28 18:34:48 +00001/* $Id: light.c,v 1.19 2000/10/28 18:34:48 brianp 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
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;
Keith Whitwellfe5d67d2000-10-27 16:44:40 +0000388 if (!ctx->Fog.ColorSumEnabled)
389 CLEAR_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000390 }
jtgafb833d1999-08-19 00:55:39 +0000391 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
392 ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
Brian Paul8acb3a11999-11-22 18:58:53 +0000393 SET_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
Brian Paulf3f9b771999-10-19 20:32:40 +0000394 }
395 else {
jtgafb833d1999-08-19 00:55:39 +0000396 gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
Brian Paulf3f9b771999-10-19 20:32:40 +0000397 }
398 ctx->NewState |= NEW_RASTER_OPS;
jtgafb833d1999-08-19 00:55:39 +0000399 break;
400 default:
401 gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
402 break;
403 }
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000404
405 if (ctx->Driver.LightModelfv)
406 ctx->Driver.LightModelfv( ctx, pname, params );
407
jtgafb833d1999-08-19 00:55:39 +0000408 ctx->NewState |= NEW_LIGHTING;
409}
410
411
Brian Paulfbd8f211999-11-11 01:22:25 +0000412void
413_mesa_LightModeliv( GLenum pname, const GLint *params )
414{
415 GLfloat fparam[4];
416 GET_CURRENT_CONTEXT(ctx);
417 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModeliv");
418
419 switch (pname) {
420 case GL_LIGHT_MODEL_AMBIENT:
421 fparam[0] = INT_TO_FLOAT( params[0] );
422 fparam[1] = INT_TO_FLOAT( params[1] );
423 fparam[2] = INT_TO_FLOAT( params[2] );
424 fparam[3] = INT_TO_FLOAT( params[3] );
425 break;
426 case GL_LIGHT_MODEL_LOCAL_VIEWER:
427 case GL_LIGHT_MODEL_TWO_SIDE:
428 case GL_LIGHT_MODEL_COLOR_CONTROL:
429 fparam[0] = (GLfloat) params[0];
430 break;
431 default:
432 /* Error will be caught later in gl_LightModelfv */
433 ;
434 }
435 _mesa_LightModelfv( pname, fparam );
436}
437
438
439void
440_mesa_LightModeli( GLenum pname, GLint param )
441{
442 _mesa_LightModeliv( pname, &param );
443}
444
445
446void
447_mesa_LightModelf( GLenum pname, GLfloat param )
448{
449 _mesa_LightModelfv( pname, &param );
450}
451
jtgafb833d1999-08-19 00:55:39 +0000452
453
454/********** MATERIAL **********/
455
456
457/*
458 * Given a face and pname value (ala glColorMaterial), compute a bitmask
459 * of the targeted material values.
460 */
461GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
462 GLuint legal,
463 const char *where )
464{
465 GLuint bitmask = 0;
466
467 /* Make a bitmask indicating what material attribute(s) we're updating */
468 switch (pname) {
469 case GL_EMISSION:
470 bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
471 break;
472 case GL_AMBIENT:
473 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
474 break;
475 case GL_DIFFUSE:
476 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
477 break;
478 case GL_SPECULAR:
479 bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
480 break;
481 case GL_SHININESS:
482 bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
483 break;
484 case GL_AMBIENT_AND_DIFFUSE:
485 bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
486 bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
487 break;
488 case GL_COLOR_INDEXES:
489 bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
490 break;
491 default:
492 gl_error( ctx, GL_INVALID_ENUM, where );
493 return 0;
494 }
495
496 if (face==GL_FRONT) {
497 bitmask &= FRONT_MATERIAL_BITS;
498 }
499 else if (face==GL_BACK) {
500 bitmask &= BACK_MATERIAL_BITS;
501 }
502 else if (face != GL_FRONT_AND_BACK) {
503 gl_error( ctx, GL_INVALID_ENUM, where );
504 return 0;
505 }
506
507 if (bitmask & ~legal) {
508 gl_error( ctx, GL_INVALID_ENUM, where );
509 return 0;
510 }
511
512 return bitmask;
513}
514
515
516
jtgafb833d1999-08-19 00:55:39 +0000517/*
518 * Check if the global material has to be updated with info that was
519 * associated with a vertex via glMaterial.
520 * This function is used when any material values get changed between
521 * glBegin/glEnd either by calling glMaterial() or by calling glColor()
522 * when GL_COLOR_MATERIAL is enabled.
523 *
Brian Paulde82d062000-06-26 23:37:46 +0000524 * src[0] is front material, src[1] is back material
525 *
jtgafb833d1999-08-19 00:55:39 +0000526 * KW: Added code here to keep the precomputed variables uptodate.
527 * This means we can use the faster shade functions when using
528 * GL_COLOR_MATERIAL, and we can also now use the precomputed
529 * values in the slower shading functions, which further offsets
530 * the cost of doing this here.
531 */
532void gl_update_material( GLcontext *ctx,
Brian Paulde82d062000-06-26 23:37:46 +0000533 const struct gl_material src[2],
jtgafb833d1999-08-19 00:55:39 +0000534 GLuint bitmask )
535{
536 struct gl_light *light, *list = &ctx->Light.EnabledList;
jtgafb833d1999-08-19 00:55:39 +0000537
538 if (ctx->Light.ColorMaterialEnabled)
539 bitmask &= ~ctx->Light.ColorMaterialBitmask;
540
Keith Whitwell06ac5921999-11-10 06:29:44 +0000541 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000542 fprintf(stderr, "gl_update_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000543
jtgafb833d1999-08-19 00:55:39 +0000544 if (!bitmask)
545 return;
546
Brian Paulde82d062000-06-26 23:37:46 +0000547 /* update material emission */
548 if (bitmask & FRONT_EMISSION_BIT) {
549 struct gl_material *mat = &ctx->Light.Material[0];
550 COPY_4FV( mat->Emission, src[0].Emission );
551 }
552 if (bitmask & BACK_EMISSION_BIT) {
553 struct gl_material *mat = &ctx->Light.Material[1];
554 COPY_4FV( mat->Emission, src[1].Emission );
555 }
556
557 /* update material ambience */
jtgafb833d1999-08-19 00:55:39 +0000558 if (bitmask & FRONT_AMBIENT_BIT) {
559 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000560 COPY_4FV( mat->Ambient, src[0].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000561 foreach (light, list) {
562 SCALE_3V( light->MatAmbient[0], light->Ambient, src[0].Ambient);
563 }
jtgafb833d1999-08-19 00:55:39 +0000564 }
565 if (bitmask & BACK_AMBIENT_BIT) {
566 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000567 COPY_4FV( mat->Ambient, src[1].Ambient );
Brian Paulde82d062000-06-26 23:37:46 +0000568 foreach (light, list) {
569 SCALE_3V( light->MatAmbient[1], light->Ambient, src[1].Ambient);
570 }
jtgafb833d1999-08-19 00:55:39 +0000571 }
Brian Paulde82d062000-06-26 23:37:46 +0000572
573 /* update BaseColor = emission + scene's ambience * material's ambience */
574 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
575 struct gl_material *mat = &ctx->Light.Material[0];
576 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
577 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
578 }
579 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
580 struct gl_material *mat = &ctx->Light.Material[1];
581 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
582 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
583 }
584
585 /* update material diffuse values */
jtgafb833d1999-08-19 00:55:39 +0000586 if (bitmask & FRONT_DIFFUSE_BIT) {
587 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000588 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000589 SUB_3V( tmp, src[0].Diffuse, mat->Diffuse );
590 foreach (light, list) {
591 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
592 }
593 COPY_4FV( mat->Diffuse, src[0].Diffuse );
594 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
595 }
596 if (bitmask & BACK_DIFFUSE_BIT) {
597 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000598 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000599 SUB_3V( tmp, src[1].Diffuse, mat->Diffuse );
600 foreach (light, list) {
601 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
602 }
603 COPY_4FV( mat->Diffuse, src[1].Diffuse );
604 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
605 }
Brian Paulde82d062000-06-26 23:37:46 +0000606
607 /* update material specular values */
jtgafb833d1999-08-19 00:55:39 +0000608 if (bitmask & FRONT_SPECULAR_BIT) {
609 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000610 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000611 SUB_3V( tmp, src[0].Specular, mat->Specular );
612 foreach (light, list) {
613 if (light->Flags & LIGHT_SPECULAR) {
614 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
615 light->IsMatSpecular[0] =
616 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
617 }
618 }
619 COPY_4FV( mat->Specular, src[0].Specular );
620 }
621 if (bitmask & BACK_SPECULAR_BIT) {
622 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000623 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000624 SUB_3V( tmp, src[1].Specular, mat->Specular );
625 foreach (light, list) {
626 if (light->Flags & LIGHT_SPECULAR) {
627 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
628 light->IsMatSpecular[1] =
629 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
630 }
631 }
632 COPY_4FV( mat->Specular, src[1].Specular );
633 }
Brian Paulde82d062000-06-26 23:37:46 +0000634
jtgafb833d1999-08-19 00:55:39 +0000635 if (bitmask & FRONT_SHININESS_BIT) {
636 GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess;
637 gl_compute_shine_table( ctx, 0, shininess );
638 gl_compute_shine_table( ctx, 2, shininess * .5 );
639 }
640 if (bitmask & BACK_SHININESS_BIT) {
641 GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess;
642 gl_compute_shine_table( ctx, 1, shininess );
643 gl_compute_shine_table( ctx, 3, shininess * .5 );
644 }
Brian Paulde82d062000-06-26 23:37:46 +0000645
jtgafb833d1999-08-19 00:55:39 +0000646 if (bitmask & FRONT_INDEXES_BIT) {
647 ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
648 ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
649 ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
650 }
651 if (bitmask & BACK_INDEXES_BIT) {
652 ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
653 ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
654 ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
655 }
656
Keith Whitwell06ac5921999-11-10 06:29:44 +0000657 if (0)
658 {
659 struct gl_material *mat = &ctx->Light.Material[0];
660 fprintf(stderr, "update_mat emission : %f %f %f\n",
661 mat->Emission[0],
662 mat->Emission[1],
663 mat->Emission[2]);
664 fprintf(stderr, "update_mat specular : %f %f %f\n",
665 mat->Specular[0],
666 mat->Specular[1],
667 mat->Specular[2]);
668 fprintf(stderr, "update_mat diffuse : %f %f %f\n",
669 mat->Diffuse[0],
670 mat->Diffuse[1],
671 mat->Diffuse[2]);
672 fprintf(stderr, "update_mat ambient : %f %f %f\n",
673 mat->Ambient[0],
674 mat->Ambient[1],
675 mat->Ambient[2]);
676 }
jtgafb833d1999-08-19 00:55:39 +0000677}
678
679
680
681
Brian Paulde82d062000-06-26 23:37:46 +0000682/*
683 * Update the current materials from the given rgba color
684 * according to the bitmask in ColorMaterialBitmask, which is
685 * set by glColorMaterial().
686 */
jtgafb833d1999-08-19 00:55:39 +0000687void gl_update_color_material( GLcontext *ctx,
Brian Paulba643a22000-10-28 18:34:48 +0000688 const GLchan rgba[4] )
jtgafb833d1999-08-19 00:55:39 +0000689{
690 struct gl_light *light, *list = &ctx->Light.EnabledList;
691 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
Brian Paulde82d062000-06-26 23:37:46 +0000692 GLfloat color[4];
jtgafb833d1999-08-19 00:55:39 +0000693
694 UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
Brian Paulfbd8f211999-11-11 01:22:25 +0000695
Keith Whitwell06ac5921999-11-10 06:29:44 +0000696 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
Brian Paulde82d062000-06-26 23:37:46 +0000697 fprintf(stderr, "gl_update_color_material, mask 0x%x\n", bitmask);
Keith Whitwell06ac5921999-11-10 06:29:44 +0000698
Brian Paulde82d062000-06-26 23:37:46 +0000699 /* update emissive colors */
700 if (bitmask & FRONT_EMISSION_BIT) {
701 struct gl_material *mat = &ctx->Light.Material[0];
702 COPY_4FV( mat->Emission, color );
703 }
Brian Paulfbd8f211999-11-11 01:22:25 +0000704
Brian Paulde82d062000-06-26 23:37:46 +0000705 if (bitmask & BACK_EMISSION_BIT) {
706 struct gl_material *mat = &ctx->Light.Material[1];
707 COPY_4FV( mat->Emission, color );
708 }
709
710 /* update light->MatAmbient = light's ambient * material's ambient */
jtgafb833d1999-08-19 00:55:39 +0000711 if (bitmask & FRONT_AMBIENT_BIT) {
712 struct gl_material *mat = &ctx->Light.Material[0];
jtgafb833d1999-08-19 00:55:39 +0000713 foreach (light, list) {
Brian Paulde82d062000-06-26 23:37:46 +0000714 SCALE_3V( light->MatAmbient[0], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000715 }
716 COPY_4FV( mat->Ambient, color );
717 }
718
719 if (bitmask & BACK_AMBIENT_BIT) {
720 struct gl_material *mat = &ctx->Light.Material[1];
jtgafb833d1999-08-19 00:55:39 +0000721 foreach (light, list) {
Brian Paulde82d062000-06-26 23:37:46 +0000722 SCALE_3V( light->MatAmbient[1], light->Ambient, color);
jtgafb833d1999-08-19 00:55:39 +0000723 }
724 COPY_4FV( mat->Ambient, color );
725 }
726
Brian Paulde82d062000-06-26 23:37:46 +0000727 /* update BaseColor = emission + scene's ambience * material's ambience */
728 if (bitmask & (FRONT_EMISSION_BIT | FRONT_AMBIENT_BIT)) {
729 struct gl_material *mat = &ctx->Light.Material[0];
730 COPY_3V( ctx->Light.BaseColor[0], mat->Emission );
731 ACC_SCALE_3V( ctx->Light.BaseColor[0], mat->Ambient, ctx->Light.Model.Ambient );
732 }
733
734 if (bitmask & (BACK_EMISSION_BIT | BACK_AMBIENT_BIT)) {
735 struct gl_material *mat = &ctx->Light.Material[1];
736 COPY_3V( ctx->Light.BaseColor[1], mat->Emission );
737 ACC_SCALE_3V( ctx->Light.BaseColor[1], mat->Ambient, ctx->Light.Model.Ambient );
738 }
739
740 /* update light->MatDiffuse = light's diffuse * material's diffuse */
jtgafb833d1999-08-19 00:55:39 +0000741 if (bitmask & FRONT_DIFFUSE_BIT) {
742 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000743 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000744 SUB_3V( tmp, color, mat->Diffuse );
745 foreach (light, list) {
746 ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
747 }
748 COPY_4FV( mat->Diffuse, color );
749 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
750 }
751
752 if (bitmask & BACK_DIFFUSE_BIT) {
753 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000754 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000755 SUB_3V( tmp, color, mat->Diffuse );
756 foreach (light, list) {
757 ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
758 }
759 COPY_4FV( mat->Diffuse, color );
760 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
761 }
762
Brian Paulde82d062000-06-26 23:37:46 +0000763 /* update light->MatSpecular = light's specular * material's specular */
jtgafb833d1999-08-19 00:55:39 +0000764 if (bitmask & FRONT_SPECULAR_BIT) {
765 struct gl_material *mat = &ctx->Light.Material[0];
Brian Paulde82d062000-06-26 23:37:46 +0000766 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000767 SUB_3V( tmp, color, mat->Specular );
768 foreach (light, list) {
769 if (light->Flags & LIGHT_SPECULAR) {
770 ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
771 light->IsMatSpecular[0] =
772 (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
773 }
774 }
775 COPY_4FV( mat->Specular, color );
776 }
Brian Paulde82d062000-06-26 23:37:46 +0000777
jtgafb833d1999-08-19 00:55:39 +0000778 if (bitmask & BACK_SPECULAR_BIT) {
779 struct gl_material *mat = &ctx->Light.Material[1];
Brian Paulde82d062000-06-26 23:37:46 +0000780 GLfloat tmp[4];
jtgafb833d1999-08-19 00:55:39 +0000781 SUB_3V( tmp, color, mat->Specular );
782 foreach (light, list) {
783 if (light->Flags & LIGHT_SPECULAR) {
784 ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
785 light->IsMatSpecular[1] =
786 (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
787 }
788 }
789 COPY_4FV( mat->Specular, color );
790 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000791
792 if (0)
793 {
794 struct gl_material *mat = &ctx->Light.Material[0];
795 fprintf(stderr, "update_color_mat emission : %f %f %f\n",
796 mat->Emission[0],
797 mat->Emission[1],
798 mat->Emission[2]);
799 fprintf(stderr, "update_color_mat specular : %f %f %f\n",
800 mat->Specular[0],
801 mat->Specular[1],
802 mat->Specular[2]);
803 fprintf(stderr, "update_color_mat diffuse : %f %f %f\n",
804 mat->Diffuse[0],
805 mat->Diffuse[1],
806 mat->Diffuse[2]);
807 fprintf(stderr, "update_color_mat ambient : %f %f %f\n",
808 mat->Ambient[0],
809 mat->Ambient[1],
810 mat->Ambient[2]);
811 }
jtgafb833d1999-08-19 00:55:39 +0000812}
813
814
815
816
Brian Paulfbd8f211999-11-11 01:22:25 +0000817void
818_mesa_ColorMaterial( GLenum face, GLenum mode )
jtgafb833d1999-08-19 00:55:39 +0000819{
Brian Paulfbd8f211999-11-11 01:22:25 +0000820 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000821 GLuint bitmask;
822 GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
823 FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
824 FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
825 FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
826
827 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
828
Keith Whitwell06ac5921999-11-10 06:29:44 +0000829 if (MESA_VERBOSE&VERBOSE_API)
830 fprintf(stderr, "glColorMaterial %s %s\n",
831 gl_lookup_enum_by_nr(face),
832 gl_lookup_enum_by_nr(mode));
833
jtgafb833d1999-08-19 00:55:39 +0000834 bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
835
836 if (bitmask != 0) {
837 ctx->Light.ColorMaterialBitmask = bitmask;
838 ctx->Light.ColorMaterialFace = face;
839 ctx->Light.ColorMaterialMode = mode;
840 }
Keith Whitwell06ac5921999-11-10 06:29:44 +0000841
842 if (ctx->Light.ColorMaterialEnabled)
843 gl_update_color_material( ctx, ctx->Current.ByteColor );
jtgafb833d1999-08-19 00:55:39 +0000844}
845
846
847
Brian Paulfbd8f211999-11-11 01:22:25 +0000848
849void
850_mesa_Materialf( GLenum face, GLenum pname, GLfloat param )
851{
852 _mesa_Materialfv( face, pname, &param );
853}
854
855
jtgafb833d1999-08-19 00:55:39 +0000856/* KW: This is now called directly (ie by name) from the glMaterial*
857 * API functions.
858 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000859void
860_mesa_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
jtgafb833d1999-08-19 00:55:39 +0000861{
Brian Paulfbd8f211999-11-11 01:22:25 +0000862 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000863 struct immediate *IM;
864 struct gl_material *mat;
865 GLuint bitmask;
866 GLuint count;
867
868 bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" );
869 if (bitmask == 0)
870 return;
871
872 IM = ctx->input;
873 count = IM->Count;
874
Keith Whitwelld4714731999-10-19 18:37:02 +0000875 if (!IM->Material) {
876 IM->Material =
877 (struct gl_material (*)[2]) MALLOC( sizeof(struct gl_material) *
878 VB_SIZE * 2 );
879 IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * VB_SIZE );
880 }
881
882
jtgafb833d1999-08-19 00:55:39 +0000883 if (!(IM->Flag[count] & VERT_MATERIAL)) {
884 IM->Flag[count] |= VERT_MATERIAL;
Keith Whitwelld4714731999-10-19 18:37:02 +0000885 IM->MaterialMask[count] = 0;
jtgafb833d1999-08-19 00:55:39 +0000886 }
887
Brian Paulfbd8f211999-11-11 01:22:25 +0000888
jtgafb833d1999-08-19 00:55:39 +0000889 IM->MaterialMask[count] |= bitmask;
890 mat = IM->Material[count];
jtgafb833d1999-08-19 00:55:39 +0000891
892 if (bitmask & FRONT_AMBIENT_BIT) {
893 COPY_4FV( mat[0].Ambient, params );
894 }
895 if (bitmask & BACK_AMBIENT_BIT) {
896 COPY_4FV( mat[1].Ambient, params );
897 }
898 if (bitmask & FRONT_DIFFUSE_BIT) {
899 COPY_4FV( mat[0].Diffuse, params );
900 }
901 if (bitmask & BACK_DIFFUSE_BIT) {
902 COPY_4FV( mat[1].Diffuse, params );
903 }
904 if (bitmask & FRONT_SPECULAR_BIT) {
905 COPY_4FV( mat[0].Specular, params );
906 }
907 if (bitmask & BACK_SPECULAR_BIT) {
908 COPY_4FV( mat[1].Specular, params );
909 }
910 if (bitmask & FRONT_EMISSION_BIT) {
911 COPY_4FV( mat[0].Emission, params );
912 }
913 if (bitmask & BACK_EMISSION_BIT) {
914 COPY_4FV( mat[1].Emission, params );
915 }
916 if (bitmask & FRONT_SHININESS_BIT) {
917 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
918 mat[0].Shininess = shininess;
919 }
920 if (bitmask & BACK_SHININESS_BIT) {
921 GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
922 mat[1].Shininess = shininess;
923 }
924 if (bitmask & FRONT_INDEXES_BIT) {
925 mat[0].AmbientIndex = params[0];
926 mat[0].DiffuseIndex = params[1];
927 mat[0].SpecularIndex = params[2];
928 }
929 if (bitmask & BACK_INDEXES_BIT) {
930 mat[1].AmbientIndex = params[0];
931 mat[1].DiffuseIndex = params[1];
932 mat[1].SpecularIndex = params[2];
933 }
934}
935
936
Brian Paulfbd8f211999-11-11 01:22:25 +0000937void
938_mesa_Materiali(GLenum face, GLenum pname, GLint param )
jtgafb833d1999-08-19 00:55:39 +0000939{
Brian Paulfbd8f211999-11-11 01:22:25 +0000940 _mesa_Materialiv(face, pname, &param);
941}
942
943
944void
945_mesa_Materialiv(GLenum face, GLenum pname, const GLint *params )
946{
947 GLfloat fparam[4];
948 switch (pname) {
949 case GL_AMBIENT:
950 case GL_DIFFUSE:
951 case GL_SPECULAR:
952 case GL_EMISSION:
953 case GL_AMBIENT_AND_DIFFUSE:
954 fparam[0] = INT_TO_FLOAT( params[0] );
955 fparam[1] = INT_TO_FLOAT( params[1] );
956 fparam[2] = INT_TO_FLOAT( params[2] );
957 fparam[3] = INT_TO_FLOAT( params[3] );
958 break;
959 case GL_SHININESS:
960 fparam[0] = (GLfloat) params[0];
961 break;
962 case GL_COLOR_INDEXES:
963 fparam[0] = (GLfloat) params[0];
964 fparam[1] = (GLfloat) params[1];
965 fparam[2] = (GLfloat) params[2];
966 break;
967 default:
968 /* Error will be caught later in gl_Materialfv */
969 ;
970 }
971 _mesa_Materialfv(face, pname, fparam);
972}
973
974
975void
976_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
977{
978 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000979 GLuint f;
980
981 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
982
983 if (face==GL_FRONT) {
984 f = 0;
985 }
986 else if (face==GL_BACK) {
987 f = 1;
988 }
989 else {
990 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
991 return;
992 }
993 switch (pname) {
994 case GL_AMBIENT:
995 COPY_4FV( params, ctx->Light.Material[f].Ambient );
996 break;
997 case GL_DIFFUSE:
998 COPY_4FV( params, ctx->Light.Material[f].Diffuse );
999 break;
1000 case GL_SPECULAR:
1001 COPY_4FV( params, ctx->Light.Material[f].Specular );
1002 break;
1003 case GL_EMISSION:
1004 COPY_4FV( params, ctx->Light.Material[f].Emission );
1005 break;
1006 case GL_SHININESS:
1007 *params = ctx->Light.Material[f].Shininess;
1008 break;
1009 case GL_COLOR_INDEXES:
1010 params[0] = ctx->Light.Material[f].AmbientIndex;
1011 params[1] = ctx->Light.Material[f].DiffuseIndex;
1012 params[2] = ctx->Light.Material[f].SpecularIndex;
1013 break;
1014 default:
1015 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1016 }
1017}
1018
1019
1020
Brian Paulfbd8f211999-11-11 01:22:25 +00001021void
1022_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
jtgafb833d1999-08-19 00:55:39 +00001023{
Brian Paulfbd8f211999-11-11 01:22:25 +00001024 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001025 GLuint f;
1026
1027 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
1028
1029 if (face==GL_FRONT) {
1030 f = 0;
1031 }
1032 else if (face==GL_BACK) {
1033 f = 1;
1034 }
1035 else {
1036 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
1037 return;
1038 }
1039 switch (pname) {
1040 case GL_AMBIENT:
1041 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
1042 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
1043 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
1044 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
1045 break;
1046 case GL_DIFFUSE:
1047 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
1048 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
1049 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
1050 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
1051 break;
1052 case GL_SPECULAR:
1053 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
1054 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
1055 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
1056 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
1057 break;
1058 case GL_EMISSION:
1059 params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
1060 params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
1061 params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
1062 params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
1063 break;
1064 case GL_SHININESS:
1065 *params = ROUNDF( ctx->Light.Material[f].Shininess );
1066 break;
1067 case GL_COLOR_INDEXES:
1068 params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
1069 params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
1070 params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
1071 break;
1072 default:
1073 gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
1074 }
1075}
1076
1077
1078
1079
1080/**********************************************************************/
1081/***** Lighting computation *****/
1082/**********************************************************************/
1083
1084
1085/*
1086 * Notes:
1087 * When two-sided lighting is enabled we compute the color (or index)
1088 * for both the front and back side of the primitive. Then, when the
1089 * orientation of the facet is later learned, we can determine which
1090 * color (or index) to use for rendering.
1091 *
1092 * KW: We now know orientation in advance and only shade for
1093 * the side or sides which are actually required.
1094 *
1095 * Variables:
1096 * n = normal vector
1097 * V = vertex position
1098 * P = light source position
1099 * Pe = (0,0,0,1)
1100 *
1101 * Precomputed:
1102 * IF P[3]==0 THEN
1103 * // light at infinity
1104 * IF local_viewer THEN
1105 * VP_inf_norm = unit vector from V to P // Precompute
1106 * ELSE
1107 * // eye at infinity
1108 * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
1109 * ENDIF
1110 * ENDIF
1111 *
1112 * Functions:
1113 * Normalize( v ) = normalized vector v
1114 * Magnitude( v ) = length of vector v
1115 */
1116
1117
1118
1119/*
1120 * Whenever the spotlight exponent for a light changes we must call
1121 * this function to recompute the exponent lookup table.
1122 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001123void
1124gl_compute_spot_exp_table( struct gl_light *l )
jtgafb833d1999-08-19 00:55:39 +00001125{
Brian Paula0faa7f2000-07-18 16:55:56 +00001126 GLint i;
1127 GLdouble exponent = l->SpotExponent;
1128 GLdouble tmp = 0;
1129 GLint clamp = 0;
jtgafb833d1999-08-19 00:55:39 +00001130
1131 l->SpotExpTable[0][0] = 0.0;
1132
Brian Paula0faa7f2000-07-18 16:55:56 +00001133 for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
jtgafb833d1999-08-19 00:55:39 +00001134 if (clamp == 0) {
Brian Paula0faa7f2000-07-18 16:55:56 +00001135 tmp = pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
1136 if (tmp < FLT_MIN * 100.0) {
jtgafb833d1999-08-19 00:55:39 +00001137 tmp = 0.0;
1138 clamp = 1;
1139 }
1140 }
1141 l->SpotExpTable[i][0] = tmp;
1142 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001143 for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
jtgafb833d1999-08-19 00:55:39 +00001144 l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
1145 }
1146 l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
1147}
1148
1149
1150
1151
1152/* Calculate a new shine table. Doing this here saves a branch in
1153 * lighting, and the cost of doing it early may be partially offset
1154 * by keeping a MRU cache of shine tables for various shine values.
1155 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001156static void
1157compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
jtgafb833d1999-08-19 00:55:39 +00001158{
Brian Paula0faa7f2000-07-18 16:55:56 +00001159 GLint i;
jtgafb833d1999-08-19 00:55:39 +00001160 GLfloat *m = tab->tab;
1161
Brian Paula0faa7f2000-07-18 16:55:56 +00001162 m[0] = 0.0;
1163 if (shininess == 0.0) {
jtgafb833d1999-08-19 00:55:39 +00001164 for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
Brian Paula0faa7f2000-07-18 16:55:56 +00001165 m[i] = 1.0;
1166 }
1167 else {
1168 for (i = 1 ; i < SHINE_TABLE_SIZE ; i++) {
1169 GLdouble t = pow(i / (GLfloat) (SHINE_TABLE_SIZE - 1), shininess);
1170 if (t > 1e-20)
1171 m[i] = t;
1172 else
1173 m[i] = 0.0;
jtgafb833d1999-08-19 00:55:39 +00001174 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001175 m[SHINE_TABLE_SIZE] = 1.0;
jtgafb833d1999-08-19 00:55:39 +00001176 }
1177
1178 tab->shininess = shininess;
1179}
1180
jtgafb833d1999-08-19 00:55:39 +00001181
Brian Paula0faa7f2000-07-18 16:55:56 +00001182void
1183gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
jtgafb833d1999-08-19 00:55:39 +00001184{
Brian Paula0faa7f2000-07-18 16:55:56 +00001185#define DISTSQR(a,b) ((a-b)*(a-b))
jtgafb833d1999-08-19 00:55:39 +00001186 struct gl_shine_tab *list = ctx->ShineTabList;
1187 struct gl_shine_tab *s;
1188
1189 foreach(s, list)
1190 if ( DISTSQR(s->shininess, shininess) < 1e-4 )
1191 break;
1192
Brian Paula0faa7f2000-07-18 16:55:56 +00001193 if (s == list) {
jtgafb833d1999-08-19 00:55:39 +00001194 foreach(s, list)
Brian Paula0faa7f2000-07-18 16:55:56 +00001195 if (s->refcount == 0)
1196 break;
jtgafb833d1999-08-19 00:55:39 +00001197
1198 compute_shine_table( s, shininess );
1199 }
1200
1201 ctx->ShineTable[i]->refcount--;
1202 ctx->ShineTable[i] = s;
1203 move_to_tail( list, s );
1204 s->refcount++;
Brian Paula0faa7f2000-07-18 16:55:56 +00001205#undef DISTSQR
jtgafb833d1999-08-19 00:55:39 +00001206}
1207
1208
1209
Brian Paul16a9efe2000-01-13 00:29:02 +00001210#if 0
Brian Paula0faa7f2000-07-18 16:55:56 +00001211static void
1212gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
jtgafb833d1999-08-19 00:55:39 +00001213{
1214 GLuint i;
1215
1216 if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) {
1217 gl_compute_shine_table( ctx, 0, l->Material[0].Shininess );
1218 gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 );
1219 }
1220
1221 if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) {
1222 gl_compute_shine_table( ctx, 1, l->Material[1].Shininess );
1223 gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 );
1224 }
1225
1226 make_empty_list( &l->EnabledList );
1227 for (i = 0 ; i < MAX_LIGHTS ; i++) {
1228 if (l->Light[i].Enabled)
1229 insert_at_tail( &l->EnabledList, &l->Light[i] );
1230 }
1231}
Brian Paul16a9efe2000-01-13 00:29:02 +00001232#endif
jtgafb833d1999-08-19 00:55:39 +00001233
1234
1235/*
1236 * Examine current lighting parameters to determine if the optimized lighting
1237 * function can be used.
1238 * Also, precompute some lighting values such as the products of light
1239 * source and material ambient, diffuse and specular coefficients.
1240 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001241void
1242gl_update_lighting( GLcontext *ctx )
jtgafb833d1999-08-19 00:55:39 +00001243{
1244 struct gl_light *light;
1245
1246 ctx->Light.Flags = 0;
1247
1248 foreach(light, &ctx->Light.EnabledList) {
1249
1250 light->Flags = 0;
1251
1252 if (light->EyePosition[3] != 0.0F)
1253 light->Flags |= LIGHT_POSITIONAL;
1254
1255 if (LEN_SQUARED_3FV(light->Specular) > 1e-16)
1256 light->Flags |= LIGHT_SPECULAR;
1257
1258 if (light->SpotCutoff != 180.0F)
1259 light->Flags |= LIGHT_SPOT;
1260
1261 ctx->Light.Flags |= light->Flags;
1262 }
1263
1264 ctx->Light.NeedVertices =
1265 ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
1266 (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) ||
1267 (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR)));
1268
1269
1270 /* Precompute some shading values.
1271 */
Brian Paulb1394fa2000-09-26 20:53:53 +00001272 if (ctx->Visual.RGBAflag) {
jtgafb833d1999-08-19 00:55:39 +00001273 GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1);
1274 GLuint side;
1275 for (side=0; side < sides; side++) {
1276 struct gl_material *mat = &ctx->Light.Material[side];
Brian Paulc535ba52000-06-29 04:56:30 +00001277
jtgafb833d1999-08-19 00:55:39 +00001278 COPY_3V(ctx->Light.BaseColor[side], mat->Emission);
1279 ACC_SCALE_3V(ctx->Light.BaseColor[side],
1280 ctx->Light.Model.Ambient,
1281 mat->Ambient);
1282
1283 FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side],
1284 ctx->Light.Material[side].Diffuse[3] );
1285 }
1286
1287 foreach (light, &ctx->Light.EnabledList) {
1288 for (side=0; side< sides; side++) {
Brian Paulc535ba52000-06-29 04:56:30 +00001289 const struct gl_material *mat = &ctx->Light.Material[side];
1290 SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse );
1291 SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient );
1292 if (light->Flags & LIGHT_SPECULAR) {
jtgafb833d1999-08-19 00:55:39 +00001293 SCALE_3V( light->MatSpecular[side], light->Specular,
1294 mat->Specular);
1295 light->IsMatSpecular[side] =
1296 (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16);
1297 }
1298 else
1299 light->IsMatSpecular[side] = 0;
1300 }
1301 }
1302 }
Brian Paulc535ba52000-06-29 04:56:30 +00001303 else {
1304 static const GLfloat ci[3] = { .30, .59, .11 };
jtgafb833d1999-08-19 00:55:39 +00001305 foreach(light, &ctx->Light.EnabledList) {
1306 light->dli = DOT3(ci, light->Diffuse);
1307 light->sli = DOT3(ci, light->Specular);
1308 }
1309 }
1310}
1311
Brian Paulc535ba52000-06-29 04:56:30 +00001312
1313
jtgafb833d1999-08-19 00:55:39 +00001314/* Need to seriously restrict the circumstances under which these
1315 * calc's are performed.
1316 */
Brian Paula0faa7f2000-07-18 16:55:56 +00001317void
1318gl_compute_light_positions( GLcontext *ctx )
jtgafb833d1999-08-19 00:55:39 +00001319{
1320 struct gl_light *light;
1321
Brian Paulde82d062000-06-26 23:37:46 +00001322 if (1 /*ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer*/) {
1323 static const GLfloat eye_z[3] = { 0, 0, 1 };
1324 if (ctx->NeedEyeCoords) {
jtgafb833d1999-08-19 00:55:39 +00001325 COPY_3V( ctx->EyeZDir, eye_z );
1326 }
Brian Paulde82d062000-06-26 23:37:46 +00001327 else {
1328 TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m );
1329 }
jtgafb833d1999-08-19 00:55:39 +00001330 }
1331
1332 foreach (light, &ctx->Light.EnabledList) {
1333
Brian Paulde82d062000-06-26 23:37:46 +00001334 if (ctx->NeedEyeCoords) {
jtgafb833d1999-08-19 00:55:39 +00001335 COPY_4FV( light->Position, light->EyePosition );
1336 }
Brian Paulde82d062000-06-26 23:37:46 +00001337 else {
1338 TRANSFORM_POINT( light->Position, ctx->ModelView.inv,
1339 light->EyePosition );
1340 }
jtgafb833d1999-08-19 00:55:39 +00001341
Brian Paulde82d062000-06-26 23:37:46 +00001342 if (!(light->Flags & LIGHT_POSITIONAL)) {
jtgafb833d1999-08-19 00:55:39 +00001343 /* VP (VP) = Normalize( Position ) */
1344 COPY_3V( light->VP_inf_norm, light->Position );
1345 NORMALIZE_3FV( light->VP_inf_norm );
1346
Brian Paulde82d062000-06-26 23:37:46 +00001347 if (!ctx->Light.Model.LocalViewer) {
jtgafb833d1999-08-19 00:55:39 +00001348 /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1349 ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir);
1350 NORMALIZE_3FV( light->h_inf_norm );
1351 }
jtgafb833d1999-08-19 00:55:39 +00001352 light->VP_inf_spot_attenuation = 1.0;
1353 }
1354
Brian Paulde82d062000-06-26 23:37:46 +00001355 if (light->Flags & LIGHT_SPOT) {
jtgafb833d1999-08-19 00:55:39 +00001356 if (ctx->NeedEyeNormals) {
1357 COPY_3V( light->NormDirection, light->EyeDirection );
Brian Paulde82d062000-06-26 23:37:46 +00001358 }
1359 else {
jtgafb833d1999-08-19 00:55:39 +00001360 TRANSFORM_NORMAL( light->NormDirection,
1361 light->EyeDirection,
1362 ctx->ModelView.m);
1363 }
1364
1365 NORMALIZE_3FV( light->NormDirection );
1366
1367
1368 /* Unlikely occurrance?
1369 */
1370 if (!(light->Flags & LIGHT_POSITIONAL)) {
1371 GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm,
1372 light->NormDirection);
1373
1374 if (PV_dot_dir > light->CosCutoff) {
1375 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
1376 int k = (int) x;
1377 light->VP_inf_spot_attenuation =
1378 (light->SpotExpTable[k][0] +
1379 (x-k)*light->SpotExpTable[k][1]);
1380 }
Brian Paulde82d062000-06-26 23:37:46 +00001381 else {
jtgafb833d1999-08-19 00:55:39 +00001382 light->VP_inf_spot_attenuation = 0;
Brian Paulde82d062000-06-26 23:37:46 +00001383 }
jtgafb833d1999-08-19 00:55:39 +00001384 }
1385 }
1386 }
1387}
1388
1389
Brian Paula0faa7f2000-07-18 16:55:56 +00001390void
1391gl_update_normal_transform( GLcontext *ctx )
jtgafb833d1999-08-19 00:55:39 +00001392{
1393 GLuint new_flag = 0;
1394 normal_func *last = ctx->NormalTransform;
1395
1396 ctx->vb_rescale_factor = 1.0;
1397
1398 if (ctx->NeedEyeCoords) {
1399 if (ctx->NeedNormals) {
1400 GLuint transform = NORM_TRANSFORM_NO_ROT;
1401
1402 if (ctx->ModelView.flags & (MAT_FLAG_GENERAL |
1403 MAT_FLAG_ROTATION |
1404 MAT_FLAG_GENERAL_3D |
1405 MAT_FLAG_PERSPECTIVE))
1406 transform = NORM_TRANSFORM;
1407
1408
1409 new_flag = ctx->NewState & NEW_MODELVIEW;
1410 ctx->vb_rescale_factor = ctx->rescale_factor;
1411
Brian Paula0faa7f2000-07-18 16:55:56 +00001412 if (ctx->Transform.Normalize) {
jtgafb833d1999-08-19 00:55:39 +00001413 ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE];
1414 }
1415 else if (ctx->Transform.RescaleNormals &&
Brian Paula0faa7f2000-07-18 16:55:56 +00001416 ctx->rescale_factor != 1.0) {
jtgafb833d1999-08-19 00:55:39 +00001417 ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE];
1418 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001419 else {
jtgafb833d1999-08-19 00:55:39 +00001420 ctx->NormalTransform = gl_normal_tab[transform];
1421 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001422 }
1423 else {
jtgafb833d1999-08-19 00:55:39 +00001424 ctx->NormalTransform = 0;
1425 }
1426 }
1427 else {
1428 if (ctx->NeedNormals) {
1429 ctx->vb_rescale_factor = 1.0/ctx->rescale_factor;
1430
Brian Paula0faa7f2000-07-18 16:55:56 +00001431 if (ctx->Transform.Normalize) {
jtgafb833d1999-08-19 00:55:39 +00001432 ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE];
1433 }
1434 else if (!ctx->Transform.RescaleNormals &&
Brian Paula0faa7f2000-07-18 16:55:56 +00001435 ctx->rescale_factor != 1.0) {
jtgafb833d1999-08-19 00:55:39 +00001436 ctx->NormalTransform = gl_normal_tab[NORM_RESCALE];
1437 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001438 else {
jtgafb833d1999-08-19 00:55:39 +00001439 ctx->NormalTransform = 0;
1440 }
Brian Paula0faa7f2000-07-18 16:55:56 +00001441 }
1442 else {
jtgafb833d1999-08-19 00:55:39 +00001443 ctx->NormalTransform = 0;
1444 }
1445 }
1446
1447 if (last != ctx->NormalTransform || new_flag)
1448 ctx->NewState |= NEW_NORMAL_TRANSFORM;
1449}