t_vb_lighttmp.h revision c0bcd2ca99609fe8b6e992e2277ef8612d46fdfe
1/* $Id: t_vb_lighttmp.h,v 1.3 2001/01/17 02:49:39 keithw 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 (stage->changed_inputs == 0) 665 return; 666 667 if ( CHECK_COLOR_MATERIAL(j) ) 668 gl_update_color_material( ctx, *CMcolor ); 669 670 if ( CHECK_MATERIAL(j) ) 671 gl_update_material( ctx, new_material[j], new_material_mask[j] ); 672 673 if ( CHECK_VALIDATE(j) ) 674 gl_validate_all_lighting_tables( ctx ); 675 676 do { 677 do { 678 GLfloat sum[2][3]; 679 680 COPY_3V(sum[0], ctx->Light._BaseColor[0]); 681 if (IDX & LIGHT_TWOSIDE) 682 COPY_3V(sum[1], ctx->Light._BaseColor[1]); 683 684 foreach (light, &ctx->Light.EnabledList) { 685 GLfloat n_dot_h, n_dot_VP, spec; 686 687 ACC_3V(sum[0], light->_MatAmbient[0]); 688 if (IDX & LIGHT_TWOSIDE) 689 ACC_3V(sum[1], light->_MatAmbient[1]); 690 691 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 692 693 if (n_dot_VP > 0.0F) { 694 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); 695 n_dot_h = DOT3(normal, light->_h_inf_norm); 696 if (n_dot_h > 0.0F) { 697 struct gl_shine_tab *tab = ctx->_ShineTable[0]; 698 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 699 ACC_SCALE_SCALAR_3V( sum[0], spec, 700 light->_MatSpecular[0]); 701 } 702 } 703 else if (IDX & LIGHT_TWOSIDE) { 704 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); 705 n_dot_h = -DOT3(normal, light->_h_inf_norm); 706 if (n_dot_h > 0.0F) { 707 struct gl_shine_tab *tab = ctx->_ShineTable[1]; 708 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 709 ACC_SCALE_SCALAR_3V( sum[1], spec, 710 light->_MatSpecular[1]); 711 } 712 } 713 } 714 715 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); 716 Fcolor[j][3] = sumA[0]; 717 718 if (IDX & LIGHT_TWOSIDE) { 719 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); 720 Bcolor[j][3] = sumA[1]; 721 } 722 723 j++; 724 STRIDE_F(normal, NSTRIDE); 725 } while (DO_ANOTHER_NORMAL(j)); 726 727 /* Reuse the shading results while there is no change to 728 * normal or material values. 729 */ 730 for ( ; REUSE_LIGHT_RESULTS(j) ; j++ ) { 731 COPY_CHAN4(Fcolor[j], Fcolor[j-1]); 732 if (IDX & LIGHT_TWOSIDE) 733 COPY_CHAN4(Bcolor[j], Bcolor[j-1]); 734 STRIDE_F(normal, NSTRIDE); 735 } 736 737 if ( CHECK_COLOR_MATERIAL(j) ) 738 gl_update_color_material( ctx, CMcolor[j] ); 739 740 if ( CHECK_MATERIAL(j) ) 741 gl_update_material( ctx, new_material[j], new_material_mask[j] ); 742 743 if ( CHECK_VALIDATE(j) ) 744 gl_validate_all_lighting_tables( ctx ); 745 746 } while (!CHECK_END_VB(j)); 747} 748 749 750 751 752 753/* 754 * Use current lighting/material settings to compute the color indexes 755 * for an array of vertices. 756 * Input: n - number of vertices to light 757 * side - 0=use front material, 1=use back material 758 * vertex - array of [n] vertex position in eye coordinates 759 * normal - array of [n] surface normal vector 760 * Output: indexResult - resulting array of [n] color indexes 761 */ 762static void TAG(light_ci)( GLcontext *ctx, 763 struct vertex_buffer *VB, 764 struct gl_pipeline_stage *stage, 765 GLvector4f *input ) 766{ 767 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 768 GLuint j; 769 GLuint vstride = input->stride; 770 const GLfloat *vertex = (GLfloat *) input->data; 771 GLuint nstride = VB->NormalPtr->stride; 772 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 773 GLubyte (*CMcolor)[4]; 774 GLuint CMstride; 775 GLuint *flags = VB->Flag; 776 GLuint *indexResult[2]; 777 struct gl_material (*new_material)[2] = VB->Material; 778 GLuint *new_material_mask = VB->MaterialMask; 779 GLuint nr = VB->Count; 780 781 (void) flags; 782 (void) nstride; 783 (void) vstride; 784 785 VB->IndexPtr[0] = &store->LitIndex[0]; 786 if (IDX & LIGHT_TWOSIDE) 787 VB->IndexPtr[1] = &store->LitIndex[1]; 788 789 if (stage->changed_inputs == 0) 790 return; 791 792 indexResult[0] = VB->IndexPtr[0]->data; 793 indexResult[1] = VB->IndexPtr[1]->data; 794 795 if (IDX & LIGHT_COLORMATERIAL) { 796 CMcolor = VB->ColorPtr[0]->data; 797 CMstride = VB->ColorPtr[0]->stride; 798 } 799 800 /* loop over vertices */ 801 for ( j=0 ; 802 j<nr ; 803 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE) 804 { 805 GLfloat diffuse[2], specular[2]; 806 GLuint side = 0; 807 struct gl_light *light; 808 809 if ( CHECK_COLOR_MATERIAL(j) ) 810 gl_update_color_material( ctx, (GLchan *)CMcolor[j] ); 811 812 if ( CHECK_MATERIAL(j) ) 813 gl_update_material( ctx, new_material[j], new_material_mask[j] ); 814 815 if ( CHECK_VALIDATE(j) ) 816 gl_validate_all_lighting_tables( ctx ); 817 818 diffuse[0] = specular[0] = 0.0F; 819 820 if ( IDX & LIGHT_TWOSIDE ) { 821 diffuse[1] = specular[1] = 0.0F; 822 } 823 824 /* Accumulate diffuse and specular from each light source */ 825 foreach (light, &ctx->Light.EnabledList) { 826 827 GLfloat attenuation = 1.0F; 828 GLfloat VP[3]; /* unit vector from vertex to light */ 829 GLfloat n_dot_VP; /* dot product of l and n */ 830 GLfloat *h, n_dot_h, correction = 1.0; 831 832 /* compute l and attenuation */ 833 if (!(light->_Flags & LIGHT_POSITIONAL)) { 834 /* directional light */ 835 COPY_3V(VP, light->_VP_inf_norm); 836 } 837 else { 838 GLfloat d; /* distance from vertex to light */ 839 840 SUB_3V(VP, light->_Position, vertex); 841 842 d = LEN_3FV( VP ); 843 if ( d > 1e-6) { 844 GLfloat invd = 1.0F / d; 845 SELF_SCALE_SCALAR_3V(VP, invd); 846 } 847 848 attenuation = 1.0F / (light->ConstantAttenuation + d * 849 (light->LinearAttenuation + d * 850 light->QuadraticAttenuation)); 851 852 /* spotlight attenuation */ 853 if (light->_Flags & LIGHT_SPOT) { 854 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 855 if (PV_dot_dir<light->_CosCutoff) { 856 continue; /* this light makes no contribution */ 857 } 858 else { 859 double x = PV_dot_dir * (EXP_TABLE_SIZE-1); 860 int k = (int) x; 861 GLfloat spot = (light->_SpotExpTable[k][0] 862 + (x-k)*light->_SpotExpTable[k][1]); 863 attenuation *= spot; 864 } 865 } 866 } 867 868 if (attenuation < 1e-3) 869 continue; /* this light makes no contribution */ 870 871 n_dot_VP = DOT3( normal, VP ); 872 873 /* which side are we lighting? */ 874 if (n_dot_VP < 0.0F) { 875 if (!(IDX & LIGHT_TWOSIDE)) 876 continue; 877 side = 1; 878 correction = -1; 879 n_dot_VP = -n_dot_VP; 880 } 881 882 /* accumulate diffuse term */ 883 diffuse[side] += n_dot_VP * light->_dli * attenuation; 884 885 /* specular term */ 886 if (ctx->Light.Model.LocalViewer) { 887 GLfloat v[3]; 888 COPY_3V(v, vertex); 889 NORMALIZE_3FV(v); 890 SUB_3V(VP, VP, v); /* h = VP + VPe */ 891 h = VP; 892 NORMALIZE_3FV(h); 893 } 894 else if (light->_Flags & LIGHT_POSITIONAL) { 895 h = VP; 896 ACC_3V(h, ctx->_EyeZDir); 897 NORMALIZE_3FV(h); 898 } 899 else { 900 h = light->_h_inf_norm; 901 } 902 903 n_dot_h = correction * DOT3(normal, h); 904 905 if (n_dot_h > 0.0F) 906 { 907 GLfloat spec_coef; 908 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 909 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef); 910 specular[side] += spec_coef * light->_sli * attenuation; 911 } 912 } /*loop over lights*/ 913 914 /* Now compute final color index */ 915 for (side = 0 ; side < NR_SIDES ; side++) { 916 struct gl_material *mat = &ctx->Light.Material[side]; 917 GLfloat index; 918 919 if (specular[side] > 1.0F) { 920 index = mat->SpecularIndex; 921 } 922 else { 923 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex; 924 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex; 925 926 index = mat->AmbientIndex 927 + diffuse[side] * (1.0F-specular[side]) * d_a 928 + specular[side] * s_a; 929 930 if (index > mat->SpecularIndex) { 931 index = mat->SpecularIndex; 932 } 933 } 934 indexResult[side][j] = (GLuint) (GLint) index; 935 } 936 } /*for vertex*/ 937 938 if ( CHECK_COLOR_MATERIAL(j) ) 939 gl_update_color_material( ctx, CMcolor[j] ); 940 941 if ( CHECK_MATERIAL(j) ) 942 gl_update_material( ctx, new_material[j], new_material_mask[j] ); 943 944 if ( CHECK_VALIDATE(j) ) 945 gl_validate_all_lighting_tables( ctx ); 946} 947 948 949 950static void TAG(init_light_tab)( void ) 951{ 952 _tnl_light_tab[IDX] = TAG(light_rgba); 953 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba); 954 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single); 955 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec); 956 _tnl_light_ci_tab[IDX] = TAG(light_ci); 957} 958 959 960#undef TAG 961#undef IDX 962#undef NR_SIDES 963#undef NSTRIDE 964#undef VSTRIDE 965#undef CHECK_MATERIAL 966#undef CHECK_END_VB 967#undef DO_ANOTHER_NORMAL 968#undef REUSE_LIGHT_RESULTS 969#undef CMSTRIDE 970#undef CHECK_COLOR_MATERIAL 971#undef CHECK_VALIDATE 972