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