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