1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 #include "c99_math.h" 28 #include "glheader.h" 29 #include "imports.h" 30 #include "context.h" 31 #include "enums.h" 32 #include "light.h" 33 #include "macros.h" 34 #include "mtypes.h" 35 #include "math/m_matrix.h" 36 #include "util/bitscan.h" 37 38 39 void GLAPIENTRY 40 _mesa_ShadeModel( GLenum mode ) 41 { 42 GET_CURRENT_CONTEXT(ctx); 43 44 if (MESA_VERBOSE & VERBOSE_API) 45 _mesa_debug(ctx, "glShadeModel %s\n", _mesa_enum_to_string(mode)); 46 47 if (ctx->Light.ShadeModel == mode) 48 return; 49 50 if (mode != GL_FLAT && mode != GL_SMOOTH) { 51 _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel"); 52 return; 53 } 54 55 FLUSH_VERTICES(ctx, _NEW_LIGHT); 56 ctx->Light.ShadeModel = mode; 57 58 if (ctx->Driver.ShadeModel) 59 ctx->Driver.ShadeModel( ctx, mode ); 60 } 61 62 63 /** 64 * Set the provoking vertex (the vertex which specifies the prim's 65 * color when flat shading) to either the first or last vertex of the 66 * triangle or line. 67 */ 68 void GLAPIENTRY 69 _mesa_ProvokingVertex(GLenum mode) 70 { 71 GET_CURRENT_CONTEXT(ctx); 72 73 if (MESA_VERBOSE&VERBOSE_API) 74 _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode); 75 76 switch (mode) { 77 case GL_FIRST_VERTEX_CONVENTION_EXT: 78 case GL_LAST_VERTEX_CONVENTION_EXT: 79 break; 80 default: 81 _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode); 82 return; 83 } 84 85 if (ctx->Light.ProvokingVertex == mode) 86 return; 87 88 FLUSH_VERTICES(ctx, _NEW_LIGHT); 89 ctx->Light.ProvokingVertex = mode; 90 } 91 92 93 /** 94 * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set 95 * per-light state. 96 * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction 97 * will have already been transformed by the modelview matrix! 98 * Also, all error checking should have already been done. 99 */ 100 void 101 _mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *params) 102 { 103 struct gl_light *light; 104 105 assert(lnum < MAX_LIGHTS); 106 light = &ctx->Light.Light[lnum]; 107 108 switch (pname) { 109 case GL_AMBIENT: 110 if (TEST_EQ_4V(light->Ambient, params)) 111 return; 112 FLUSH_VERTICES(ctx, _NEW_LIGHT); 113 COPY_4V( light->Ambient, params ); 114 break; 115 case GL_DIFFUSE: 116 if (TEST_EQ_4V(light->Diffuse, params)) 117 return; 118 FLUSH_VERTICES(ctx, _NEW_LIGHT); 119 COPY_4V( light->Diffuse, params ); 120 break; 121 case GL_SPECULAR: 122 if (TEST_EQ_4V(light->Specular, params)) 123 return; 124 FLUSH_VERTICES(ctx, _NEW_LIGHT); 125 COPY_4V( light->Specular, params ); 126 break; 127 case GL_POSITION: 128 /* NOTE: position has already been transformed by ModelView! */ 129 if (TEST_EQ_4V(light->EyePosition, params)) 130 return; 131 FLUSH_VERTICES(ctx, _NEW_LIGHT); 132 COPY_4V(light->EyePosition, params); 133 if (light->EyePosition[3] != 0.0F) 134 light->_Flags |= LIGHT_POSITIONAL; 135 else 136 light->_Flags &= ~LIGHT_POSITIONAL; 137 break; 138 case GL_SPOT_DIRECTION: 139 /* NOTE: Direction already transformed by inverse ModelView! */ 140 if (TEST_EQ_3V(light->SpotDirection, params)) 141 return; 142 FLUSH_VERTICES(ctx, _NEW_LIGHT); 143 COPY_3V(light->SpotDirection, params); 144 break; 145 case GL_SPOT_EXPONENT: 146 assert(params[0] >= 0.0F); 147 assert(params[0] <= ctx->Const.MaxSpotExponent); 148 if (light->SpotExponent == params[0]) 149 return; 150 FLUSH_VERTICES(ctx, _NEW_LIGHT); 151 light->SpotExponent = params[0]; 152 break; 153 case GL_SPOT_CUTOFF: 154 assert(params[0] == 180.0F || (params[0] >= 0.0F && params[0] <= 90.0F)); 155 if (light->SpotCutoff == params[0]) 156 return; 157 FLUSH_VERTICES(ctx, _NEW_LIGHT); 158 light->SpotCutoff = params[0]; 159 light->_CosCutoff = (cosf(light->SpotCutoff * M_PI / 180.0)); 160 if (light->_CosCutoff < 0) 161 light->_CosCutoff = 0; 162 if (light->SpotCutoff != 180.0F) 163 light->_Flags |= LIGHT_SPOT; 164 else 165 light->_Flags &= ~LIGHT_SPOT; 166 break; 167 case GL_CONSTANT_ATTENUATION: 168 assert(params[0] >= 0.0F); 169 if (light->ConstantAttenuation == params[0]) 170 return; 171 FLUSH_VERTICES(ctx, _NEW_LIGHT); 172 light->ConstantAttenuation = params[0]; 173 break; 174 case GL_LINEAR_ATTENUATION: 175 assert(params[0] >= 0.0F); 176 if (light->LinearAttenuation == params[0]) 177 return; 178 FLUSH_VERTICES(ctx, _NEW_LIGHT); 179 light->LinearAttenuation = params[0]; 180 break; 181 case GL_QUADRATIC_ATTENUATION: 182 assert(params[0] >= 0.0F); 183 if (light->QuadraticAttenuation == params[0]) 184 return; 185 FLUSH_VERTICES(ctx, _NEW_LIGHT); 186 light->QuadraticAttenuation = params[0]; 187 break; 188 default: 189 _mesa_problem(ctx, "Unexpected pname in _mesa_light()"); 190 return; 191 } 192 193 if (ctx->Driver.Lightfv) 194 ctx->Driver.Lightfv( ctx, GL_LIGHT0 + lnum, pname, params ); 195 } 196 197 198 void GLAPIENTRY 199 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param ) 200 { 201 GLfloat fparam[4]; 202 fparam[0] = param; 203 fparam[1] = fparam[2] = fparam[3] = 0.0F; 204 _mesa_Lightfv( light, pname, fparam ); 205 } 206 207 208 void GLAPIENTRY 209 _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params ) 210 { 211 GET_CURRENT_CONTEXT(ctx); 212 GLint i = (GLint) (light - GL_LIGHT0); 213 GLfloat temp[4]; 214 215 if (i < 0 || i >= (GLint) ctx->Const.MaxLights) { 216 _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light ); 217 return; 218 } 219 220 /* do particular error checks, transformations */ 221 switch (pname) { 222 case GL_AMBIENT: 223 case GL_DIFFUSE: 224 case GL_SPECULAR: 225 /* nothing */ 226 break; 227 case GL_POSITION: 228 /* transform position by ModelView matrix */ 229 TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params); 230 params = temp; 231 break; 232 case GL_SPOT_DIRECTION: 233 /* transform direction by inverse modelview */ 234 if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { 235 _math_matrix_analyse(ctx->ModelviewMatrixStack.Top); 236 } 237 TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m); 238 params = temp; 239 break; 240 case GL_SPOT_EXPONENT: 241 if (params[0] < 0.0F || params[0] > ctx->Const.MaxSpotExponent) { 242 _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); 243 return; 244 } 245 break; 246 case GL_SPOT_CUTOFF: 247 if ((params[0] < 0.0F || params[0] > 90.0F) && params[0] != 180.0F) { 248 _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); 249 return; 250 } 251 break; 252 case GL_CONSTANT_ATTENUATION: 253 case GL_LINEAR_ATTENUATION: 254 case GL_QUADRATIC_ATTENUATION: 255 if (params[0] < 0.0F) { 256 _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); 257 return; 258 } 259 break; 260 default: 261 _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname); 262 return; 263 } 264 265 _mesa_light(ctx, i, pname, params); 266 } 267 268 269 void GLAPIENTRY 270 _mesa_Lighti( GLenum light, GLenum pname, GLint param ) 271 { 272 GLint iparam[4]; 273 iparam[0] = param; 274 iparam[1] = iparam[2] = iparam[3] = 0; 275 _mesa_Lightiv( light, pname, iparam ); 276 } 277 278 279 void GLAPIENTRY 280 _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params ) 281 { 282 GLfloat fparam[4]; 283 284 switch (pname) { 285 case GL_AMBIENT: 286 case GL_DIFFUSE: 287 case GL_SPECULAR: 288 fparam[0] = INT_TO_FLOAT( params[0] ); 289 fparam[1] = INT_TO_FLOAT( params[1] ); 290 fparam[2] = INT_TO_FLOAT( params[2] ); 291 fparam[3] = INT_TO_FLOAT( params[3] ); 292 break; 293 case GL_POSITION: 294 fparam[0] = (GLfloat) params[0]; 295 fparam[1] = (GLfloat) params[1]; 296 fparam[2] = (GLfloat) params[2]; 297 fparam[3] = (GLfloat) params[3]; 298 break; 299 case GL_SPOT_DIRECTION: 300 fparam[0] = (GLfloat) params[0]; 301 fparam[1] = (GLfloat) params[1]; 302 fparam[2] = (GLfloat) params[2]; 303 break; 304 case GL_SPOT_EXPONENT: 305 case GL_SPOT_CUTOFF: 306 case GL_CONSTANT_ATTENUATION: 307 case GL_LINEAR_ATTENUATION: 308 case GL_QUADRATIC_ATTENUATION: 309 fparam[0] = (GLfloat) params[0]; 310 break; 311 default: 312 /* error will be caught later in gl_Lightfv */ 313 ; 314 } 315 316 _mesa_Lightfv( light, pname, fparam ); 317 } 318 319 320 321 void GLAPIENTRY 322 _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params ) 323 { 324 GET_CURRENT_CONTEXT(ctx); 325 GLint l = (GLint) (light - GL_LIGHT0); 326 327 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { 328 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); 329 return; 330 } 331 332 switch (pname) { 333 case GL_AMBIENT: 334 COPY_4V( params, ctx->Light.Light[l].Ambient ); 335 break; 336 case GL_DIFFUSE: 337 COPY_4V( params, ctx->Light.Light[l].Diffuse ); 338 break; 339 case GL_SPECULAR: 340 COPY_4V( params, ctx->Light.Light[l].Specular ); 341 break; 342 case GL_POSITION: 343 COPY_4V( params, ctx->Light.Light[l].EyePosition ); 344 break; 345 case GL_SPOT_DIRECTION: 346 COPY_3V( params, ctx->Light.Light[l].SpotDirection ); 347 break; 348 case GL_SPOT_EXPONENT: 349 params[0] = ctx->Light.Light[l].SpotExponent; 350 break; 351 case GL_SPOT_CUTOFF: 352 params[0] = ctx->Light.Light[l].SpotCutoff; 353 break; 354 case GL_CONSTANT_ATTENUATION: 355 params[0] = ctx->Light.Light[l].ConstantAttenuation; 356 break; 357 case GL_LINEAR_ATTENUATION: 358 params[0] = ctx->Light.Light[l].LinearAttenuation; 359 break; 360 case GL_QUADRATIC_ATTENUATION: 361 params[0] = ctx->Light.Light[l].QuadraticAttenuation; 362 break; 363 default: 364 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); 365 break; 366 } 367 } 368 369 370 void GLAPIENTRY 371 _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params ) 372 { 373 GET_CURRENT_CONTEXT(ctx); 374 GLint l = (GLint) (light - GL_LIGHT0); 375 376 if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { 377 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); 378 return; 379 } 380 381 switch (pname) { 382 case GL_AMBIENT: 383 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]); 384 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]); 385 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]); 386 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]); 387 break; 388 case GL_DIFFUSE: 389 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]); 390 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]); 391 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]); 392 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]); 393 break; 394 case GL_SPECULAR: 395 params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]); 396 params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]); 397 params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]); 398 params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]); 399 break; 400 case GL_POSITION: 401 params[0] = (GLint) ctx->Light.Light[l].EyePosition[0]; 402 params[1] = (GLint) ctx->Light.Light[l].EyePosition[1]; 403 params[2] = (GLint) ctx->Light.Light[l].EyePosition[2]; 404 params[3] = (GLint) ctx->Light.Light[l].EyePosition[3]; 405 break; 406 case GL_SPOT_DIRECTION: 407 params[0] = (GLint) ctx->Light.Light[l].SpotDirection[0]; 408 params[1] = (GLint) ctx->Light.Light[l].SpotDirection[1]; 409 params[2] = (GLint) ctx->Light.Light[l].SpotDirection[2]; 410 break; 411 case GL_SPOT_EXPONENT: 412 params[0] = (GLint) ctx->Light.Light[l].SpotExponent; 413 break; 414 case GL_SPOT_CUTOFF: 415 params[0] = (GLint) ctx->Light.Light[l].SpotCutoff; 416 break; 417 case GL_CONSTANT_ATTENUATION: 418 params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation; 419 break; 420 case GL_LINEAR_ATTENUATION: 421 params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation; 422 break; 423 case GL_QUADRATIC_ATTENUATION: 424 params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation; 425 break; 426 default: 427 _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); 428 break; 429 } 430 } 431 432 433 434 /**********************************************************************/ 435 /*** Light Model ***/ 436 /**********************************************************************/ 437 438 439 void GLAPIENTRY 440 _mesa_LightModelfv( GLenum pname, const GLfloat *params ) 441 { 442 GLenum newenum; 443 GLboolean newbool; 444 GET_CURRENT_CONTEXT(ctx); 445 446 switch (pname) { 447 case GL_LIGHT_MODEL_AMBIENT: 448 if (TEST_EQ_4V( ctx->Light.Model.Ambient, params )) 449 return; 450 FLUSH_VERTICES(ctx, _NEW_LIGHT); 451 COPY_4V( ctx->Light.Model.Ambient, params ); 452 break; 453 case GL_LIGHT_MODEL_LOCAL_VIEWER: 454 if (ctx->API != API_OPENGL_COMPAT) 455 goto invalid_pname; 456 newbool = (params[0] != 0.0F); 457 if (ctx->Light.Model.LocalViewer == newbool) 458 return; 459 FLUSH_VERTICES(ctx, _NEW_LIGHT); 460 ctx->Light.Model.LocalViewer = newbool; 461 break; 462 case GL_LIGHT_MODEL_TWO_SIDE: 463 newbool = (params[0] != 0.0F); 464 if (ctx->Light.Model.TwoSide == newbool) 465 return; 466 FLUSH_VERTICES(ctx, _NEW_LIGHT); 467 ctx->Light.Model.TwoSide = newbool; 468 break; 469 case GL_LIGHT_MODEL_COLOR_CONTROL: 470 if (ctx->API != API_OPENGL_COMPAT) 471 goto invalid_pname; 472 if (params[0] == (GLfloat) GL_SINGLE_COLOR) 473 newenum = GL_SINGLE_COLOR; 474 else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) 475 newenum = GL_SEPARATE_SPECULAR_COLOR; 476 else { 477 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)", 478 (GLint) params[0] ); 479 return; 480 } 481 if (ctx->Light.Model.ColorControl == newenum) 482 return; 483 FLUSH_VERTICES(ctx, _NEW_LIGHT); 484 ctx->Light.Model.ColorControl = newenum; 485 break; 486 default: 487 goto invalid_pname; 488 } 489 490 if (ctx->Driver.LightModelfv) 491 ctx->Driver.LightModelfv( ctx, pname, params ); 492 493 return; 494 495 invalid_pname: 496 _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname ); 497 return; 498 } 499 500 501 void GLAPIENTRY 502 _mesa_LightModeliv( GLenum pname, const GLint *params ) 503 { 504 GLfloat fparam[4]; 505 506 switch (pname) { 507 case GL_LIGHT_MODEL_AMBIENT: 508 fparam[0] = INT_TO_FLOAT( params[0] ); 509 fparam[1] = INT_TO_FLOAT( params[1] ); 510 fparam[2] = INT_TO_FLOAT( params[2] ); 511 fparam[3] = INT_TO_FLOAT( params[3] ); 512 break; 513 case GL_LIGHT_MODEL_LOCAL_VIEWER: 514 case GL_LIGHT_MODEL_TWO_SIDE: 515 case GL_LIGHT_MODEL_COLOR_CONTROL: 516 fparam[0] = (GLfloat) params[0]; 517 break; 518 default: 519 /* Error will be caught later in gl_LightModelfv */ 520 ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F); 521 } 522 _mesa_LightModelfv( pname, fparam ); 523 } 524 525 526 void GLAPIENTRY 527 _mesa_LightModeli( GLenum pname, GLint param ) 528 { 529 GLint iparam[4]; 530 iparam[0] = param; 531 iparam[1] = iparam[2] = iparam[3] = 0; 532 _mesa_LightModeliv( pname, iparam ); 533 } 534 535 536 void GLAPIENTRY 537 _mesa_LightModelf( GLenum pname, GLfloat param ) 538 { 539 GLfloat fparam[4]; 540 fparam[0] = param; 541 fparam[1] = fparam[2] = fparam[3] = 0.0F; 542 _mesa_LightModelfv( pname, fparam ); 543 } 544 545 546 547 /********** MATERIAL **********/ 548 549 550 /* 551 * Given a face and pname value (ala glColorMaterial), compute a bitmask 552 * of the targeted material values. 553 */ 554 GLuint 555 _mesa_material_bitmask( struct gl_context *ctx, GLenum face, GLenum pname, 556 GLuint legal, const char *where ) 557 { 558 GLuint bitmask = 0; 559 560 /* Make a bitmask indicating what material attribute(s) we're updating */ 561 switch (pname) { 562 case GL_EMISSION: 563 bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION; 564 break; 565 case GL_AMBIENT: 566 bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; 567 break; 568 case GL_DIFFUSE: 569 bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; 570 break; 571 case GL_SPECULAR: 572 bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR; 573 break; 574 case GL_SHININESS: 575 bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS; 576 break; 577 case GL_AMBIENT_AND_DIFFUSE: 578 bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; 579 bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; 580 break; 581 case GL_COLOR_INDEXES: 582 bitmask |= MAT_BIT_FRONT_INDEXES | MAT_BIT_BACK_INDEXES; 583 break; 584 default: 585 _mesa_error( ctx, GL_INVALID_ENUM, "%s", where ); 586 return 0; 587 } 588 589 if (face==GL_FRONT) { 590 bitmask &= FRONT_MATERIAL_BITS; 591 } 592 else if (face==GL_BACK) { 593 bitmask &= BACK_MATERIAL_BITS; 594 } 595 else if (face != GL_FRONT_AND_BACK) { 596 _mesa_error( ctx, GL_INVALID_ENUM, "%s", where ); 597 return 0; 598 } 599 600 if (bitmask & ~legal) { 601 _mesa_error( ctx, GL_INVALID_ENUM, "%s", where ); 602 return 0; 603 } 604 605 return bitmask; 606 } 607 608 609 610 /* Update derived values following a change in ctx->Light.Material 611 */ 612 void 613 _mesa_update_material( struct gl_context *ctx, GLuint bitmask ) 614 { 615 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 616 617 if (MESA_VERBOSE & VERBOSE_MATERIAL) 618 _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask); 619 620 if (!bitmask) 621 return; 622 623 /* update material ambience */ 624 if (bitmask & MAT_BIT_FRONT_AMBIENT) { 625 GLbitfield mask = ctx->Light._EnabledLights; 626 while (mask) { 627 const int i = u_bit_scan(&mask); 628 struct gl_light *light = &ctx->Light.Light[i]; 629 SCALE_3V( light->_MatAmbient[0], light->Ambient, 630 mat[MAT_ATTRIB_FRONT_AMBIENT]); 631 } 632 } 633 634 if (bitmask & MAT_BIT_BACK_AMBIENT) { 635 GLbitfield mask = ctx->Light._EnabledLights; 636 while (mask) { 637 const int i = u_bit_scan(&mask); 638 struct gl_light *light = &ctx->Light.Light[i]; 639 SCALE_3V( light->_MatAmbient[1], light->Ambient, 640 mat[MAT_ATTRIB_BACK_AMBIENT]); 641 } 642 } 643 644 /* update BaseColor = emission + scene's ambience * material's ambience */ 645 if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) { 646 COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] ); 647 ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT], 648 ctx->Light.Model.Ambient ); 649 } 650 651 if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) { 652 COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] ); 653 ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT], 654 ctx->Light.Model.Ambient ); 655 } 656 657 /* update material diffuse values */ 658 if (bitmask & MAT_BIT_FRONT_DIFFUSE) { 659 GLbitfield mask = ctx->Light._EnabledLights; 660 while (mask) { 661 const int i = u_bit_scan(&mask); 662 struct gl_light *light = &ctx->Light.Light[i]; 663 SCALE_3V( light->_MatDiffuse[0], light->Diffuse, 664 mat[MAT_ATTRIB_FRONT_DIFFUSE] ); 665 } 666 } 667 668 if (bitmask & MAT_BIT_BACK_DIFFUSE) { 669 GLbitfield mask = ctx->Light._EnabledLights; 670 while (mask) { 671 const int i = u_bit_scan(&mask); 672 struct gl_light *light = &ctx->Light.Light[i]; 673 SCALE_3V( light->_MatDiffuse[1], light->Diffuse, 674 mat[MAT_ATTRIB_BACK_DIFFUSE] ); 675 } 676 } 677 678 /* update material specular values */ 679 if (bitmask & MAT_BIT_FRONT_SPECULAR) { 680 GLbitfield mask = ctx->Light._EnabledLights; 681 while (mask) { 682 const int i = u_bit_scan(&mask); 683 struct gl_light *light = &ctx->Light.Light[i]; 684 SCALE_3V( light->_MatSpecular[0], light->Specular, 685 mat[MAT_ATTRIB_FRONT_SPECULAR]); 686 } 687 } 688 689 if (bitmask & MAT_BIT_BACK_SPECULAR) { 690 GLbitfield mask = ctx->Light._EnabledLights; 691 while (mask) { 692 const int i = u_bit_scan(&mask); 693 struct gl_light *light = &ctx->Light.Light[i]; 694 SCALE_3V( light->_MatSpecular[1], light->Specular, 695 mat[MAT_ATTRIB_BACK_SPECULAR]); 696 } 697 } 698 } 699 700 701 /* 702 * Update the current materials from the given rgba color 703 * according to the bitmask in _ColorMaterialBitmask, which is 704 * set by glColorMaterial(). 705 */ 706 void 707 _mesa_update_color_material( struct gl_context *ctx, const GLfloat color[4] ) 708 { 709 GLbitfield bitmask = ctx->Light._ColorMaterialBitmask; 710 struct gl_material *mat = &ctx->Light.Material; 711 712 while (bitmask) { 713 const int i = u_bit_scan(&bitmask); 714 715 COPY_4FV( mat->Attrib[i], color ); 716 } 717 718 _mesa_update_material( ctx, bitmask ); 719 } 720 721 722 void GLAPIENTRY 723 _mesa_ColorMaterial( GLenum face, GLenum mode ) 724 { 725 GET_CURRENT_CONTEXT(ctx); 726 GLuint bitmask; 727 GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION | 728 MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR | 729 MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE | 730 MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT); 731 732 if (MESA_VERBOSE&VERBOSE_API) 733 _mesa_debug(ctx, "glColorMaterial %s %s\n", 734 _mesa_enum_to_string(face), 735 _mesa_enum_to_string(mode)); 736 737 bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial"); 738 if (bitmask == 0) 739 return; /* error was recorded */ 740 741 if (ctx->Light._ColorMaterialBitmask == bitmask && 742 ctx->Light.ColorMaterialFace == face && 743 ctx->Light.ColorMaterialMode == mode) 744 return; 745 746 FLUSH_VERTICES(ctx, _NEW_LIGHT); 747 ctx->Light._ColorMaterialBitmask = bitmask; 748 ctx->Light.ColorMaterialFace = face; 749 ctx->Light.ColorMaterialMode = mode; 750 751 if (ctx->Light.ColorMaterialEnabled) { 752 FLUSH_CURRENT( ctx, 0 ); 753 _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); 754 } 755 756 if (ctx->Driver.ColorMaterial) 757 ctx->Driver.ColorMaterial( ctx, face, mode ); 758 } 759 760 761 void GLAPIENTRY 762 _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params ) 763 { 764 GET_CURRENT_CONTEXT(ctx); 765 GLuint f; 766 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 767 FLUSH_VERTICES(ctx, 0); /* update materials */ 768 769 FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ 770 771 if (face==GL_FRONT) { 772 f = 0; 773 } 774 else if (face==GL_BACK) { 775 f = 1; 776 } 777 else { 778 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" ); 779 return; 780 } 781 782 switch (pname) { 783 case GL_AMBIENT: 784 COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] ); 785 break; 786 case GL_DIFFUSE: 787 COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] ); 788 break; 789 case GL_SPECULAR: 790 COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] ); 791 break; 792 case GL_EMISSION: 793 COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] ); 794 break; 795 case GL_SHININESS: 796 *params = mat[MAT_ATTRIB_SHININESS(f)][0]; 797 break; 798 case GL_COLOR_INDEXES: 799 if (ctx->API != API_OPENGL_COMPAT) { 800 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); 801 return; 802 } 803 params[0] = mat[MAT_ATTRIB_INDEXES(f)][0]; 804 params[1] = mat[MAT_ATTRIB_INDEXES(f)][1]; 805 params[2] = mat[MAT_ATTRIB_INDEXES(f)][2]; 806 break; 807 default: 808 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); 809 } 810 } 811 812 813 void GLAPIENTRY 814 _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params ) 815 { 816 GET_CURRENT_CONTEXT(ctx); 817 GLuint f; 818 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 819 820 assert(ctx->API == API_OPENGL_COMPAT); 821 822 FLUSH_VERTICES(ctx, 0); /* update materials */ 823 FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ 824 825 if (face==GL_FRONT) { 826 f = 0; 827 } 828 else if (face==GL_BACK) { 829 f = 1; 830 } 831 else { 832 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" ); 833 return; 834 } 835 switch (pname) { 836 case GL_AMBIENT: 837 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] ); 838 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] ); 839 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] ); 840 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] ); 841 break; 842 case GL_DIFFUSE: 843 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] ); 844 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] ); 845 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] ); 846 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] ); 847 break; 848 case GL_SPECULAR: 849 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] ); 850 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] ); 851 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] ); 852 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] ); 853 break; 854 case GL_EMISSION: 855 params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] ); 856 params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] ); 857 params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] ); 858 params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] ); 859 break; 860 case GL_SHININESS: 861 *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] ); 862 break; 863 case GL_COLOR_INDEXES: 864 params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] ); 865 params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] ); 866 params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] ); 867 break; 868 default: 869 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); 870 } 871 } 872 873 874 875 /** 876 * Examine current lighting parameters to determine if the optimized lighting 877 * function can be used. 878 * Also, precompute some lighting values such as the products of light 879 * source and material ambient, diffuse and specular coefficients. 880 */ 881 void 882 _mesa_update_lighting( struct gl_context *ctx ) 883 { 884 GLbitfield flags = 0; 885 ctx->Light._NeedEyeCoords = GL_FALSE; 886 887 if (!ctx->Light.Enabled) 888 return; 889 890 GLbitfield mask = ctx->Light._EnabledLights; 891 while (mask) { 892 const int i = u_bit_scan(&mask); 893 struct gl_light *light = &ctx->Light.Light[i]; 894 flags |= light->_Flags; 895 } 896 897 ctx->Light._NeedVertices = 898 ((flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) || 899 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR || 900 ctx->Light.Model.LocalViewer); 901 902 ctx->Light._NeedEyeCoords = ((flags & LIGHT_POSITIONAL) || 903 ctx->Light.Model.LocalViewer); 904 905 /* XXX: This test is overkill & needs to be fixed both for software and 906 * hardware t&l drivers. The above should be sufficient & should 907 * be tested to verify this. 908 */ 909 if (ctx->Light._NeedVertices) 910 ctx->Light._NeedEyeCoords = GL_TRUE; 911 912 /* Precompute some shading values. Although we reference 913 * Light.Material here, we can get away without flushing 914 * FLUSH_UPDATE_CURRENT, as when any outstanding material changes 915 * are flushed, they will update the derived state at that time. 916 */ 917 if (ctx->Light.Model.TwoSide) 918 _mesa_update_material(ctx, 919 MAT_BIT_FRONT_EMISSION | 920 MAT_BIT_FRONT_AMBIENT | 921 MAT_BIT_FRONT_DIFFUSE | 922 MAT_BIT_FRONT_SPECULAR | 923 MAT_BIT_BACK_EMISSION | 924 MAT_BIT_BACK_AMBIENT | 925 MAT_BIT_BACK_DIFFUSE | 926 MAT_BIT_BACK_SPECULAR); 927 else 928 _mesa_update_material(ctx, 929 MAT_BIT_FRONT_EMISSION | 930 MAT_BIT_FRONT_AMBIENT | 931 MAT_BIT_FRONT_DIFFUSE | 932 MAT_BIT_FRONT_SPECULAR); 933 } 934 935 936 /** 937 * Update state derived from light position, spot direction. 938 * Called upon: 939 * _NEW_MODELVIEW 940 * _NEW_LIGHT 941 * _TNL_NEW_NEED_EYE_COORDS 942 * 943 * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled. 944 * Also update on lighting space changes. 945 */ 946 static void 947 compute_light_positions( struct gl_context *ctx ) 948 { 949 static const GLfloat eye_z[3] = { 0, 0, 1 }; 950 951 if (!ctx->Light.Enabled) 952 return; 953 954 if (ctx->_NeedEyeCoords) { 955 COPY_3V( ctx->_EyeZDir, eye_z ); 956 } 957 else { 958 TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m ); 959 } 960 961 GLbitfield mask = ctx->Light._EnabledLights; 962 while (mask) { 963 const int i = u_bit_scan(&mask); 964 struct gl_light *light = &ctx->Light.Light[i]; 965 966 if (ctx->_NeedEyeCoords) { 967 /* _Position is in eye coordinate space */ 968 COPY_4FV( light->_Position, light->EyePosition ); 969 } 970 else { 971 /* _Position is in object coordinate space */ 972 TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv, 973 light->EyePosition ); 974 } 975 976 if (!(light->_Flags & LIGHT_POSITIONAL)) { 977 /* VP (VP) = Normalize( Position ) */ 978 COPY_3V( light->_VP_inf_norm, light->_Position ); 979 NORMALIZE_3FV( light->_VP_inf_norm ); 980 981 if (!ctx->Light.Model.LocalViewer) { 982 /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */ 983 ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir); 984 NORMALIZE_3FV( light->_h_inf_norm ); 985 } 986 light->_VP_inf_spot_attenuation = 1.0; 987 } 988 else { 989 /* positional light w/ homogeneous coordinate, divide by W */ 990 GLfloat wInv = 1.0F / light->_Position[3]; 991 light->_Position[0] *= wInv; 992 light->_Position[1] *= wInv; 993 light->_Position[2] *= wInv; 994 } 995 996 if (light->_Flags & LIGHT_SPOT) { 997 /* Note: we normalize the spot direction now */ 998 999 if (ctx->_NeedEyeCoords) { 1000 COPY_3V( light->_NormSpotDirection, light->SpotDirection ); 1001 NORMALIZE_3FV( light->_NormSpotDirection ); 1002 } 1003 else { 1004 GLfloat spotDir[3]; 1005 COPY_3V(spotDir, light->SpotDirection); 1006 NORMALIZE_3FV(spotDir); 1007 TRANSFORM_NORMAL( light->_NormSpotDirection, 1008 spotDir, 1009 ctx->ModelviewMatrixStack.Top->m); 1010 } 1011 1012 NORMALIZE_3FV( light->_NormSpotDirection ); 1013 1014 if (!(light->_Flags & LIGHT_POSITIONAL)) { 1015 GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm, 1016 light->_NormSpotDirection); 1017 1018 if (PV_dot_dir > light->_CosCutoff) { 1019 light->_VP_inf_spot_attenuation = 1020 powf(PV_dot_dir, light->SpotExponent); 1021 } 1022 else { 1023 light->_VP_inf_spot_attenuation = 0; 1024 } 1025 } 1026 } 1027 } 1028 } 1029 1030 1031 1032 static void 1033 update_modelview_scale( struct gl_context *ctx ) 1034 { 1035 ctx->_ModelViewInvScale = 1.0F; 1036 if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) { 1037 const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv; 1038 GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10]; 1039 if (f < 1e-12f) f = 1.0f; 1040 if (ctx->_NeedEyeCoords) 1041 ctx->_ModelViewInvScale = 1.0f / sqrtf(f); 1042 else 1043 ctx->_ModelViewInvScale = sqrtf(f); 1044 } 1045 } 1046 1047 1048 /** 1049 * Bring up to date any state that relies on _NeedEyeCoords. 1050 */ 1051 void 1052 _mesa_update_tnl_spaces( struct gl_context *ctx, GLuint new_state ) 1053 { 1054 const GLuint oldneedeyecoords = ctx->_NeedEyeCoords; 1055 1056 (void) new_state; 1057 ctx->_NeedEyeCoords = GL_FALSE; 1058 1059 if (ctx->_ForceEyeCoords || 1060 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) || 1061 ctx->Point._Attenuated || 1062 ctx->Light._NeedEyeCoords) 1063 ctx->_NeedEyeCoords = GL_TRUE; 1064 1065 if (ctx->Light.Enabled && 1066 !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) 1067 ctx->_NeedEyeCoords = GL_TRUE; 1068 1069 /* Check if the truth-value interpretations of the bitfields have 1070 * changed: 1071 */ 1072 if (oldneedeyecoords != ctx->_NeedEyeCoords) { 1073 /* Recalculate all state that depends on _NeedEyeCoords. 1074 */ 1075 update_modelview_scale(ctx); 1076 compute_light_positions( ctx ); 1077 1078 if (ctx->Driver.LightingSpaceChange) 1079 ctx->Driver.LightingSpaceChange( ctx ); 1080 } 1081 else { 1082 GLuint new_state2 = ctx->NewState; 1083 1084 /* Recalculate that same state only if it has been invalidated 1085 * by other statechanges. 1086 */ 1087 if (new_state2 & _NEW_MODELVIEW) 1088 update_modelview_scale(ctx); 1089 1090 if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW)) 1091 compute_light_positions( ctx ); 1092 } 1093 } 1094 1095 1096 /** 1097 * Drivers may need this if the hardware tnl unit doesn't support the 1098 * light-in-modelspace optimization. It's also useful for debugging. 1099 */ 1100 void 1101 _mesa_allow_light_in_model( struct gl_context *ctx, GLboolean flag ) 1102 { 1103 ctx->_ForceEyeCoords = !flag; 1104 ctx->NewState |= _NEW_POINT; /* one of the bits from 1105 * _MESA_NEW_NEED_EYE_COORDS. 1106 */ 1107 } 1108 1109 1110 1111 /**********************************************************************/ 1112 /***** Initialization *****/ 1113 /**********************************************************************/ 1114 1115 /** 1116 * Initialize the n-th light data structure. 1117 * 1118 * \param l pointer to the gl_light structure to be initialized. 1119 * \param n number of the light. 1120 * \note The defaults for light 0 are different than the other lights. 1121 */ 1122 static void 1123 init_light( struct gl_light *l, GLuint n ) 1124 { 1125 ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 ); 1126 if (n==0) { 1127 ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 ); 1128 ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 ); 1129 } 1130 else { 1131 ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 ); 1132 ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 ); 1133 } 1134 ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 ); 1135 ASSIGN_3V( l->SpotDirection, 0.0, 0.0, -1.0 ); 1136 l->SpotExponent = 0.0; 1137 l->SpotCutoff = 180.0; 1138 l->_CosCutoff = 0.0; /* KW: -ve values not admitted */ 1139 l->ConstantAttenuation = 1.0; 1140 l->LinearAttenuation = 0.0; 1141 l->QuadraticAttenuation = 0.0; 1142 l->Enabled = GL_FALSE; 1143 } 1144 1145 1146 /** 1147 * Initialize the light model data structure. 1148 * 1149 * \param lm pointer to the gl_lightmodel structure to be initialized. 1150 */ 1151 static void 1152 init_lightmodel( struct gl_lightmodel *lm ) 1153 { 1154 ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F ); 1155 lm->LocalViewer = GL_FALSE; 1156 lm->TwoSide = GL_FALSE; 1157 lm->ColorControl = GL_SINGLE_COLOR; 1158 } 1159 1160 1161 /** 1162 * Initialize the material data structure. 1163 * 1164 * \param m pointer to the gl_material structure to be initialized. 1165 */ 1166 static void 1167 init_material( struct gl_material *m ) 1168 { 1169 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F ); 1170 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F ); 1171 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F ); 1172 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F ); 1173 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F ); 1174 ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F ); 1175 1176 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F ); 1177 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F ); 1178 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F ); 1179 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F ); 1180 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F ); 1181 ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F ); 1182 } 1183 1184 1185 /** 1186 * Initialize all lighting state for the given context. 1187 */ 1188 void 1189 _mesa_init_lighting( struct gl_context *ctx ) 1190 { 1191 GLuint i; 1192 1193 /* Lighting group */ 1194 ctx->Light._EnabledLights = 0; 1195 for (i = 0; i < MAX_LIGHTS; i++) { 1196 init_light( &ctx->Light.Light[i], i ); 1197 } 1198 1199 init_lightmodel( &ctx->Light.Model ); 1200 init_material( &ctx->Light.Material ); 1201 ctx->Light.ShadeModel = GL_SMOOTH; 1202 ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT; 1203 ctx->Light.Enabled = GL_FALSE; 1204 ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK; 1205 ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE; 1206 ctx->Light._ColorMaterialBitmask = _mesa_material_bitmask( ctx, 1207 GL_FRONT_AND_BACK, 1208 GL_AMBIENT_AND_DIFFUSE, ~0, 1209 NULL ); 1210 1211 ctx->Light.ColorMaterialEnabled = GL_FALSE; 1212 ctx->Light.ClampVertexColor = ctx->API == API_OPENGL_COMPAT; 1213 ctx->Light._ClampVertexColor = ctx->API == API_OPENGL_COMPAT; 1214 1215 /* Miscellaneous */ 1216 ctx->Light._NeedEyeCoords = GL_FALSE; 1217 ctx->_NeedEyeCoords = GL_FALSE; 1218 ctx->_ForceEyeCoords = GL_FALSE; 1219 ctx->_ModelViewInvScale = 1.0; 1220 } 1221