t_vb_lighttmp.h revision ff56908e09c0351179478deb19677cf56eec1f64
1 2/* 3 * Mesa 3-D graphics library 4 * Version: 4.1 5 * 6 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * 26 * Authors: 27 * Brian Paul 28 * Keith Whitwell <keith@tungstengraphics.com> 29 */ 30 31 32#if (IDX & LIGHT_FLAGS) 33# define VSTRIDE (4 * sizeof(GLfloat)) 34# define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/ 35# define CHECK_MATERIAL(x) (flags[x] & VERT_BIT_MATERIAL) 36# define CHECK_END_VB(x) (flags[x] & VERT_BIT_END_VB) 37# if (IDX & LIGHT_COLORMATERIAL) 38# define CMSTRIDE STRIDE_F(CMcolor, CMstride) 39# define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0) 40# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL)) 41# define DO_ANOTHER_NORMAL(x) \ 42 ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) 43# define REUSE_LIGHT_RESULTS(x) \ 44 ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) 45# else 46# define CMSTRIDE (void)0 47# define CHECK_COLOR_MATERIAL(x) 0 48# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL)) 49# define DO_ANOTHER_NORMAL(x) \ 50 ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) 51# define REUSE_LIGHT_RESULTS(x) \ 52 ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) 53# endif 54#else 55# define VSTRIDE vstride 56# define NSTRIDE nstride 57# define CHECK_MATERIAL(x) 0 /* no materials on array paths */ 58# define CHECK_END_VB(XX) (XX >= nr) 59# if (IDX & LIGHT_COLORMATERIAL) 60# define CMSTRIDE STRIDE_F(CMcolor, CMstride) 61# define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */ 62# define CHECK_VALIDATE(x) (x < nr) 63# define DO_ANOTHER_NORMAL(x) 0 /* always stop to recalc colormat */ 64# else 65# define CMSTRIDE (void)0 66# define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */ 67# define CHECK_VALIDATE(x) (0) 68# define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */ 69# endif 70# define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */ 71#endif 72 73 74 75#if (IDX & LIGHT_TWOSIDE) 76# define NR_SIDES 2 77#else 78# define NR_SIDES 1 79#endif 80 81 82/* define TRACE if to trace lighting code */ 83/* #define TRACE 1 */ 84 85/* 86 * ctx is the current context 87 * VB is the vertex buffer 88 * stage is the lighting stage-private data 89 * input is the vector of eye or object-space vertex coordinates 90 */ 91static void TAG(light_rgba_spec)( GLcontext *ctx, 92 struct vertex_buffer *VB, 93 struct gl_pipeline_stage *stage, 94 GLvector4f *input ) 95{ 96 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 97 GLfloat (*base)[3] = ctx->Light._BaseColor; 98 GLchan sumA[2]; 99 GLuint j; 100 101 const GLuint vstride = input->stride; 102 const GLfloat *vertex = (GLfloat *)input->data; 103 const GLuint nstride = VB->NormalPtr->stride; 104 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 105 106 GLfloat *CMcolor; 107 GLuint CMstride; 108 109 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; 110 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; 111 GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr; 112 GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr; 113 114 const GLuint nr = VB->Count; 115 const GLuint *flags = VB->Flag; 116 struct gl_material *new_material = VB->Material; 117 const GLuint *new_material_mask = VB->MaterialMask; 118 119 (void) flags; 120 (void) nstride; 121 (void) vstride; 122 123#ifdef TRACE 124 fprintf(stderr, "%s\n", __FUNCTION__ ); 125#endif 126 127 if (IDX & LIGHT_COLORMATERIAL) { 128 if (VB->ColorPtr[0]->Type != GL_FLOAT || 129 VB->ColorPtr[0]->Size != 4) 130 import_color_material( ctx, stage ); 131 132 CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr; 133 CMstride = VB->ColorPtr[0]->StrideB; 134 } 135 136 VB->ColorPtr[0] = &store->LitColor[0]; 137 VB->SecondaryColorPtr[0] = &store->LitSecondary[0]; 138 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 139 140 if (IDX & LIGHT_TWOSIDE) { 141 VB->ColorPtr[1] = &store->LitColor[1]; 142 VB->SecondaryColorPtr[1] = &store->LitSecondary[1]; 143 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 144 } 145 146 /* Side-effects done, can we finish now? 147 */ 148 if (stage->changed_inputs == 0) 149 return; 150 151 for ( j=0 ; 152 j<nr ; 153 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE) 154 { 155 GLfloat sum[2][3], spec[2][3]; 156 struct gl_light *light; 157 158 if ( CHECK_COLOR_MATERIAL(j) ) 159 _mesa_update_color_material( ctx, CMcolor ); 160 161 if ( CHECK_MATERIAL(j) ) 162 update_materials( ctx, &new_material[j], new_material_mask[j] ); 163 164 if ( CHECK_VALIDATE(j) ) { 165 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 166 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 167 if (IDX & LIGHT_TWOSIDE) 168 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 169 } 170 171 COPY_3V(sum[0], base[0]); 172 ZERO_3V(spec[0]); 173 174 if (IDX & LIGHT_TWOSIDE) { 175 COPY_3V(sum[1], base[1]); 176 ZERO_3V(spec[1]); 177 } 178 179 /* Add contribution from each enabled light source */ 180 foreach (light, &ctx->Light.EnabledList) { 181 GLfloat n_dot_h; 182 GLfloat correction; 183 GLint side; 184 GLfloat contrib[3]; 185 GLfloat attenuation; 186 GLfloat VP[3]; /* unit vector from vertex to light */ 187 GLfloat n_dot_VP; /* n dot VP */ 188 GLfloat *h; 189 190 /* compute VP and attenuation */ 191 if (!(light->_Flags & LIGHT_POSITIONAL)) { 192 /* directional light */ 193 COPY_3V(VP, light->_VP_inf_norm); 194 attenuation = light->_VP_inf_spot_attenuation; 195 } 196 else { 197 GLfloat d; /* distance from vertex to light */ 198 199 SUB_3V(VP, light->_Position, vertex); 200 201 d = (GLfloat) LEN_3FV( VP ); 202 203 if (d > 1e-6) { 204 GLfloat invd = 1.0F / d; 205 SELF_SCALE_SCALAR_3V(VP, invd); 206 } 207 208 attenuation = 1.0F / (light->ConstantAttenuation + d * 209 (light->LinearAttenuation + d * 210 light->QuadraticAttenuation)); 211 212 /* spotlight attenuation */ 213 if (light->_Flags & LIGHT_SPOT) { 214 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 215 216 if (PV_dot_dir<light->_CosCutoff) { 217 continue; /* this light makes no contribution */ 218 } 219 else { 220 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 221 GLint k = (GLint) x; 222 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 223 + (x-k)*light->_SpotExpTable[k][1]); 224 attenuation *= spot; 225 } 226 } 227 } 228 229 if (attenuation < 1e-3) 230 continue; /* this light makes no contribution */ 231 232 /* Compute dot product or normal and vector from V to light pos */ 233 n_dot_VP = DOT3( normal, VP ); 234 235 /* Which side gets the diffuse & specular terms? */ 236 if (n_dot_VP < 0.0F) { 237 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 238 if (!(IDX & LIGHT_TWOSIDE)) { 239 continue; 240 } 241 side = 1; 242 correction = -1; 243 n_dot_VP = -n_dot_VP; 244 } 245 else { 246 if (IDX & LIGHT_TWOSIDE) { 247 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 248 } 249 side = 0; 250 correction = 1; 251 } 252 253 /* diffuse term */ 254 COPY_3V(contrib, light->_MatAmbient[side]); 255 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 256 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib ); 257 258 /* specular term - cannibalize VP... */ 259 if (ctx->Light.Model.LocalViewer) { 260 GLfloat v[3]; 261 COPY_3V(v, vertex); 262 NORMALIZE_3FV(v); 263 SUB_3V(VP, VP, v); /* h = VP + VPe */ 264 h = VP; 265 NORMALIZE_3FV(h); 266 } 267 else if (light->_Flags & LIGHT_POSITIONAL) { 268 h = VP; 269 ACC_3V(h, ctx->_EyeZDir); 270 NORMALIZE_3FV(h); 271 } 272 else { 273 h = light->_h_inf_norm; 274 } 275 276 n_dot_h = correction * DOT3(normal, h); 277 278 if (n_dot_h > 0.0F) { 279 GLfloat spec_coef; 280 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 281 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 282 283 if (spec_coef > 1.0e-10) { 284 spec_coef *= attenuation; 285 ACC_SCALE_SCALAR_3V( spec[side], spec_coef, 286 light->_MatSpecular[side]); 287 } 288 } 289 } /*loop over lights*/ 290 291 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); 292 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] ); 293 Fcolor[j][3] = sumA[0]; 294 295 if (IDX & LIGHT_TWOSIDE) { 296 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); 297 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] ); 298 Bcolor[j][3] = sumA[1]; 299 } 300 } 301} 302 303 304static void TAG(light_rgba)( GLcontext *ctx, 305 struct vertex_buffer *VB, 306 struct gl_pipeline_stage *stage, 307 GLvector4f *input ) 308{ 309 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 310 GLuint j; 311 312 GLfloat (*base)[3] = ctx->Light._BaseColor; 313 GLchan sumA[2]; 314 315 const GLuint vstride = input->stride; 316 const GLfloat *vertex = (GLfloat *) input->data; 317 const GLuint nstride = VB->NormalPtr->stride; 318 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 319 320 GLfloat *CMcolor; 321 GLuint CMstride; 322 323 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; 324 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; 325 GLchan (*color[2])[4]; 326 const GLuint *flags = VB->Flag; 327 328 struct gl_material *new_material = VB->Material; 329 const GLuint *new_material_mask = VB->MaterialMask; 330 const GLuint nr = VB->Count; 331 332#ifdef TRACE 333 fprintf(stderr, "%s\n", __FUNCTION__ ); 334#endif 335 336 (void) flags; 337 (void) nstride; 338 (void) vstride; 339 340 color[0] = Fcolor; 341 color[1] = Bcolor; 342 343 if (IDX & LIGHT_COLORMATERIAL) { 344 if (VB->ColorPtr[0]->Type != GL_FLOAT || 345 VB->ColorPtr[0]->Size != 4) 346 import_color_material( ctx, stage ); 347 348 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; 349 CMstride = VB->ColorPtr[0]->StrideB; 350 } 351 352 VB->ColorPtr[0] = &store->LitColor[0]; 353 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 354 355 if (IDX & LIGHT_TWOSIDE) { 356 VB->ColorPtr[1] = &store->LitColor[1]; 357 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 358 } 359 360 if (stage->changed_inputs == 0) 361 return; 362 363 for ( j=0 ; 364 j<nr ; 365 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE) 366 { 367 GLfloat sum[2][3]; 368 struct gl_light *light; 369 370 if ( CHECK_COLOR_MATERIAL(j) ) 371 _mesa_update_color_material( ctx, CMcolor ); 372 373 if ( CHECK_MATERIAL(j) ) 374 update_materials( ctx, &new_material[j], new_material_mask[j] ); 375 376 if ( CHECK_VALIDATE(j) ) { 377 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 378 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 379 if (IDX & LIGHT_TWOSIDE) 380 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 381 } 382 383 COPY_3V(sum[0], base[0]); 384 385 if ( IDX & LIGHT_TWOSIDE ) 386 COPY_3V(sum[1], base[1]); 387 388 /* Add contribution from each enabled light source */ 389 foreach (light, &ctx->Light.EnabledList) { 390 391 GLfloat n_dot_h; 392 GLfloat correction; 393 GLint side; 394 GLfloat contrib[3]; 395 GLfloat attenuation = 1.0; 396 GLfloat VP[3]; /* unit vector from vertex to light */ 397 GLfloat n_dot_VP; /* n dot VP */ 398 GLfloat *h; 399 400 /* compute VP and attenuation */ 401 if (!(light->_Flags & LIGHT_POSITIONAL)) { 402 /* directional light */ 403 COPY_3V(VP, light->_VP_inf_norm); 404 attenuation = light->_VP_inf_spot_attenuation; 405 } 406 else { 407 GLfloat d; /* distance from vertex to light */ 408 409 410 SUB_3V(VP, light->_Position, vertex); 411 412 d = (GLfloat) LEN_3FV( VP ); 413 414 if ( d > 1e-6) { 415 GLfloat invd = 1.0F / d; 416 SELF_SCALE_SCALAR_3V(VP, invd); 417 } 418 419 attenuation = 1.0F / (light->ConstantAttenuation + d * 420 (light->LinearAttenuation + d * 421 light->QuadraticAttenuation)); 422 423 /* spotlight attenuation */ 424 if (light->_Flags & LIGHT_SPOT) { 425 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 426 427 if (PV_dot_dir<light->_CosCutoff) { 428 continue; /* this light makes no contribution */ 429 } 430 else { 431 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 432 GLint k = (GLint) x; 433 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 434 + (x-k)*light->_SpotExpTable[k][1]); 435 attenuation *= spot; 436 } 437 } 438 } 439 440 if (attenuation < 1e-3) 441 continue; /* this light makes no contribution */ 442 443 /* Compute dot product or normal and vector from V to light pos */ 444 n_dot_VP = DOT3( normal, VP ); 445 446 /* which side are we lighting? */ 447 if (n_dot_VP < 0.0F) { 448 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 449 450 if (!(IDX & LIGHT_TWOSIDE)) 451 continue; 452 453 side = 1; 454 correction = -1; 455 n_dot_VP = -n_dot_VP; 456 } 457 else { 458 if (IDX & LIGHT_TWOSIDE) { 459 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 460 } 461 side = 0; 462 correction = 1; 463 } 464 465 COPY_3V(contrib, light->_MatAmbient[side]); 466 467 /* diffuse term */ 468 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 469 470 /* specular term - cannibalize VP... */ 471 { 472 if (ctx->Light.Model.LocalViewer) { 473 GLfloat v[3]; 474 COPY_3V(v, vertex); 475 NORMALIZE_3FV(v); 476 SUB_3V(VP, VP, v); /* h = VP + VPe */ 477 h = VP; 478 NORMALIZE_3FV(h); 479 } 480 else if (light->_Flags & LIGHT_POSITIONAL) { 481 h = VP; 482 ACC_3V(h, ctx->_EyeZDir); 483 NORMALIZE_3FV(h); 484 } 485 else { 486 h = light->_h_inf_norm; 487 } 488 489 n_dot_h = correction * DOT3(normal, h); 490 491 if (n_dot_h > 0.0F) 492 { 493 GLfloat spec_coef; 494 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 495 496 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 497 498 ACC_SCALE_SCALAR_3V( contrib, spec_coef, 499 light->_MatSpecular[side]); 500 } 501 } 502 503 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); 504 } 505 506 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); 507 Fcolor[j][3] = sumA[0]; 508 509 if (IDX & LIGHT_TWOSIDE) { 510 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); 511 Bcolor[j][3] = sumA[1]; 512 } 513 } 514} 515 516 517 518 519/* As below, but with just a single light. 520 */ 521static void TAG(light_fast_rgba_single)( GLcontext *ctx, 522 struct vertex_buffer *VB, 523 struct gl_pipeline_stage *stage, 524 GLvector4f *input ) 525 526{ 527 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 528 const GLuint nstride = VB->NormalPtr->stride; 529 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 530 GLfloat *CMcolor; 531 GLuint CMstride; 532 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; 533 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; 534 const struct gl_light *light = ctx->Light.EnabledList.next; 535 const GLuint *flags = VB->Flag; 536 GLchan basechan[2][4]; 537 GLuint j = 0; 538 struct gl_material *new_material = VB->Material; 539 const GLuint *new_material_mask = VB->MaterialMask; 540 GLfloat base[2][3]; 541 const GLuint nr = VB->Count; 542 543#ifdef TRACE 544 fprintf(stderr, "%s\n", __FUNCTION__ ); 545#endif 546 547 (void) input; /* doesn't refer to Eye or Obj */ 548 (void) flags; 549 (void) nr; 550 (void) nstride; 551 552 if (IDX & LIGHT_COLORMATERIAL) { 553 if (VB->ColorPtr[0]->Type != GL_FLOAT || 554 VB->ColorPtr[0]->Size != 4) 555 import_color_material( ctx, stage ); 556 557 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; 558 CMstride = VB->ColorPtr[0]->StrideB; 559 } 560 561 VB->ColorPtr[0] = &store->LitColor[0]; 562 if (IDX & LIGHT_TWOSIDE) 563 VB->ColorPtr[1] = &store->LitColor[1]; 564 565 if (stage->changed_inputs == 0) 566 return; 567 568 do { 569 570 if ( CHECK_COLOR_MATERIAL(j) ) { 571 _mesa_update_color_material( ctx, CMcolor ); 572 } 573 574 if ( CHECK_MATERIAL(j) ) 575 update_materials( ctx, &new_material[j], new_material_mask[j] ); 576 577 if ( CHECK_VALIDATE(j) ) 578 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 579 580 581 /* No attenuation, so incoporate _MatAmbient into base color. 582 */ 583 COPY_3V(base[0], light->_MatAmbient[0]); 584 ACC_3V(base[0], ctx->Light._BaseColor[0] ); 585 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] ); 586 UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3], 587 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 588 589 if (IDX & LIGHT_TWOSIDE) { 590 COPY_3V(base[1], light->_MatAmbient[1]); 591 ACC_3V(base[1], ctx->Light._BaseColor[1]); 592 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]); 593 UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3], 594 ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 595 } 596 597 do { 598 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm); 599 600 if (n_dot_VP < 0.0F) { 601 if (IDX & LIGHT_TWOSIDE) { 602 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); 603 GLfloat sum[3]; 604 COPY_3V(sum, base[1]); 605 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); 606 if (n_dot_h > 0.0F) { 607 GLfloat spec; 608 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); 609 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); 610 } 611 UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum ); 612 Bcolor[j][3] = basechan[1][3]; 613 } 614 COPY_CHAN4(Fcolor[j], basechan[0]); 615 } 616 else { 617 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); 618 GLfloat sum[3]; 619 COPY_3V(sum, base[0]); 620 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); 621 if (n_dot_h > 0.0F) { 622 GLfloat spec; 623 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); 624 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); 625 626 } 627 UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum ); 628 Fcolor[j][3] = basechan[0][3]; 629 if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]); 630 } 631 632 j++; 633 CMSTRIDE; 634 STRIDE_F(normal, NSTRIDE); 635 } while (DO_ANOTHER_NORMAL(j)); 636 637 638 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE)) 639 { 640 COPY_CHAN4(Fcolor[j], Fcolor[j-1]); 641 if (IDX & LIGHT_TWOSIDE) 642 COPY_CHAN4(Bcolor[j], Bcolor[j-1]); 643 } 644 645 } while (!CHECK_END_VB(j)); 646} 647 648 649/* Light infinite lights 650 */ 651static void TAG(light_fast_rgba)( GLcontext *ctx, 652 struct vertex_buffer *VB, 653 struct gl_pipeline_stage *stage, 654 GLvector4f *input ) 655{ 656 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 657 GLchan sumA[2]; 658 const GLuint nstride = VB->NormalPtr->stride; 659 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 660 GLfloat *CMcolor; 661 GLuint CMstride; 662 GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; 663 GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; 664 const GLuint *flags = VB->Flag; 665 GLuint j = 0; 666 struct gl_material *new_material = VB->Material; 667 GLuint *new_material_mask = VB->MaterialMask; 668 const GLuint nr = VB->Count; 669 const struct gl_light *light; 670 671#ifdef TRACE 672 fprintf(stderr, "%s\n", __FUNCTION__ ); 673#endif 674 675 (void) flags; 676 (void) input; 677 (void) nr; 678 (void) nstride; 679 680 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 681 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 682 683 if (IDX & LIGHT_COLORMATERIAL) { 684 if (VB->ColorPtr[0]->Type != GL_FLOAT || 685 VB->ColorPtr[0]->Size != 4) 686 import_color_material( ctx, stage ); 687 688 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; 689 CMstride = VB->ColorPtr[0]->StrideB; 690 } 691 692 VB->ColorPtr[0] = &store->LitColor[0]; 693 if (IDX & LIGHT_TWOSIDE) 694 VB->ColorPtr[1] = &store->LitColor[1]; 695 696 if (stage->changed_inputs == 0) 697 return; 698 699 do { 700 do { 701 GLfloat sum[2][3]; 702 703 if ( CHECK_COLOR_MATERIAL(j) ) 704 _mesa_update_color_material( ctx, CMcolor ); 705 706 if ( CHECK_MATERIAL(j) ) 707 update_materials( ctx, &new_material[j], new_material_mask[j] ); 708 709 if ( CHECK_VALIDATE(j) ) { 710 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 711 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); 712 if (IDX & LIGHT_TWOSIDE) 713 UNCLAMPED_FLOAT_TO_CHAN(sumA[1], 714 ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); 715 } 716 717 718 COPY_3V(sum[0], ctx->Light._BaseColor[0]); 719 if (IDX & LIGHT_TWOSIDE) 720 COPY_3V(sum[1], ctx->Light._BaseColor[1]); 721 722 foreach (light, &ctx->Light.EnabledList) { 723 GLfloat n_dot_h, n_dot_VP, spec; 724 725 ACC_3V(sum[0], light->_MatAmbient[0]); 726 if (IDX & LIGHT_TWOSIDE) 727 ACC_3V(sum[1], light->_MatAmbient[1]); 728 729 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 730 731 if (n_dot_VP > 0.0F) { 732 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); 733 n_dot_h = DOT3(normal, light->_h_inf_norm); 734 if (n_dot_h > 0.0F) { 735 struct gl_shine_tab *tab = ctx->_ShineTable[0]; 736 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 737 ACC_SCALE_SCALAR_3V( sum[0], spec, 738 light->_MatSpecular[0]); 739 } 740 } 741 else if (IDX & LIGHT_TWOSIDE) { 742 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); 743 n_dot_h = -DOT3(normal, light->_h_inf_norm); 744 if (n_dot_h > 0.0F) { 745 struct gl_shine_tab *tab = ctx->_ShineTable[1]; 746 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 747 ACC_SCALE_SCALAR_3V( sum[1], spec, 748 light->_MatSpecular[1]); 749 } 750 } 751 } 752 753 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); 754 Fcolor[j][3] = sumA[0]; 755 756 if (IDX & LIGHT_TWOSIDE) { 757 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); 758 Bcolor[j][3] = sumA[1]; 759 } 760 761 j++; 762 CMSTRIDE; 763 STRIDE_F(normal, NSTRIDE); 764 } while (DO_ANOTHER_NORMAL(j)); 765 766 /* Reuse the shading results while there is no change to 767 * normal or material values. 768 */ 769 for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE)) 770 { 771 COPY_CHAN4(Fcolor[j], Fcolor[j-1]); 772 if (IDX & LIGHT_TWOSIDE) 773 COPY_CHAN4(Bcolor[j], Bcolor[j-1]); 774 } 775 776 } while (!CHECK_END_VB(j)); 777} 778 779 780 781 782 783/* 784 * Use current lighting/material settings to compute the color indexes 785 * for an array of vertices. 786 * Input: n - number of vertices to light 787 * side - 0=use front material, 1=use back material 788 * vertex - array of [n] vertex position in eye coordinates 789 * normal - array of [n] surface normal vector 790 * Output: indexResult - resulting array of [n] color indexes 791 */ 792static void TAG(light_ci)( GLcontext *ctx, 793 struct vertex_buffer *VB, 794 struct gl_pipeline_stage *stage, 795 GLvector4f *input ) 796{ 797 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 798 GLuint j; 799 const GLuint vstride = input->stride; 800 const GLfloat *vertex = (GLfloat *) input->data; 801 const GLuint nstride = VB->NormalPtr->stride; 802 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 803 GLfloat *CMcolor; 804 GLuint CMstride; 805 const GLuint *flags = VB->Flag; 806 GLuint *indexResult[2]; 807 struct gl_material *new_material = VB->Material; 808 GLuint *new_material_mask = VB->MaterialMask; 809 const GLuint nr = VB->Count; 810 811#ifdef TRACE 812 fprintf(stderr, "%s\n", __FUNCTION__ ); 813#endif 814 815 (void) flags; 816 (void) nstride; 817 (void) vstride; 818 819 VB->IndexPtr[0] = &store->LitIndex[0]; 820 if (IDX & LIGHT_TWOSIDE) 821 VB->IndexPtr[1] = &store->LitIndex[1]; 822 823 if (stage->changed_inputs == 0) 824 return; 825 826 indexResult[0] = VB->IndexPtr[0]->data; 827 if (IDX & LIGHT_TWOSIDE) 828 indexResult[1] = VB->IndexPtr[1]->data; 829 830 if (IDX & LIGHT_COLORMATERIAL) { 831 if (VB->ColorPtr[0]->Type != GL_FLOAT || 832 VB->ColorPtr[0]->Size != 4) 833 import_color_material( ctx, stage ); 834 835 CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; 836 CMstride = VB->ColorPtr[0]->StrideB; 837 } 838 839 /* loop over vertices */ 840 for ( j=0 ; 841 j<nr ; 842 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE) 843 { 844 GLfloat diffuse[2], specular[2]; 845 GLuint side = 0; 846 struct gl_light *light; 847 848 if ( CHECK_COLOR_MATERIAL(j) ) 849 _mesa_update_color_material( ctx, CMcolor ); 850 851 if ( CHECK_MATERIAL(j) ) 852 update_materials( ctx, &new_material[j], new_material_mask[j] ); 853 854 if ( CHECK_VALIDATE(j) ) 855 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); 856 857 diffuse[0] = specular[0] = 0.0F; 858 859 if ( IDX & LIGHT_TWOSIDE ) { 860 diffuse[1] = specular[1] = 0.0F; 861 } 862 863 /* Accumulate diffuse and specular from each light source */ 864 foreach (light, &ctx->Light.EnabledList) { 865 866 GLfloat attenuation = 1.0F; 867 GLfloat VP[3]; /* unit vector from vertex to light */ 868 GLfloat n_dot_VP; /* dot product of l and n */ 869 GLfloat *h, n_dot_h, correction = 1.0; 870 871 /* compute l and attenuation */ 872 if (!(light->_Flags & LIGHT_POSITIONAL)) { 873 /* directional light */ 874 COPY_3V(VP, light->_VP_inf_norm); 875 } 876 else { 877 GLfloat d; /* distance from vertex to light */ 878 879 SUB_3V(VP, light->_Position, vertex); 880 881 d = (GLfloat) LEN_3FV( VP ); 882 if ( d > 1e-6) { 883 GLfloat invd = 1.0F / d; 884 SELF_SCALE_SCALAR_3V(VP, invd); 885 } 886 887 attenuation = 1.0F / (light->ConstantAttenuation + d * 888 (light->LinearAttenuation + d * 889 light->QuadraticAttenuation)); 890 891 /* spotlight attenuation */ 892 if (light->_Flags & LIGHT_SPOT) { 893 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 894 if (PV_dot_dir < light->_CosCutoff) { 895 continue; /* this light makes no contribution */ 896 } 897 else { 898 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 899 GLint k = (GLint) x; 900 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 901 + (x-k)*light->_SpotExpTable[k][1]); 902 attenuation *= spot; 903 } 904 } 905 } 906 907 if (attenuation < 1e-3) 908 continue; /* this light makes no contribution */ 909 910 n_dot_VP = DOT3( normal, VP ); 911 912 /* which side are we lighting? */ 913 if (n_dot_VP < 0.0F) { 914 if (!(IDX & LIGHT_TWOSIDE)) 915 continue; 916 side = 1; 917 correction = -1; 918 n_dot_VP = -n_dot_VP; 919 } 920 921 /* accumulate diffuse term */ 922 diffuse[side] += n_dot_VP * light->_dli * attenuation; 923 924 /* specular term */ 925 if (ctx->Light.Model.LocalViewer) { 926 GLfloat v[3]; 927 COPY_3V(v, vertex); 928 NORMALIZE_3FV(v); 929 SUB_3V(VP, VP, v); /* h = VP + VPe */ 930 h = VP; 931 NORMALIZE_3FV(h); 932 } 933 else if (light->_Flags & LIGHT_POSITIONAL) { 934 h = VP; 935 /* Strangely, disabling this addition fixes a conformance 936 * problem. If this code is enabled, l_sed.c fails. 937 */ 938 /*ACC_3V(h, ctx->_EyeZDir);*/ 939 NORMALIZE_3FV(h); 940 } 941 else { 942 h = light->_h_inf_norm; 943 } 944 945 n_dot_h = correction * DOT3(normal, h); 946 if (n_dot_h > 0.0F) { 947 GLfloat spec_coef; 948 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 949 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef); 950 specular[side] += spec_coef * light->_sli * attenuation; 951 } 952 } /*loop over lights*/ 953 954 /* Now compute final color index */ 955 for (side = 0 ; side < NR_SIDES ; side++) { 956 const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side]; 957 GLfloat index; 958 959 if (specular[side] > 1.0F) { 960 index = ind[MAT_INDEX_SPECULAR]; 961 } 962 else { 963 GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT]; 964 GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT]; 965 GLfloat i = (ind[MAT_INDEX_AMBIENT] 966 + diffuse[side] * (1.0F-specular[side]) * d_a 967 + specular[side] * s_a); 968 if (i > ind[MAT_INDEX_SPECULAR]) { 969 i = ind[MAT_INDEX_SPECULAR]; 970 } 971 } 972 indexResult[side][j] = (GLuint) (GLint) index; 973 } 974 } /*for vertex*/ 975} 976 977 978 979static void TAG(init_light_tab)( void ) 980{ 981 _tnl_light_tab[IDX] = TAG(light_rgba); 982 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba); 983 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single); 984 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec); 985 _tnl_light_ci_tab[IDX] = TAG(light_ci); 986} 987 988 989#undef TAG 990#undef IDX 991#undef NR_SIDES 992#undef NSTRIDE 993#undef VSTRIDE 994#undef CHECK_MATERIAL 995#undef CHECK_END_VB 996#undef DO_ANOTHER_NORMAL 997#undef REUSE_LIGHT_RESULTS 998#undef CMSTRIDE 999#undef CHECK_COLOR_MATERIAL 1000#undef CHECK_VALIDATE 1001